http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAffinityTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAffinityTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAffinityTest.cs new file mode 100644 index 0000000..beb2c0f --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheAffinityTest.cs @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using Apache.Ignite.Core.Cache; + using Apache.Ignite.Core.Cluster; + using Apache.Ignite.Core.Impl; + using Apache.Ignite.Core.Portable; + using NUnit.Framework; + + /// <summary> + /// Affinity key tests. + /// </summary> + public class CacheAffinityTest + { + /// <summary> + /// + /// </summary> + [TestFixtureSetUp] + public virtual void StartGrids() + { + TestUtils.KillProcesses(); + + IgniteConfigurationEx cfg = new IgniteConfigurationEx(); + + cfg.JvmClasspath = TestUtils.CreateTestClasspath(); + cfg.JvmOptions = TestUtils.TestJavaOptions(); + cfg.SpringConfigUrl = "config\\native-client-test-cache-affinity.xml"; + + for (int i = 0; i < 3; i++) + { + cfg.GridName = "grid-" + i; + + Ignition.Start(cfg); + } + } + + /// <summary> + /// Tear-down routine. + /// </summary> + [TestFixtureTearDown] + public virtual void StopGrids() + { + for (int i = 0; i < 3; i++) + Ignition.Stop("grid-" + i, true); + } + + /// <summary> + /// Test affinity key. + /// </summary> + [Test] + public void TestAffinity() + { + IIgnite g = Ignition.GetIgnite("grid-0"); + + ICacheAffinity aff = g.Affinity(null); + + IClusterNode node = aff.MapKeyToNode(new AffinityTestKey(0, 1)); + + for (int i = 0; i < 10; i++) + Assert.AreEqual(node.Id, aff.MapKeyToNode(new AffinityTestKey(i, 1)).Id); + } + + /// <summary> + /// Test affinity with portable flag. + /// </summary> + [Test] + public void TestAffinityPortable() + { + IIgnite g = Ignition.GetIgnite("grid-0"); + + ICacheAffinity aff = g.Affinity(null); + + IPortableObject affKey = g.Portables().ToPortable<IPortableObject>(new AffinityTestKey(0, 1)); + + IClusterNode node = aff.MapKeyToNode(affKey); + + for (int i = 0; i < 10; i++) + { + IPortableObject otherAffKey = + g.Portables().ToPortable<IPortableObject>(new AffinityTestKey(i, 1)); + + Assert.AreEqual(node.Id, aff.MapKeyToNode(otherAffKey).Id); + } + } + + /// <summary> + /// Affinity key. + /// </summary> + public class AffinityTestKey + { + /** ID. */ + private int _id; + + /** Affinity key. */ + private int _affKey; + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="id">ID.</param> + /// <param name="affKey">Affinity key.</param> + public AffinityTestKey(int id, int affKey) + { + _id = id; + _affKey = affKey; + } + + /** <inheritdoc /> */ + public override bool Equals(object obj) + { + AffinityTestKey other = obj as AffinityTestKey; + + return other != null && _id == other._id; + } + + /** <inheritdoc /> */ + public override int GetHashCode() + { + return _id; + } + } + } +}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheDynamicStartTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheDynamicStartTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheDynamicStartTest.cs new file mode 100644 index 0000000..210d80c --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheDynamicStartTest.cs @@ -0,0 +1,281 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using System; + using System.Collections.Generic; + using Apache.Ignite.Core.Cache; + using Apache.Ignite.Core.Impl; + using Apache.Ignite.Core.Portable; + using Apache.Ignite.Core.Tests.Query; + using NUnit.Framework; + + /// <summary> + /// Tests for dynamic a cache start. + /// </summary> + public class CacheDynamicStartTest + { + /** Grid name: data. */ + private const string GridData = "d"; + + /** Grid name: data, no configuration. */ + private const string GridDataNoCfg = "dnc"; + + /** Grid name: client. */ + private const string GridClient = "c"; + + /** Cache name: partitioned, transactional. */ + private const string CacheTx = "p"; + + /** Cache name: atomic. */ + private const string CacheAtomic = "pa"; + + /** Cache name: dummy. */ + private const string CacheDummy = "dummy"; + + /// <summary> + /// Set up routine. + /// </summary> + [SetUp] + public void SetUp() + { + TestUtils.KillProcesses(); + + Ignition.Start(CreateConfiguration(GridData, @"config/dynamic/dynamic-data.xml")); + Ignition.Start(CreateConfiguration(GridDataNoCfg, @"config/dynamic/dynamic-data-no-cfg.xml")); + Ignition.Start(CreateConfiguration(GridClient, @"config/dynamic/dynamic-client.xml")); + } + + /// <summary> + /// Tear down routine. + /// </summary> + [TearDown] + public void StopGrids() + { + Ignition.Stop(GridData, true); + Ignition.Stop(GridDataNoCfg, true); + Ignition.Stop(GridClient, true); + } + + /// <summary> + /// Create configuration. + /// </summary> + /// <param name="name">Grid name.</param> + /// <param name="springCfg">Spring configuration.</param> + /// <returns>Configuration.</returns> + private static IgniteConfigurationEx CreateConfiguration(string name, string springCfg) + { + IgniteConfigurationEx cfg = new IgniteConfigurationEx(); + + PortableConfiguration portCfg = new PortableConfiguration(); + + ICollection<PortableTypeConfiguration> portTypeCfgs = new List<PortableTypeConfiguration>(); + + portTypeCfgs.Add(new PortableTypeConfiguration(typeof(DynamicTestKey))); + portTypeCfgs.Add(new PortableTypeConfiguration(typeof(DynamicTestValue))); + + portCfg.TypeConfigurations = portTypeCfgs; + + cfg.GridName = name; + cfg.PortableConfiguration = portCfg; + cfg.JvmClasspath = TestUtils.CreateTestClasspath(); + cfg.JvmOptions = TestUtils.TestJavaOptions(); + cfg.SpringConfigUrl = springCfg; + + return cfg; + } + + /// <summary> + /// Try getting not configured cache. + /// </summary> + [Test] + public void TestNoStarted() + { + Assert.Throws<ArgumentException>(() => + { + Ignition.GetIgnite(GridData).Cache<CacheTestKey, PortablePerson>(CacheDummy); + }); + + Assert.Throws<ArgumentException>(() => + { + Ignition.GetIgnite(GridDataNoCfg).Cache<CacheTestKey, PortablePerson>(CacheDummy); + }); + + Assert.Throws<ArgumentException>(() => + { + Ignition.GetIgnite(GridClient).Cache<CacheTestKey, PortablePerson>(CacheDummy); + }); + } + + /// <summary> + /// Test TX cache. + /// </summary> + [Test] + public void TestTransactional() + { + Check(CacheTx); + } + + /// <summary> + /// Test ATOMIC cache. + /// </summary> + [Test] + public void TestAtomic() + { + Check(CacheAtomic); + } + + /// <summary> + /// Check routine. + /// </summary> + /// <param name="cacheName">Cache name.</param> + private void Check(string cacheName) + { + ICache<DynamicTestKey, DynamicTestValue> cacheData = + Ignition.GetIgnite(GridData).Cache<DynamicTestKey, DynamicTestValue>(cacheName); + + ICache<DynamicTestKey, DynamicTestValue> cacheDataNoCfg = + Ignition.GetIgnite(GridDataNoCfg).Cache<DynamicTestKey, DynamicTestValue>(cacheName); + + ICache<DynamicTestKey, DynamicTestValue> cacheClient = + Ignition.GetIgnite(GridClient).Cache<DynamicTestKey, DynamicTestValue>(cacheName); + + DynamicTestKey key1 = new DynamicTestKey(1); + DynamicTestKey key2 = new DynamicTestKey(2); + DynamicTestKey key3 = new DynamicTestKey(3); + + DynamicTestValue val1 = new DynamicTestValue(1); + DynamicTestValue val2 = new DynamicTestValue(2); + DynamicTestValue val3 = new DynamicTestValue(3); + + cacheData.Put(key1, val1); + Assert.AreEqual(val1, cacheData.Get(key1)); + Assert.AreEqual(val1, cacheDataNoCfg.Get(key1)); + Assert.AreEqual(val1, cacheClient.Get(key1)); + + cacheDataNoCfg.Put(key2, val2); + Assert.AreEqual(val2, cacheData.Get(key2)); + Assert.AreEqual(val2, cacheDataNoCfg.Get(key2)); + Assert.AreEqual(val2, cacheClient.Get(key2)); + + cacheClient.Put(key3, val3); + Assert.AreEqual(val3, cacheData.Get(key3)); + Assert.AreEqual(val3, cacheDataNoCfg.Get(key3)); + Assert.AreEqual(val3, cacheClient.Get(key3)); + + for (int i = 0; i < 10000; i++) + cacheClient.Put(new DynamicTestKey(i), new DynamicTestValue(1)); + + int sizeClient = cacheClient.LocalSize(); + + Assert.AreEqual(0, sizeClient); + } + } + + /// <summary> + /// Key for dynamic cache start tests. + /// </summary> + class DynamicTestKey + { + /// <summary> + /// Default constructor. + /// </summary> + public DynamicTestKey() + { + // No-op. + } + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="id">ID.</param> + public DynamicTestKey(int id) + { + Id = id; + } + + /// <summary> + /// ID. + /// </summary> + public int Id + { + get; + set; + } + + /** <inheritdoc /> */ + public override bool Equals(object obj) + { + DynamicTestKey other = obj as DynamicTestKey; + + return other != null && Id == other.Id; + } + + /** <inheritdoc /> */ + public override int GetHashCode() + { + return Id; + } + } + + /// <summary> + /// Value for dynamic cache start tests. + /// </summary> + class DynamicTestValue + { + /// <summary> + /// Default constructor. + /// </summary> + public DynamicTestValue() + { + // No-op. + } + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="id">ID.</param> + public DynamicTestValue(int id) + { + Id = id; + } + + /// <summary> + /// ID. + /// </summary> + public int Id + { + get; + set; + } + + /** <inheritdoc /> */ + public override bool Equals(object obj) + { + DynamicTestValue other = obj as DynamicTestValue; + + return other != null && Id == other.Id; + } + + /** <inheritdoc /> */ + public override int GetHashCode() + { + return Id; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheEntryTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheEntryTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheEntryTest.cs new file mode 100644 index 0000000..8464b8e --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheEntryTest.cs @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using System.Collections.Generic; + using Apache.Ignite.Core.Impl.Cache; + using NUnit.Framework; + + /// <summary> + /// <see cref="CacheEntry{TK,TV}"/> tests. + /// </summary> + public class CacheEntryTest + { + /// <summary> + /// Tests equality members. + /// </summary> + [Test] + public void TestEquality() + { + var entry1 = new CacheEntry<int, int>(1, 2); + var entry2 = new CacheEntry<int, int>(1, 2); + var entry3 = new CacheEntry<int, int>(1, 3); + + Assert.AreEqual(entry1, entry2); + Assert.AreNotEqual(entry1, entry3); + + var boxedEntry1 = (object) entry1; + var boxedEntry2 = (object) entry2; + var boxedEntry3 = (object) entry3; + + Assert.IsFalse(ReferenceEquals(boxedEntry1, boxedEntry2)); + + Assert.AreEqual(boxedEntry1, boxedEntry2); + Assert.AreNotEqual(boxedEntry1, boxedEntry3); + } + + /// <summary> + /// Tests with hash data structures. + /// </summary> + [Test] + public void TestHashCode() + { + var entry1 = new CacheEntry<int, int>(1, 2); + var entry2 = new CacheEntry<int, int>(1, 2); + var entry3 = new CacheEntry<int, int>(1, 3); + + var set = new HashSet<object> {entry1}; + + Assert.IsTrue(set.Contains(entry1)); + Assert.IsTrue(set.Contains(entry2)); + Assert.IsFalse(set.Contains(entry3)); + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheForkedTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheForkedTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheForkedTest.cs new file mode 100644 index 0000000..04aff5f --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheForkedTest.cs @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using System.IO; + using Apache.Ignite.Core.Tests.Process; + using NUnit.Framework; + + /// <summary> + /// Tests cache with a standalone process. + /// </summary> + [Ignore("IGNITE-1367")] + public class CacheForkedTest + { + /** */ + private IIgnite _grid; + + /// <summary> + /// Set up. + /// </summary> + [TestFixtureSetUp] + public void SetUp() + { + const string springConfigUrl = "config\\compute\\compute-grid1.xml"; + + // ReSharper disable once UnusedVariable + var proc = new IgniteProcess( + "-jvmClasspath=" + TestUtils.CreateTestClasspath(), + "-springConfigUrl=" + Path.GetFullPath(springConfigUrl), + "-J-ea", + "-J-Xcheck:jni", + "-J-Xms512m", + "-J-Xmx512m", + "-J-DIGNITE_QUIET=false" + ); + + _grid = Ignition.Start(new IgniteConfiguration + { + JvmClasspath = TestUtils.CreateTestClasspath(), + JvmOptions = TestUtils.TestJavaOptions(), + SpringConfigUrl = springConfigUrl + }); + + Assert.IsTrue(_grid.WaitTopology(2, 30000)); + } + + /// <summary> + /// Tear down. + /// </summary> + [TestFixtureTearDown] + public void TearDown() + { + IgniteProcess.KillAll(); + + Ignition.StopAll(true); + } + + /// <summary> + /// Tests cache clear. + /// </summary> + [Test] + public void TestClearCache() + { + _grid.Cache<object, object>(null).Clear(); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheLocalAtomicTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheLocalAtomicTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheLocalAtomicTest.cs new file mode 100644 index 0000000..b60c254 --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheLocalAtomicTest.cs @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + public class CacheLocalAtomicTest : CacheAbstractTest + { + protected override int CachePartitions() + { + return 1; + } + + protected override int GridCount() + { + return 1; + } + + protected override string CacheName() + { + return "local_atomic"; + } + + protected override bool NearEnabled() + { + return false; + } + + protected override bool TxEnabled() + { + return false; + } + + protected override bool LocalCache() + { + return true; + } + + protected override int Backups() + { + return 0; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheLocalTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheLocalTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheLocalTest.cs new file mode 100644 index 0000000..02cb987 --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheLocalTest.cs @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + public class CacheLocalTest : CacheAbstractTest + { + protected override int CachePartitions() + { + return 1; + } + + protected override int GridCount() + { + return 1; + } + + protected override string CacheName() + { + return "local"; + } + + protected override bool NearEnabled() + { + return false; + } + + protected override bool TxEnabled() + { + return true; + } + protected override bool LocalCache() + { + return true; + } + + protected override int Backups() + { + return 0; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedAtomicNearEnabledTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedAtomicNearEnabledTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedAtomicNearEnabledTest.cs new file mode 100644 index 0000000..4f6e7a0 --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedAtomicNearEnabledTest.cs @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using NUnit.Framework; + + [Category(TestUtils.CategoryIntensive)] + public class CachePartitionedAtomicNearEnabledTest : CacheAbstractTest + { + protected override int GridCount() + { + return 3; + } + + protected override string CacheName() + { + return "partitioned_atomic_near"; + } + + protected override bool NearEnabled() + { + return true; + } + + protected override bool TxEnabled() + { + return false; + } + + protected override int Backups() + { + return 1; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedAtomicTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedAtomicTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedAtomicTest.cs new file mode 100644 index 0000000..ab59c64 --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedAtomicTest.cs @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using NUnit.Framework; + + [Category(TestUtils.CategoryIntensive)] + public class CachePartitionedAtomicTest : CacheAbstractTest + { + protected override int GridCount() + { + return 3; + } + + protected override string CacheName() + { + return "partitioned_atomic"; + } + + protected override bool NearEnabled() + { + return false; + } + + protected override bool TxEnabled() + { + return false; + } + + protected override int Backups() + { + return 1; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedNearEnabledTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedNearEnabledTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedNearEnabledTest.cs new file mode 100644 index 0000000..830698b --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedNearEnabledTest.cs @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using NUnit.Framework; + + [Category(TestUtils.CategoryIntensive)] + public class CachePartitionedNearEnabledTest : CacheAbstractTest + { + protected override int GridCount() + { + return 3; + } + + protected override string CacheName() + { + return "partitioned_near"; + } + + protected override bool NearEnabled() + { + return true; + } + + protected override bool TxEnabled() + { + return true; + } + + protected override int Backups() + { + return 1; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedTest.cs new file mode 100644 index 0000000..02d3208 --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CachePartitionedTest.cs @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using NUnit.Framework; + + [Category(TestUtils.CategoryIntensive)] + public class CachePartitionedTest : CacheAbstractTest + { + protected override int GridCount() + { + return 3; + } + + protected override string CacheName() + { + return "partitioned"; + } + + protected override bool NearEnabled() + { + return false; + } + + protected override bool TxEnabled() + { + return true; + } + + protected override int Backups() + { + return 1; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheReplicatedAtomicTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheReplicatedAtomicTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheReplicatedAtomicTest.cs new file mode 100644 index 0000000..db6f5a5 --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheReplicatedAtomicTest.cs @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using NUnit.Framework; + + [Category(TestUtils.CategoryIntensive)] + public class CacheReplicatedAtomicTest : CacheAbstractTest + { + protected override int CachePartitions() + { + return 512; + } + + protected override int GridCount() + { + return 3; + } + + protected override string CacheName() + { + return "replicated_atomic"; + } + + protected override bool NearEnabled() + { + return false; + } + + protected override bool TxEnabled() + { + return false; + } + + protected override int Backups() + { + return GridCount() - 1; + } + + protected override bool ReplicatedCache() + { + return true; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheReplicatedTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheReplicatedTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheReplicatedTest.cs new file mode 100644 index 0000000..7c70222 --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheReplicatedTest.cs @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using NUnit.Framework; + + [Category(TestUtils.CategoryIntensive)] + public class CacheReplicatedTest : CacheAbstractTest + { + protected override int CachePartitions() + { + return 512; + } + + protected override int GridCount() + { + return 3; + } + + protected override string CacheName() + { + return "replicated"; + } + + protected override bool NearEnabled() + { + return false; + } + + protected override bool TxEnabled() + { + return true; + } + + protected override int Backups() + { + return GridCount() - 1; + } + + protected override bool ReplicatedCache() + { + return true; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheTestAsyncWrapper.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheTestAsyncWrapper.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheTestAsyncWrapper.cs new file mode 100644 index 0000000..93f5973 --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/CacheTestAsyncWrapper.cs @@ -0,0 +1,436 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache +{ + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics; + using Apache.Ignite.Core.Cache; + using Apache.Ignite.Core.Cache.Expiry; + using Apache.Ignite.Core.Cache.Query; + using Apache.Ignite.Core.Cache.Query.Continuous; + using Apache.Ignite.Core.Common; + + /// <summary> + /// Wraps IGridCache implementation to simplify async mode testing. + /// </summary> + internal class CacheTestAsyncWrapper<TK, TV> : ICache<TK, TV> + { + private readonly ICache<TK, TV> _cache; + + /// <summary> + /// Initializes a new instance of the <see cref="CacheTestAsyncWrapper{K, V}"/> class. + /// </summary> + /// <param name="cache">The cache to be wrapped.</param> + public CacheTestAsyncWrapper(ICache<TK, TV> cache) + { + Debug.Assert(cache.IsAsync, "GridCacheTestAsyncWrapper only works with async caches."); + + _cache = cache; + } + + /** <inheritDoc /> */ + public ICache<TK, TV> WithAsync() + { + return this; + } + + /** <inheritDoc /> */ + public bool IsAsync + { + get { return true; } + } + + /** <inheritDoc /> */ + public IFuture GetFuture() + { + Debug.Fail("GridCacheTestAsyncWrapper.Future() should not be called. It always returns null."); + return null; + } + + /** <inheritDoc /> */ + public IFuture<TResult> GetFuture<TResult>() + { + Debug.Fail("GridCacheTestAsyncWrapper.Future() should not be called. It always returns null."); + return null; + } + + /** <inheritDoc /> */ + public string Name + { + get { return _cache.Name; } + } + + /** <inheritDoc /> */ + public IIgnite Ignite + { + get { return _cache.Ignite; } + } + + /** <inheritDoc /> */ + public bool IsEmpty + { + get { return _cache.IsEmpty; } + } + + /** <inheritDoc /> */ + public bool KeepPortable + { + get { return _cache.KeepPortable; } + } + + /** <inheritDoc /> */ + public ICache<TK, TV> WithSkipStore() + { + return _cache.WithSkipStore().WrapAsync(); + } + + /** <inheritDoc /> */ + public ICache<TK, TV> WithExpiryPolicy(IExpiryPolicy plc) + { + return _cache.WithExpiryPolicy(plc).WrapAsync(); + } + + /** <inheritDoc /> */ + public ICache<TK1, TV1> WithKeepPortable<TK1, TV1>() + { + return _cache.WithKeepPortable<TK1, TV1>().WrapAsync(); + } + + /** <inheritDoc /> */ + public void LoadCache(ICacheEntryFilter<TK, TV> p, params object[] args) + { + _cache.LoadCache(p, args); + WaitResult(); + } + + /** <inheritDoc /> */ + public void LocalLoadCache(ICacheEntryFilter<TK, TV> p, params object[] args) + { + _cache.LocalLoadCache(p, args); + WaitResult(); + } + + /** <inheritDoc /> */ + public bool ContainsKey(TK key) + { + _cache.ContainsKey(key); + return GetResult<bool>(); + } + + /** <inheritDoc /> */ + public bool ContainsKeys(IEnumerable<TK> keys) + { + _cache.ContainsKeys(keys); + return GetResult<bool>(); + } + + /** <inheritDoc /> */ + public TV LocalPeek(TK key, params CachePeekMode[] modes) + { + _cache.LocalPeek(key, modes); + return GetResult<TV>(); + } + + /** <inheritDoc /> */ + public TV Get(TK key) + { + _cache.Get(key); + return GetResult<TV>(); + } + + /** <inheritDoc /> */ + public IDictionary<TK, TV> GetAll(IEnumerable<TK> keys) + { + _cache.GetAll(keys); + return GetResult<IDictionary<TK, TV>>(); + } + + /** <inheritDoc /> */ + public void Put(TK key, TV val) + { + _cache.Put(key, val); + WaitResult(); + } + + /** <inheritDoc /> */ + public TV GetAndPut(TK key, TV val) + { + _cache.GetAndPut(key, val); + return GetResult<TV>(); + } + + /** <inheritDoc /> */ + public TV GetAndReplace(TK key, TV val) + { + _cache.GetAndReplace(key, val); + return GetResult<TV>(); + } + + /** <inheritDoc /> */ + public TV GetAndRemove(TK key) + { + _cache.GetAndRemove(key); + return GetResult<TV>(); + } + + /** <inheritDoc /> */ + public bool PutIfAbsent(TK key, TV val) + { + _cache.PutIfAbsent(key, val); + return GetResult<bool>(); + } + + /** <inheritDoc /> */ + public TV GetAndPutIfAbsent(TK key, TV val) + { + _cache.GetAndPutIfAbsent(key, val); + return GetResult<TV>(); + } + + /** <inheritDoc /> */ + public bool Replace(TK key, TV val) + { + _cache.Replace(key, val); + return GetResult<bool>(); + } + + /** <inheritDoc /> */ + public bool Replace(TK key, TV oldVal, TV newVal) + { + _cache.Replace(key, oldVal, newVal); + return GetResult<bool>(); + } + + /** <inheritDoc /> */ + public void PutAll(IDictionary<TK, TV> vals) + { + _cache.PutAll(vals); + WaitResult(); + } + + /** <inheritDoc /> */ + public void LocalEvict(IEnumerable<TK> keys) + { + _cache.LocalEvict(keys); + } + + /** <inheritDoc /> */ + public void Clear() + { + _cache.Clear(); + WaitResult(); + } + + /** <inheritDoc /> */ + public void Clear(TK key) + { + _cache.Clear(key); + } + + /** <inheritDoc /> */ + public void ClearAll(IEnumerable<TK> keys) + { + _cache.ClearAll(keys); + } + + /** <inheritDoc /> */ + public void LocalClear(TK key) + { + _cache.LocalClear(key); + } + + /** <inheritDoc /> */ + public void LocalClearAll(IEnumerable<TK> keys) + { + _cache.LocalClearAll(keys); + } + + /** <inheritDoc /> */ + public bool Remove(TK key) + { + _cache.Remove(key); + return GetResult<bool>(); + } + + /** <inheritDoc /> */ + public bool Remove(TK key, TV val) + { + _cache.Remove(key, val); + return GetResult<bool>(); + } + + /** <inheritDoc /> */ + public void RemoveAll(IEnumerable<TK> keys) + { + _cache.RemoveAll(keys); + WaitResult(); + } + + /** <inheritDoc /> */ + public void RemoveAll() + { + _cache.RemoveAll(); + WaitResult(); + } + + /** <inheritDoc /> */ + public int LocalSize(params CachePeekMode[] modes) + { + return _cache.LocalSize(modes); + } + + /** <inheritDoc /> */ + public int Size(params CachePeekMode[] modes) + { + _cache.Size(modes); + return GetResult<int>(); + } + + /** <inheritDoc /> */ + public void LocalPromote(IEnumerable<TK> keys) + { + _cache.LocalPromote(keys); + } + + /** <inheritDoc /> */ + public IQueryCursor<ICacheEntry<TK, TV>> Query(QueryBase qry) + { + return _cache.Query(qry); + } + + /** <inheritDoc /> */ + public IQueryCursor<IList> QueryFields(SqlFieldsQuery qry) + { + return _cache.QueryFields(qry); + } + + /** <inheritDoc /> */ + IContinuousQueryHandle ICache<TK, TV>.QueryContinuous(ContinuousQuery<TK, TV> qry) + { + return _cache.QueryContinuous(qry); + } + + /** <inheritDoc /> */ + public IContinuousQueryHandle<ICacheEntry<TK, TV>> QueryContinuous(ContinuousQuery<TK, TV> qry, QueryBase initialQry) + { + return _cache.QueryContinuous(qry, initialQry); + } + + /** <inheritDoc /> */ + public IEnumerable<ICacheEntry<TK, TV>> GetLocalEntries(params CachePeekMode[] peekModes) + { + return _cache.GetLocalEntries(peekModes); + } + + /** <inheritDoc /> */ + public TR Invoke<TR, TA>(TK key, ICacheEntryProcessor<TK, TV, TA, TR> processor, TA arg) + { + _cache.Invoke(key, processor, arg); + + return GetResult<TR>(); + } + + /** <inheritDoc /> */ + public IDictionary<TK, ICacheEntryProcessorResult<TR>> InvokeAll<TR, TA>(IEnumerable<TK> keys, + ICacheEntryProcessor<TK, TV, TA, TR> processor, TA arg) + { + _cache.InvokeAll(keys, processor, arg); + + return GetResult<IDictionary<TK, ICacheEntryProcessorResult<TR>>>(); + } + + /** <inheritDoc /> */ + public ICacheLock Lock(TK key) + { + return _cache.Lock(key); + } + + /** <inheritDoc /> */ + public ICacheLock LockAll(IEnumerable<TK> keys) + { + return _cache.LockAll(keys); + } + + /** <inheritDoc /> */ + public bool IsLocalLocked(TK key, bool byCurrentThread) + { + return _cache.IsLocalLocked(key, byCurrentThread); + } + + /** <inheritDoc /> */ + public ICacheMetrics GetMetrics() + { + return _cache.GetMetrics(); + } + + /** <inheritDoc /> */ + public IFuture Rebalance() + { + return _cache.Rebalance(); + } + + /** <inheritDoc /> */ + public ICache<TK, TV> WithNoRetries() + { + return _cache.WithNoRetries(); + } + + /** <inheritDoc /> */ + public IEnumerator<ICacheEntry<TK, TV>> GetEnumerator() + { + return _cache.GetEnumerator(); + } + + /** <inheritDoc /> */ + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// <summary> + /// Waits for the async result. + /// </summary> + private void WaitResult() + { + GetResult<object>(); + } + + /// <summary> + /// Gets the async result. + /// </summary> + private T GetResult<T>() + { + return _cache.GetFuture<T>().Get(); + } + } + + /// <summary> + /// Extension methods for IGridCache. + /// </summary> + public static class CacheExtensions + { + /// <summary> + /// Wraps specified instance into GridCacheTestAsyncWrapper. + /// </summary> + public static ICache<TK, TV> WrapAsync<TK, TV>(this ICache<TK, TV> cache) + { + return new CacheTestAsyncWrapper<TK, TV>(cache); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/5cec202c/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs ---------------------------------------------------------------------- diff --git a/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs new file mode 100644 index 0000000..85227b6 --- /dev/null +++ b/modules/platform/src/test/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs @@ -0,0 +1,928 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Cache.Query +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Text; + using Apache.Ignite.Core.Cache; + using Apache.Ignite.Core.Cache.Query; + using Apache.Ignite.Core.Common; + using Apache.Ignite.Core.Impl; + using Apache.Ignite.Core.Impl.Portable; + using Apache.Ignite.Core.Portable; + using NUnit.Framework; + + /// <summary> + /// Queries tests. + /// </summary> + public class CacheQueriesTest + { + /** Grid count. */ + private const int GridCnt = 2; + + /** Cache name. */ + private const string CacheName = "cache"; + + /** Path to XML configuration. */ + private const string CfgPath = "config\\cache-query.xml"; + + /** Maximum amount of items in cache. */ + private const int MaxItemCnt = 100; + + /// <summary> + /// + /// </summary> + [TestFixtureSetUp] + public virtual void StartGrids() + { + TestUtils.JvmDebug = true; + TestUtils.KillProcesses(); + + IgniteConfigurationEx cfg = new IgniteConfigurationEx + { + PortableConfiguration = new PortableConfiguration + { + TypeConfigurations = new[] + { + new PortableTypeConfiguration(typeof (QueryPerson)), + new PortableTypeConfiguration(typeof (PortableScanQueryFilter<QueryPerson>)), + new PortableTypeConfiguration(typeof (PortableScanQueryFilter<PortableUserObject>)) + } + }, + JvmClasspath = TestUtils.CreateTestClasspath(), + JvmOptions = TestUtils.TestJavaOptions(), + SpringConfigUrl = CfgPath + }; + + for (int i = 0; i < GridCnt; i++) + { + cfg.GridName = "grid-" + i; + + Ignition.Start(cfg); + } + } + + /// <summary> + /// + /// </summary> + [TestFixtureTearDown] + public virtual void StopGrids() + { + for (int i = 0; i < GridCnt; i++) + Ignition.Stop("grid-" + i, true); + } + + /// <summary> + /// + /// </summary> + [SetUp] + public virtual void BeforeTest() + { + Console.WriteLine("Test started: " + TestContext.CurrentContext.Test.Name); + } + + /// <summary> + /// + /// </summary> + [TearDown] + public virtual void AfterTest() + { + var cache = Cache(); + + for (int i = 0; i < GridCnt; i++) + { + for (int j = 0; j < MaxItemCnt; j++) + cache.Remove(j); + + Assert.IsTrue(cache.IsEmpty); + } + + Console.WriteLine("Test finished: " + TestContext.CurrentContext.Test.Name); + } + + /// <summary> + /// + /// </summary> + /// <param name="idx"></param> + /// <returns></returns> + public IIgnite GetIgnite(int idx) + { + return Ignition.GetIgnite("grid-" + idx); + } + + /// <summary> + /// + /// </summary> + /// <param name="idx"></param> + /// <returns></returns> + public ICache<int, QueryPerson> Cache(int idx) + { + return GetIgnite(idx).Cache<int, QueryPerson>(CacheName); + } + + /// <summary> + /// + /// </summary> + /// <returns></returns> + public ICache<int, QueryPerson> Cache() + { + return Cache(0); + } + + /// <summary> + /// Test arguments validation for SQL queries. + /// </summary> + [Test] + public void TestValidationSql() + { + // 1. No sql. + Assert.Throws<ArgumentException>(() => + { Cache().Query(new SqlQuery(typeof(QueryPerson), null)); }); + + // 2. No type. + Assert.Throws<ArgumentException>(() => + { Cache().Query(new SqlQuery((string)null, "age >= 50")); }); + } + + /// <summary> + /// Test arguments validation for SQL fields queries. + /// </summary> + [Test] + public void TestValidationSqlFields() + { + // 1. No sql. + Assert.Throws<ArgumentException>(() => { Cache().QueryFields(new SqlFieldsQuery(null)); }); + } + + /// <summary> + /// Test arguments validation for TEXT queries. + /// </summary> + [Test] + public void TestValidationText() + { + // 1. No text. + Assert.Throws<ArgumentException>(() => + { Cache().Query(new TextQuery(typeof(QueryPerson), null)); }); + + // 2. No type. + Assert.Throws<ArgumentException>(() => + { Cache().Query(new TextQuery((string)null, "Ivanov")); }); + } + + /// <summary> + /// Cursor tests. + /// </summary> + [Test] + [SuppressMessage("ReSharper", "ReturnValueOfPureMethodIsNotUsed")] + public void TestCursor() + { + var cache0 = Cache().WithAsync(); + + cache0.WithAsync().Put(1, new QueryPerson("Ivanov", 30)); + + IFuture<object> res = cache0.GetFuture<object>(); + + res.Get(); + + Cache().Put(1, new QueryPerson("Ivanov", 30)); + Cache().Put(1, new QueryPerson("Petrov", 40)); + Cache().Put(1, new QueryPerson("Sidorov", 50)); + + SqlQuery qry = new SqlQuery(typeof(QueryPerson), "age >= 20"); + + // 1. Test GetAll(). + using (IQueryCursor<ICacheEntry<int, QueryPerson>> cursor = Cache().Query(qry)) + { + cursor.GetAll(); + + Assert.Throws<InvalidOperationException>(() => { cursor.GetAll(); }); + Assert.Throws<InvalidOperationException>(() => { cursor.GetEnumerator(); }); + } + + // 2. Test GetEnumerator. + using (IQueryCursor<ICacheEntry<int, QueryPerson>> cursor = Cache().Query(qry)) + { + cursor.GetEnumerator(); + + Assert.Throws<InvalidOperationException>(() => { cursor.GetAll(); }); + Assert.Throws<InvalidOperationException>(() => { cursor.GetEnumerator(); }); + } + } + + /// <summary> + /// Test enumerator. + /// </summary> + [Test] + [SuppressMessage("ReSharper", "UnusedVariable")] + public void TestEnumerator() + { + Cache().Put(1, new QueryPerson("Ivanov", 30)); + Cache().Put(2, new QueryPerson("Petrov", 40)); + Cache().Put(3, new QueryPerson("Sidorov", 50)); + Cache().Put(4, new QueryPerson("Unknown", 60)); + + // 1. Empty result set. + using ( + IQueryCursor<ICacheEntry<int, QueryPerson>> cursor = + Cache().Query(new SqlQuery(typeof(QueryPerson), "age = 100"))) + { + IEnumerator<ICacheEntry<int, QueryPerson>> e = cursor.GetEnumerator(); + + Assert.Throws<InvalidOperationException>(() => + { ICacheEntry<int, QueryPerson> entry = e.Current; }); + + Assert.IsFalse(e.MoveNext()); + + Assert.Throws<InvalidOperationException>(() => + { ICacheEntry<int, QueryPerson> entry = e.Current; }); + + Assert.Throws<NotSupportedException>(() => e.Reset()); + } + + SqlQuery qry = new SqlQuery(typeof (QueryPerson), "age < 60"); + + // 2. Page size is bigger than result set. + qry.PageSize = 4; + CheckEnumeratorQuery(qry); + + // 3. Page size equal to result set. + qry.PageSize = 3; + CheckEnumeratorQuery(qry); + + // 4. Page size if less than result set. + qry.PageSize = 2; + CheckEnumeratorQuery(qry); + } + + /// <summary> + /// Test SQL query arguments passing. + /// </summary> + public void TestSqlQueryArguments() + { + Cache().Put(1, new QueryPerson("Ivanov", 30)); + Cache().Put(2, new QueryPerson("Petrov", 40)); + Cache().Put(3, new QueryPerson("Sidorov", 50)); + + // 1. Empty result set. + using ( + IQueryCursor<ICacheEntry<int, QueryPerson>> cursor = + Cache().Query(new SqlQuery(typeof(QueryPerson), "age < ?", 50))) + { + foreach (ICacheEntry<int, QueryPerson> entry in cursor.GetAll()) + Assert.IsTrue(entry.Key == 1 || entry.Key == 2); + } + } + + /// <summary> + /// Test SQL fields query arguments passing. + /// </summary> + public void TestSqlFieldsQueryArguments() + { + Cache().Put(1, new QueryPerson("Ivanov", 30)); + Cache().Put(2, new QueryPerson("Petrov", 40)); + Cache().Put(3, new QueryPerson("Sidorov", 50)); + + // 1. Empty result set. + using ( + IQueryCursor<IList> cursor = Cache().QueryFields( + new SqlFieldsQuery("SELECT age FROM QueryPerson WHERE age < ?", 50))) + { + foreach (IList entry in cursor.GetAll()) + Assert.IsTrue((int) entry[0] < 50); + } + } + + /// <summary> + /// Check query result for enumerator test. + /// </summary> + /// <param name="qry">QUery.</param> + private void CheckEnumeratorQuery(SqlQuery qry) + { + using (IQueryCursor<ICacheEntry<int, QueryPerson>> cursor = Cache().Query(qry)) + { + bool first = false; + bool second = false; + bool third = false; + + foreach (var entry in cursor) + { + if (entry.Key == 1) + { + first = true; + + Assert.AreEqual("Ivanov", entry.Value.Name); + Assert.AreEqual(30, entry.Value.Age); + } + else if (entry.Key == 2) + { + second = true; + + Assert.AreEqual("Petrov", entry.Value.Name); + Assert.AreEqual(40, entry.Value.Age); + } + else if (entry.Key == 3) + { + third = true; + + Assert.AreEqual("Sidorov", entry.Value.Name); + Assert.AreEqual(50, entry.Value.Age); + } + else + Assert.Fail("Unexpected value: " + entry); + } + + Assert.IsTrue(first && second && third); + } + } + + /// <summary> + /// Check SQL query. + /// </summary> + [Test] + public void TestSqlQuery() + { + CheckSqlQuery(MaxItemCnt, false, false); + } + + /// <summary> + /// Check SQL query in portable mode. + /// </summary> + [Test] + public void TestSqlQueryPortable() + { + CheckSqlQuery(MaxItemCnt, false, true); + } + + /// <summary> + /// Check local SQL query. + /// </summary> + [Test] + public void TestSqlQueryLocal() + { + CheckSqlQuery(MaxItemCnt, true, false); + } + + /// <summary> + /// Check local SQL query in portable mode. + /// </summary> + [Test] + public void TestSqlQueryLocalPortable() + { + CheckSqlQuery(MaxItemCnt, true, true); + } + + /// <summary> + /// Check SQL query. + /// </summary> + /// <param name="cnt">Amount of cache entries to create.</param> + /// <param name="loc">Local query flag.</param> + /// <param name="keepPortable">Keep portable flag.</param> + private void CheckSqlQuery(int cnt, bool loc, bool keepPortable) + { + var cache = Cache(); + + // 1. Populate cache with data, calculating expected count in parallel. + var exp = PopulateCache(cache, loc, cnt, x => x < 50); + + // 2. Validate results. + SqlQuery qry = loc ? new SqlQuery(typeof(QueryPerson), "age < 50", true) : + new SqlQuery(typeof(QueryPerson), "age < 50"); + + ValidateQueryResults(cache, qry, exp, keepPortable); + } + + /// <summary> + /// Check SQL fields query. + /// </summary> + [Test] + public void TestSqlFieldsQuery() + { + CheckSqlFieldsQuery(MaxItemCnt, false); + } + + /// <summary> + /// Check local SQL fields query. + /// </summary> + [Test] + public void TestSqlFieldsQueryLocal() + { + CheckSqlFieldsQuery(MaxItemCnt, true); + } + + /// <summary> + /// Check SQL fields query. + /// </summary> + /// <param name="cnt">Amount of cache entries to create.</param> + /// <param name="loc">Local query flag.</param> + private void CheckSqlFieldsQuery(int cnt, bool loc) + { + var cache = Cache(); + + // 1. Populate cache with data, calculating expected count in parallel. + var exp = PopulateCache(cache, loc, cnt, x => x < 50); + + // 2. Vlaidate results. + SqlFieldsQuery qry = loc ? new SqlFieldsQuery("SELECT name, age FROM QueryPerson WHERE age < 50", true) : + new SqlFieldsQuery("SELECT name, age FROM QueryPerson WHERE age < 50"); + + using (IQueryCursor<IList> cursor = cache.QueryFields(qry)) + { + HashSet<int> exp0 = new HashSet<int>(exp); + + foreach (var entry in cursor.GetAll()) + { + Assert.AreEqual(2, entry.Count); + Assert.AreEqual(entry[0].ToString(), entry[1].ToString()); + + exp0.Remove((int)entry[1]); + } + + Assert.AreEqual(0, exp0.Count); + } + + using (IQueryCursor<IList> cursor = cache.QueryFields(qry)) + { + HashSet<int> exp0 = new HashSet<int>(exp); + + foreach (var entry in cursor) + { + Assert.AreEqual(entry[0].ToString(), entry[1].ToString()); + + exp0.Remove((int)entry[1]); + } + + Assert.AreEqual(0, exp0.Count); + } + } + + /// <summary> + /// Check text query. + /// </summary> + [Test] + public void TestTextQuery() + { + CheckTextQuery(MaxItemCnt, false, false); + } + + /// <summary> + /// Check SQL query in portable mode. + /// </summary> + [Test] + public void TestTextQueryPortable() + { + CheckTextQuery(MaxItemCnt, false, true); + } + + /// <summary> + /// Check local SQL query. + /// </summary> + [Test] + public void TestTextQueryLocal() + { + CheckTextQuery(MaxItemCnt, true, false); + } + + /// <summary> + /// Check local SQL query in portable mode. + /// </summary> + [Test] + public void TestTextQueryLocalPortable() + { + CheckTextQuery(MaxItemCnt, true, true); + } + + /// <summary> + /// Check text query. + /// </summary> + /// <param name="cnt">Amount of cache entries to create.</param> + /// <param name="loc">Local query flag.</param> + /// <param name="keepPortable">Keep portable flag.</param> + private void CheckTextQuery(int cnt, bool loc, bool keepPortable) + { + var cache = Cache(); + + // 1. Populate cache with data, calculating expected count in parallel. + var exp = PopulateCache(cache, loc, cnt, x => x.ToString().StartsWith("1")); + + // 2. Validate results. + TextQuery qry = loc ? new TextQuery(typeof(QueryPerson), "1*", true) : + new TextQuery(typeof(QueryPerson), "1*"); + + ValidateQueryResults(cache, qry, exp, keepPortable); + } + + /// <summary> + /// Check scan query. + /// </summary> + [Test] + public void TestScanQuery() + { + CheckScanQuery<QueryPerson>(MaxItemCnt, false, false); + } + + /// <summary> + /// Check scan query in portable mode. + /// </summary> + [Test] + public void TestScanQueryPortable() + { + CheckScanQuery<PortableUserObject>(MaxItemCnt, false, true); + } + + /// <summary> + /// Check local scan query. + /// </summary> + [Test] + public void TestScanQueryLocal() + { + CheckScanQuery<QueryPerson>(MaxItemCnt, true, false); + } + + /// <summary> + /// Check local scan query in portable mode. + /// </summary> + [Test] + public void TestScanQueryLocalPortable() + { + CheckScanQuery<PortableUserObject>(MaxItemCnt, true, true); + } + + /// <summary> + /// Check scan query with partitions. + /// </summary> + [Test] + [Ignore("IGNITE-1012")] + public void TestScanQueryPartitions([Values(true, false)] bool loc) + { + CheckScanQueryPartitions<QueryPerson>(MaxItemCnt, loc, false); + } + + /// <summary> + /// Check scan query with partitions in portable mode. + /// </summary> + [Test] + [Ignore("IGNITE-1012")] + public void TestScanQueryPartitionsPortable([Values(true, false)] bool loc) + { + CheckScanQueryPartitions<PortableUserObject>(MaxItemCnt, loc, true); + } + + /// <summary> + /// Tests that query attempt on non-indexed cache causes an exception. + /// </summary> + [Test] + public void TestIndexingDisabledError() + { + var cache = GetIgnite(0).GetOrCreateCache<int, QueryPerson>("nonindexed_cache"); + + var queries = new QueryBase[] + { + new TextQuery(typeof (QueryPerson), "1*"), + new SqlQuery(typeof (QueryPerson), "age < 50") + }; + + foreach (var qry in queries) + { + var err = Assert.Throws<IgniteException>(() => cache.Query(qry)); + + Assert.AreEqual("Indexing is disabled for cache: nonindexed_cache. " + + "Use setIndexedTypes or setTypeMetadata methods on CacheConfiguration to enable.", err.Message); + } + } + + /// <summary> + /// Check scan query. + /// </summary> + /// <param name="cnt">Amount of cache entries to create.</param> + /// <param name="loc">Local query flag.</param> + /// <param name="keepPortable">Keep portable flag.</param> + private void CheckScanQuery<TV>(int cnt, bool loc, bool keepPortable) + { + var cache = Cache(); + + // No predicate + var exp = PopulateCache(cache, loc, cnt, x => true); + var qry = new ScanQuery<int, TV>(); + ValidateQueryResults(cache, qry, exp, keepPortable); + + // Serializable + exp = PopulateCache(cache, loc, cnt, x => x < 50); + qry = new ScanQuery<int, TV>(new ScanQueryFilter<TV>()); + ValidateQueryResults(cache, qry, exp, keepPortable); + + // Portable + exp = PopulateCache(cache, loc, cnt, x => x < 50); + qry = new ScanQuery<int, TV>(new PortableScanQueryFilter<TV>()); + ValidateQueryResults(cache, qry, exp, keepPortable); + + // Exception + exp = PopulateCache(cache, loc, cnt, x => x < 50); + qry = new ScanQuery<int, TV>(new ScanQueryFilter<TV> {ThrowErr = true}); + + var ex = Assert.Throws<IgniteException>(() => ValidateQueryResults(cache, qry, exp, keepPortable)); + Assert.AreEqual(ScanQueryFilter<TV>.ErrMessage, ex.Message); + } + + /// <summary> + /// Checks scan query with partitions. + /// </summary> + /// <param name="cnt">Amount of cache entries to create.</param> + /// <param name="loc">Local query flag.</param> + /// <param name="keepPortable">Keep portable flag.</param> + private void CheckScanQueryPartitions<TV>(int cnt, bool loc, bool keepPortable) + { + StopGrids(); + StartGrids(); + + var cache = Cache(); + + var aff = cache.Ignite.Affinity(CacheName); + var exp = PopulateCache(cache, loc, cnt, x => true); // populate outside the loop (slow) + + for (var part = 0; part < aff.Partitions; part++) + { + //var exp0 = new HashSet<int>(exp.Where(x => aff.Partition(x) == part)); // filter expected keys + var exp0 = new HashSet<int>(); + foreach (var x in exp) + if (aff.Partition(x) == part) + exp0.Add(x); + + var qry = new ScanQuery<int, TV> { Partition = part }; + + Console.WriteLine("Checking query on partition " + part); + ValidateQueryResults(cache, qry, exp0, keepPortable); + } + + // Partitions with predicate + exp = PopulateCache(cache, loc, cnt, x => x < 50); // populate outside the loop (slow) + + for (var part = 0; part < aff.Partitions; part++) + { + //var exp0 = new HashSet<int>(exp.Where(x => aff.Partition(x) == part)); // filter expected keys + var exp0 = new HashSet<int>(); + foreach (var x in exp) + if (aff.Partition(x) == part) + exp0.Add(x); + + var qry = new ScanQuery<int, TV>(new ScanQueryFilter<TV>()) { Partition = part }; + + Console.WriteLine("Checking predicate query on partition " + part); + ValidateQueryResults(cache, qry, exp0, keepPortable); + } + + } + + /// <summary> + /// Validates the query results. + /// </summary> + /// <param name="cache">Cache.</param> + /// <param name="qry">Query.</param> + /// <param name="exp">Expected keys.</param> + /// <param name="keepPortable">Keep portable flag.</param> + private static void ValidateQueryResults(ICache<int, QueryPerson> cache, QueryBase qry, HashSet<int> exp, + bool keepPortable) + { + if (keepPortable) + { + var cache0 = cache.WithKeepPortable<int, IPortableObject>(); + + using (var cursor = cache0.Query(qry)) + { + HashSet<int> exp0 = new HashSet<int>(exp); + var all = new List<ICacheEntry<int, object>>(); + + foreach (var entry in cursor.GetAll()) + { + all.Add(entry); + + Assert.AreEqual(entry.Key.ToString(), entry.Value.Field<string>("name")); + Assert.AreEqual(entry.Key, entry.Value.Field<int>("age")); + + exp0.Remove(entry.Key); + } + + AssertMissingExpectedKeys(exp0, cache, all); + } + + using (var cursor = cache0.Query(qry)) + { + HashSet<int> exp0 = new HashSet<int>(exp); + var all = new List<ICacheEntry<int, object>>(); + + foreach (var entry in cursor) + { + all.Add(entry); + + Assert.AreEqual(entry.Key.ToString(), entry.Value.Field<string>("name")); + Assert.AreEqual(entry.Key, entry.Value.Field<int>("age")); + + exp0.Remove(entry.Key); + } + + AssertMissingExpectedKeys(exp0, cache, all); + } + } + else + { + using (var cursor = cache.Query(qry)) + { + HashSet<int> exp0 = new HashSet<int>(exp); + var all = new List<ICacheEntry<int, object>>(); + + foreach (var entry in cursor.GetAll()) + { + all.Add(entry); + + Assert.AreEqual(entry.Key.ToString(), entry.Value.Name); + Assert.AreEqual(entry.Key, entry.Value.Age); + + exp0.Remove(entry.Key); + } + + AssertMissingExpectedKeys(exp0, cache, all); + } + + using (var cursor = cache.Query(qry)) + { + HashSet<int> exp0 = new HashSet<int>(exp); + var all = new List<ICacheEntry<int, object>>(); + + foreach (var entry in cursor) + { + all.Add(entry); + + Assert.AreEqual(entry.Key.ToString(), entry.Value.Name); + Assert.AreEqual(entry.Key, entry.Value.Age); + + exp0.Remove(entry.Key); + } + + AssertMissingExpectedKeys(exp0, cache, all); + } + } + } + + /// <summary> + /// Asserts that all expected entries have been received. + /// </summary> + private static void AssertMissingExpectedKeys(ICollection<int> exp, ICache<int, QueryPerson> cache, + IList<ICacheEntry<int, object>> all) + { + if (exp.Count == 0) + return; + + var sb = new StringBuilder(); + var aff = cache.Ignite.Affinity(cache.Name); + + foreach (var key in exp) + { + var part = aff.Partition(key); + sb.AppendFormat( + "Query did not return expected key '{0}' (exists: {1}), partition '{2}', partition nodes: ", + key, cache.Get(key) != null, part); + + var partNodes = aff.MapPartitionToPrimaryAndBackups(part); + + foreach (var node in partNodes) + sb.Append(node).Append(" "); + + sb.AppendLine(";"); + } + + sb.Append("Returned keys: "); + + foreach (var e in all) + sb.Append(e.Key).Append(" "); + + sb.AppendLine(";"); + + Assert.Fail(sb.ToString()); + } + + /// <summary> + /// Populates the cache with random entries and returns expected results set according to filter. + /// </summary> + /// <param name="cache">The cache.</param> + /// <param name="cnt">Amount of cache entries to create.</param> + /// <param name="loc">Local query flag.</param> + /// <param name="expectedEntryFilter">The expected entry filter.</param> + /// <returns>Expected results set.</returns> + private static HashSet<int> PopulateCache(ICache<int, QueryPerson> cache, bool loc, int cnt, + Func<int, bool> expectedEntryFilter) + { + var rand = new Random(); + + var exp = new HashSet<int>(); + + for (var i = 0; i < cnt; i++) + { + var val = rand.Next(100); + + cache.Put(val, new QueryPerson(val.ToString(), val)); + + if (expectedEntryFilter(val) && (!loc || cache.Ignite.Affinity(cache.Name) + .IsPrimary(cache.Ignite.Cluster.LocalNode, val))) + exp.Add(val); + } + + return exp; + } + } + + /// <summary> + /// Person. + /// </summary> + public class QueryPerson + { + /// <summary> + /// Constructor. + /// </summary> + public QueryPerson() + { + // No-op. + } + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="name">Name.</param> + /// <param name="age">Age.</param> + public QueryPerson(string name, int age) + { + Name = name; + Age = age; + } + + /// <summary> + /// Name. + /// </summary> + public string Name { get; set; } + + /// <summary> + /// Age. + /// </summary> + public int Age { get; set; } + } + + /// <summary> + /// Query filter. + /// </summary> + [Serializable] + public class ScanQueryFilter<TV> : ICacheEntryFilter<int, TV> + { + // Error message + public const string ErrMessage = "Error in ScanQueryFilter.Invoke"; + + // Error flag + public bool ThrowErr { get; set; } + + /** <inheritdoc /> */ + public bool Invoke(ICacheEntry<int, TV> entry) + { + if (ThrowErr) + throw new Exception(ErrMessage); + + return entry.Key < 50; + } + } + + /// <summary> + /// Portable query filter. + /// </summary> + public class PortableScanQueryFilter<TV> : ScanQueryFilter<TV>, IPortableMarshalAware + { + /** <inheritdoc /> */ + public void WritePortable(IPortableWriter writer) + { + var w = writer.RawWriter(); + + w.WriteBoolean(ThrowErr); + } + + /** <inheritdoc /> */ + public void ReadPortable(IPortableReader reader) + { + var r = reader.RawReader(); + + ThrowErr = r.ReadBoolean(); + } + } +}
