You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/09/04 18:27:39 UTC
[25/55] [abbrv] ignite git commit: IGNITE-1348: Moved GridGain's .Net
module to Ignite.
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();
+ }
+ }
+}