| /* |
| * 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. |
| */ |
| |
| // ReSharper disable MissingSerializationAttribute |
| // ReSharper disable NonReadonlyMemberInGetHashCode |
| namespace Apache.Ignite.Core.Tests.Cache |
| { |
| using System; |
| using System.Collections.Generic; |
| using System.Diagnostics.CodeAnalysis; |
| using System.Linq; |
| using System.Threading; |
| using System.Threading.Tasks; |
| using System.Transactions; |
| using Apache.Ignite.Core.Binary; |
| using Apache.Ignite.Core.Cache; |
| using Apache.Ignite.Core.Cache.Expiry; |
| using Apache.Ignite.Core.Cluster; |
| using Apache.Ignite.Core.Common; |
| using Apache.Ignite.Core.Impl.Cache; |
| using Apache.Ignite.Core.Tests.Query; |
| using Apache.Ignite.Core.Transactions; |
| using NUnit.Framework; |
| |
| /// <summary> |
| /// Base cache test. |
| /// </summary> |
| [SuppressMessage("ReSharper", "UnusedVariable")] |
| public abstract class CacheAbstractTest |
| { |
| /// <summary> |
| /// Fixture setup. |
| /// </summary> |
| [TestFixtureSetUp] |
| public void StartGrids() |
| { |
| IgniteConfiguration cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) |
| { |
| BinaryConfiguration = new BinaryConfiguration( |
| typeof(BinarizablePerson), |
| typeof(CacheTestKey), |
| typeof(TestReferenceObject), |
| typeof(BinarizableAddArgCacheEntryProcessor), |
| typeof(BinarizableTestException)), |
| SpringConfigUrl = "Config\\native-client-test-cache.xml" |
| }; |
| |
| for (int i = 0; i < GridCount(); i++) |
| { |
| cfg.IgniteInstanceName = "grid-" + i; |
| |
| Ignition.Start(cfg); |
| } |
| |
| Assert.AreEqual(GridCount(), GetIgnite(0).GetCluster().GetNodes().Count); |
| } |
| |
| /// <summary> |
| /// Fixture teardown. |
| /// </summary> |
| [TestFixtureTearDown] |
| public void StopGrids() |
| { |
| Ignition.StopAll(true); |
| } |
| |
| /// <summary> |
| /// |
| /// </summary> |
| [SetUp] |
| public void BeforeTest() |
| { |
| Console.WriteLine("Test started: " + TestContext.CurrentContext.Test.Name); |
| } |
| |
| /// <summary> |
| /// |
| /// </summary> |
| [TearDown] |
| public void AfterTest() { |
| for (int i = 0; i < GridCount(); i++) |
| Cache(i).WithKeepBinary<object, object>().RemoveAll(); |
| |
| for (int i = 0; i < GridCount(); i++) |
| { |
| var cache = Cache(i); |
| var entries = cache.Select(pair => pair + GetKeyAffinity(cache, pair.Key)).ToArray(); |
| |
| if (entries.Any()) |
| Assert.Fail("Cache '{0}' is not empty in grid [{1}]: ({2})", CacheName(), i, |
| entries.Aggregate((acc, val) => string.Format("{0}, {1}", acc, val))); |
| |
| var size = cache.GetSize(); |
| Assert.AreEqual(0, size, |
| "Cache enumerator returned no entries, but cache '{0}' size is {1} in grid [{2}]", |
| CacheName(), size, i); |
| } |
| |
| Console.WriteLine("Test finished: " + TestContext.CurrentContext.Test.Name); |
| } |
| |
| protected static IIgnite GetIgnite(int idx) |
| { |
| return Ignition.GetIgnite("grid-" + idx); |
| } |
| |
| protected ICache<int, int> Cache(int idx, bool async = false) |
| { |
| return Cache<int, int>(idx, async); |
| } |
| |
| private ICache<TK, TV> Cache<TK, TV>(int idx, bool async = false) { |
| var cache = GetIgnite(idx).GetCache<TK, TV>(CacheName()); |
| |
| return async ? cache.WrapAsync() : cache; |
| } |
| |
| protected ICache<int, int> Cache(bool async = false) |
| { |
| return Cache<int, int>(0, async); |
| } |
| |
| private ICache<TK, TV> Cache<TK, TV>(bool async = false) |
| { |
| return Cache<TK, TV>(0, async); |
| } |
| |
| private ICacheAffinity Affinity() |
| { |
| return GetIgnite(0).GetAffinity(CacheName()); |
| } |
| |
| protected virtual ITransactions Transactions |
| { |
| get { return GetIgnite(0).GetTransactions(); } |
| } |
| |
| [Test] |
| public void TestCircularReference() |
| { |
| var cache = Cache().WithKeepBinary<int, object>(); |
| |
| TestReferenceObject obj1 = new TestReferenceObject(); |
| |
| obj1.Obj = new TestReferenceObject(obj1); |
| |
| cache.Put(1, obj1); |
| |
| var po = (IBinaryObject) cache.Get(1); |
| |
| Assert.IsNotNull(po); |
| |
| TestReferenceObject objRef = po.Deserialize<TestReferenceObject>(); |
| |
| Assert.IsNotNull(objRef); |
| } |
| |
| [Test] |
| public void TestName() |
| { |
| for (int i = 0; i < GridCount(); i++ ) |
| Assert.AreEqual(CacheName(), Cache(i).Name); |
| } |
| |
| [Test] |
| public void TestIsEmpty() |
| { |
| for (int i = 0; i < GridCount(); i++) |
| { |
| var cache = Cache(i); |
| |
| Assert.IsTrue(cache.IsEmpty()); |
| } |
| |
| for (int i = 0; i < GridCount(); i++) |
| { |
| var cache = Cache(i); |
| |
| cache.Put(GetPrimaryKeyForCache(cache), 1); |
| } |
| |
| for (int i = 0; i < GridCount(); i++) |
| { |
| var cache = Cache(i); |
| |
| Assert.IsFalse(cache.IsEmpty()); |
| } |
| } |
| |
| [Test] |
| public void TestContainsKey() |
| { |
| var cache = Cache(); |
| |
| int key = GetPrimaryKeyForCache(cache); |
| |
| cache.Put(key, 1); |
| |
| Assert.IsTrue(cache.ContainsKey(key)); |
| Assert.IsFalse(cache.ContainsKey(-1)); |
| } |
| |
| [Test] |
| public void TestContainsKeys() |
| { |
| var cache = Cache(); |
| |
| var keys = GetPrimaryKeysForCache(cache, 5); |
| |
| Assert.IsFalse(cache.ContainsKeys(keys)); |
| |
| cache.PutAll(keys.ToDictionary(k => k, k => k)); |
| |
| Assert.IsTrue(cache.ContainsKeys(keys)); |
| |
| Assert.IsFalse(cache.ContainsKeys(keys.Concat(new[] {int.MaxValue}))); |
| } |
| |
| [Test] |
| public void TestPeek() |
| { |
| var cache = Cache(); |
| |
| int key1 = GetPrimaryKeyForCache(cache); |
| |
| cache.Put(key1, 1); |
| |
| int unused; |
| |
| Assert.AreEqual(1, cache.LocalPeek(key1)); |
| Assert.Throws<KeyNotFoundException>(() => cache.LocalPeek(-1)); |
| Assert.IsFalse(cache.TryLocalPeek(-1, out unused)); |
| |
| Assert.AreEqual(1, cache.LocalPeek(key1, CachePeekMode.All)); |
| Assert.Throws<KeyNotFoundException>(() => cache.LocalPeek(-1, CachePeekMode.All)); |
| Assert.AreEqual(false, cache.TryLocalPeek(-1, out unused, CachePeekMode.All)); |
| } |
| |
| [Test] |
| public void TestGet() |
| { |
| var cache = Cache(); |
| |
| cache.Put(1, 1); |
| cache.Put(2, 2); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| Assert.AreEqual(2, cache.Get(2)); |
| |
| Assert.Throws<KeyNotFoundException>(() => cache.Get(3)); |
| |
| int value; |
| |
| Assert.IsTrue(cache.TryGet(1, out value)); |
| Assert.AreEqual(1, value); |
| |
| Assert.IsTrue(cache.TryGet(2, out value)); |
| Assert.AreEqual(2, value); |
| |
| Assert.IsFalse(cache.TryGet(3, out value)); |
| Assert.AreEqual(0, value); |
| } |
| |
| [Test] |
| public void TestGetAsync() |
| { |
| var cache = Cache().WrapAsync(); |
| |
| cache.Put(1, 1); |
| cache.Put(2, 2); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| Assert.AreEqual(2, cache.Get(2)); |
| Assert.IsFalse(cache.ContainsKey(3)); |
| Assert.Throws<KeyNotFoundException>(() => cache.Get(3)); |
| |
| Assert.AreEqual(1, Cache().TryGetAsync(1).Result.Value); |
| Assert.IsFalse(Cache().TryGetAsync(3).Result.Success); |
| } |
| |
| [Test] |
| public void TestGetAll() |
| { |
| var cache = Cache(); |
| |
| cache.Put(1, 1); |
| cache.Put(2, 2); |
| cache.Put(3, 3); |
| cache.Put(4, 4); |
| cache.Put(5, 5); |
| |
| var map = cache.GetAll(new List<int> {0, 1, 2, 5}).ToDictionary(x => x.Key, x => x.Value); |
| |
| Assert.AreEqual(3, map.Count); |
| |
| Assert.AreEqual(1, map[1]); |
| Assert.AreEqual(2, map[2]); |
| } |
| |
| [Test] |
| public void TestGetAllAsync() |
| { |
| var cache = Cache().WrapAsync(); |
| |
| cache.Put(1, 1); |
| cache.Put(2, 2); |
| cache.Put(3, 3); |
| |
| var map = cache.GetAll(new List<int> {0, 1, 2}).ToDictionary(x => x.Key, x => x.Value); |
| |
| Assert.AreEqual(2, map.Count); |
| |
| Assert.AreEqual(1, map[1]); |
| Assert.AreEqual(2, map[2]); |
| } |
| |
| [Test] |
| public void TestGetAndPut() |
| { |
| var cache = Cache(); |
| |
| Assert.AreEqual(false, cache.ContainsKey(1)); |
| |
| var old = cache.GetAndPut(1, 1); |
| |
| Assert.IsFalse(old.Success); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| old = cache.GetAndPut(1, 2); |
| |
| Assert.AreEqual(1, old.Value); |
| |
| Assert.AreEqual(2, cache.Get(1)); |
| } |
| |
| [Test] |
| public void TestGetAndReplace() |
| { |
| var cache = Cache(); |
| |
| cache.Put(1, 10); |
| |
| Assert.AreEqual(10, cache.GetAndReplace(1, 100).Value); |
| |
| Assert.AreEqual(false, cache.GetAndReplace(2, 2).Success); |
| |
| Assert.AreEqual(false, cache.ContainsKey(2)); |
| |
| Assert.AreEqual(100, cache.Get(1)); |
| |
| Assert.IsTrue(cache.Remove(1)); |
| } |
| |
| [Test] |
| public void TestGetAndRemove() |
| { |
| var cache = Cache(); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.IsFalse(cache.GetAndRemove(0).Success); |
| |
| Assert.AreEqual(1, cache.GetAndRemove(1).Value); |
| |
| Assert.IsFalse(cache.GetAndRemove(1).Success); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| } |
| |
| [Test] |
| public void TestGetAndPutAsync() |
| { |
| var cache = Cache().WrapAsync(); |
| |
| Assert.AreEqual(false, cache.ContainsKey(1)); |
| |
| var old = cache.GetAndPut(1, 1); |
| |
| Assert.IsFalse(old.Success); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| old = cache.GetAndPut(1, 2); |
| |
| Assert.AreEqual(1, old.Value); |
| |
| Assert.AreEqual(2, cache.Get(1)); |
| } |
| |
| [Test] |
| public void TestPut([Values(true, false)] bool async) |
| { |
| var cache = Cache(async); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| // Objects. |
| var cache2 = Cache<Container, Container>(async); |
| |
| var obj1 = new Container {Id = 1}; |
| var obj2 = new Container {Id = 2}; |
| |
| obj1.Inner = obj2; |
| obj2.Inner = obj1; |
| |
| cache2[obj1] = obj2; |
| |
| Assert.AreEqual(2, cache2[obj1].Id); |
| } |
| |
| [Test] |
| public void TestGetAndPutIfAbsent() |
| { |
| var cache = Cache(); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| Assert.IsFalse(cache.GetAndPutIfAbsent(1, 1).Success); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.AreEqual(1, cache.GetAndPutIfAbsent(1, 2).Value); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| } |
| |
| [Test] |
| public void TestGetAndPutIfAbsentAsync() |
| { |
| var cache = Cache(true); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| var old = cache.GetAndPutIfAbsent(1, 1); |
| |
| Assert.IsFalse(old.Success); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| old = cache.GetAndPutIfAbsent(1, 2); |
| |
| Assert.AreEqual(1, old.Value); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| } |
| |
| [Test] |
| public void TestPutIfAbsent([Values(true, false)] bool async) |
| { |
| var cache = Cache(async); |
| |
| Assert.Throws<KeyNotFoundException>(() => cache.Get(1)); |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| Assert.IsTrue(cache.PutIfAbsent(1, 1)); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.IsFalse(cache.PutIfAbsent(1, 2)); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| } |
| |
| [Test] |
| public void TestReplace() |
| { |
| var cache = Cache(); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| bool success = cache.Replace(1, 1); |
| |
| Assert.AreEqual(false, success); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| success = cache.Replace(1, 2); |
| |
| Assert.AreEqual(true, success); |
| |
| Assert.AreEqual(2, cache.Get(1)); |
| |
| Assert.IsFalse(cache.Replace(1, -1, 3)); |
| |
| Assert.AreEqual(2, cache.Get(1)); |
| |
| Assert.IsTrue(cache.Replace(1, 2, 3)); |
| |
| Assert.AreEqual(3, cache.Get(1)); |
| } |
| |
| [Test] |
| [Ignore("IGNITE-7072")] |
| public void TestReplaceBinary() |
| { |
| var cache = Cache<object, object>(); |
| var key = new {Foo = "bar"}; |
| var val = new {Bar = "baz", Id = 1}; |
| var val2 = new {Bar = "baz2", Id = 2}; |
| var val3 = new {Bar = "baz3", Id = 3}; |
| |
| Assert.IsFalse(cache.ContainsKey(key)); |
| Assert.AreEqual(false, cache.Replace(key, val)); |
| Assert.IsFalse(cache.ContainsKey(key)); |
| |
| cache.Put(key, val); |
| Assert.AreEqual(val, cache.Get(key)); |
| Assert.IsTrue(cache.Replace(key, val2)); |
| Assert.AreEqual(val2, cache.Get(key)); |
| |
| Assert.IsFalse(cache.Replace(key, -1, 3)); |
| Assert.AreEqual(val2, cache.Get(key)); |
| |
| Assert.IsTrue(cache.Replace(key, val2, val3)); |
| Assert.AreEqual(val3, cache.Get(key)); |
| } |
| |
| [Test] |
| public void TestGetAndReplaceAsync() |
| { |
| var cache = Cache().WrapAsync(); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| var old = cache.GetAndReplace(1, 1); |
| |
| Assert.IsFalse(old.Success); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| old = cache.GetAndReplace(1, 2); |
| |
| Assert.AreEqual(1, old.Value); |
| |
| Assert.AreEqual(2, cache.Get(1)); |
| |
| Assert.IsFalse(cache.Replace(1, -1, 3)); |
| |
| Assert.AreEqual(2, cache.Get(1)); |
| |
| Assert.IsTrue(cache.Replace(1, 2, 3)); |
| |
| Assert.AreEqual(3, cache.Get(1)); |
| } |
| |
| [Test] |
| public void TestReplacex() |
| { |
| var cache = Cache(); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| Assert.IsFalse(cache.Replace(1, 1)); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.IsTrue(cache.Replace(1, 2)); |
| |
| Assert.AreEqual(2, cache.Get(1)); |
| } |
| |
| [Test] |
| public void TestReplaceAsync() |
| { |
| var cache = Cache().WrapAsync(); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| Assert.IsFalse(cache.Replace(1, 1)); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.IsTrue(cache.Replace(1, 2)); |
| |
| Assert.AreEqual(2, cache.Get(1)); |
| } |
| |
| [Test] |
| public void TestPutAll([Values(true, false)] bool async) |
| { |
| var cache = Cache(async); |
| |
| // Primitives. |
| cache.PutAll(new Dictionary<int, int> { { 1, 1 }, { 2, 2 }, { 3, 3 } }); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| Assert.AreEqual(2, cache.Get(2)); |
| Assert.AreEqual(3, cache.Get(3)); |
| |
| // Objects. |
| var cache2 = Cache<int, Container>(async); |
| |
| var obj1 = new Container(); |
| var obj2 = new Container(); |
| var obj3 = new Container(); |
| |
| obj1.Inner = obj2; |
| obj2.Inner = obj1; |
| obj3.Inner = obj2; |
| |
| cache2.PutAll(new Dictionary<int, Container> |
| { |
| {1, obj1}, |
| {2, obj2}, |
| {3, obj3} |
| }); |
| |
| var res1 = cache2[1]; |
| var res2 = cache2[2]; |
| var res3 = cache2[3]; |
| |
| Assert.AreEqual(res1, res1.Inner.Inner); |
| Assert.AreEqual(res2, res2.Inner.Inner); |
| Assert.IsNotNull(res3.Inner.Inner.Inner); |
| } |
| |
| /// <summary> |
| /// Expiry policy tests. |
| /// </summary> |
| [Test] |
| [Ignore("https://issues.apache.org/jira/browse/IGNITE-8983")] |
| public void TestWithExpiryPolicy() |
| { |
| TestWithExpiryPolicy((cache, policy) => cache.WithExpiryPolicy(policy), true); |
| } |
| |
| /// <summary> |
| /// Expiry policy tests. |
| /// </summary> |
| [Test] |
| public void TestCacheConfigurationExpiryPolicy() |
| { |
| TestWithExpiryPolicy((cache, policy) => |
| { |
| var cfg = cache.GetConfiguration(); |
| |
| cfg.Name = string.Format("expiryPolicyCache_{0}_{1}", GetType().Name, policy.GetHashCode()); |
| cfg.ExpiryPolicyFactory = new ExpiryPolicyFactory(policy); |
| |
| return cache.Ignite.CreateCache<int, int>(cfg); |
| }, false); |
| } |
| |
| /// <summary> |
| /// Expiry policy tests. |
| /// </summary> |
| private void TestWithExpiryPolicy(Func<ICache<int, int>, IExpiryPolicy, ICache<int, int>> withPolicyFunc, |
| bool origCache) |
| { |
| ICache<int, int> cache0 = Cache(0); |
| |
| int key0; |
| int key1; |
| |
| key0 = GetPrimaryKeyForCache(cache0); |
| key1 = GetPrimaryKeyForCache(Cache(1)); |
| |
| // Test unchanged expiration. |
| ICache<int, int> cache = withPolicyFunc(cache0, new ExpiryPolicy(null, null, null)); |
| cache0 = origCache ? cache0 : cache; |
| |
| cache.Put(key0, key0); |
| cache.Put(key1, key1); |
| Thread.Sleep(200); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| |
| cache.Put(key0, key0 + 1); |
| cache.Put(key1, key1 + 1); |
| Thread.Sleep(200); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| |
| cache.Get(key0); |
| cache.Get(key1); |
| Thread.Sleep(200); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| |
| cache0.RemoveAll(new List<int> { key0, key1 }); |
| |
| // Test eternal expiration. |
| cache = withPolicyFunc(cache0, new ExpiryPolicy(TimeSpan.MaxValue, TimeSpan.MaxValue, TimeSpan.MaxValue)); |
| cache0 = origCache ? cache0 : cache; |
| |
| cache.Put(key0, key0); |
| cache.Put(key1, key1); |
| Thread.Sleep(200); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| |
| cache.Put(key0, key0 + 1); |
| cache.Put(key1, key1 + 1); |
| Thread.Sleep(200); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| |
| cache.Get(key0); |
| cache.Get(key1); |
| Thread.Sleep(200); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| |
| cache0.RemoveAll(new List<int> { key0, key1 }); |
| |
| // Test regular expiration. |
| cache = withPolicyFunc(cache0, new ExpiryPolicy(TimeSpan.FromMilliseconds(100), |
| TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(100))); |
| cache0 = origCache ? cache0 : cache; |
| |
| cache.Put(key0, key0); |
| cache.Put(key1, key1); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| Thread.Sleep(200); |
| Assert.IsFalse(cache0.ContainsKey(key0)); |
| Assert.IsFalse(cache0.ContainsKey(key1)); |
| |
| cache0.Put(key0, key0); |
| cache0.Put(key1, key1); |
| cache.Put(key0, key0 + 1); |
| cache.Put(key1, key1 + 1); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| Thread.Sleep(200); |
| Assert.IsFalse(cache0.ContainsKey(key0)); |
| Assert.IsFalse(cache0.ContainsKey(key1)); |
| |
| // Test sliding expiration |
| cache0.Put(key0, key0); |
| cache0.Put(key1, key1); |
| for (var i = 0; i < 3; i++) |
| { |
| Thread.Sleep(50); |
| |
| // Prolong expiration by touching the entry |
| cache.Get(key0); |
| cache.Get(key1); |
| } |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| Thread.Sleep(200); |
| Assert.IsFalse(cache0.ContainsKey(key0)); |
| Assert.IsFalse(cache0.ContainsKey(key1)); |
| } |
| |
| /// <summary> |
| /// Expiry policy tests for zero and negative expiry values. |
| /// </summary> |
| [Test] |
| [Ignore("IGNITE-1423")] |
| public void TestWithExpiryPolicyZeroNegative() |
| { |
| ICache<int, int> cache0 = Cache(0); |
| |
| int key0; |
| int key1; |
| |
| key0 = GetPrimaryKeyForCache(cache0); |
| key1 = GetPrimaryKeyForCache(Cache(1)); |
| |
| // Test zero expiration. |
| var cache = cache0.WithExpiryPolicy(new ExpiryPolicy(TimeSpan.Zero, TimeSpan.Zero, TimeSpan.Zero)); |
| |
| cache.Put(key0, key0); |
| cache.Put(key1, key1); |
| Assert.IsFalse(cache0.ContainsKey(key0)); |
| Assert.IsFalse(cache0.ContainsKey(key1)); |
| |
| cache0.Put(key0, key0); |
| cache0.Put(key1, key1); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| cache.Put(key0, key0 + 1); |
| cache.Put(key1, key1 + 1); |
| Assert.IsFalse(cache0.ContainsKey(key0)); |
| Assert.IsFalse(cache0.ContainsKey(key1)); |
| |
| cache0.Put(key0, key0); |
| cache0.Put(key1, key1); |
| cache.Get(key0); |
| cache.Get(key1); |
| Assert.IsFalse(cache0.ContainsKey(key0)); |
| Assert.IsFalse(cache0.ContainsKey(key1)); |
| |
| cache0.RemoveAll(new List<int> { key0, key1 }); |
| |
| // Test negative expiration. |
| cache = cache0.WithExpiryPolicy(new ExpiryPolicy(TimeSpan.FromMilliseconds(-100), |
| TimeSpan.FromMilliseconds(-100), TimeSpan.FromMilliseconds(-100))); |
| |
| cache.Put(key0, key0); |
| cache.Put(key1, key1); |
| Assert.IsFalse(cache0.ContainsKey(key0)); |
| Assert.IsFalse(cache0.ContainsKey(key1)); |
| |
| cache0.Put(key0, key0); |
| cache0.Put(key1, key1); |
| Assert.IsTrue(cache0.ContainsKey(key0)); |
| Assert.IsTrue(cache0.ContainsKey(key1)); |
| cache.Put(key0, key0 + 1); |
| cache.Put(key1, key1 + 1); |
| Assert.IsFalse(cache0.ContainsKey(key0)); |
| Assert.IsFalse(cache0.ContainsKey(key1)); |
| |
| cache0.Put(key0, key0); |
| cache0.Put(key1, key1); |
| cache.Get(key0); |
| cache.Get(key1); |
| Assert.IsFalse(cache0.ContainsKey(key0)); |
| Assert.IsFalse(cache0.ContainsKey(key1)); |
| |
| cache0.RemoveAll(new List<int> { key0, key1 }); |
| } |
| |
| [Test] |
| [Ignore("IGNITE-4535")] |
| public void TestEvict() |
| { |
| var cache = Cache(); |
| |
| int key = GetPrimaryKeyForCache(cache); |
| |
| cache.Put(key, 1); |
| |
| Assert.AreEqual(1, PeekInt(cache, key)); |
| |
| cache.LocalEvict(new[] {key}); |
| |
| Assert.AreEqual(0, cache.GetLocalSize(CachePeekMode.Onheap)); |
| |
| Assert.AreEqual(0, PeekInt(cache, key)); |
| |
| Assert.AreEqual(1, cache.Get(key)); |
| |
| Assert.AreEqual(1, cache.GetLocalSize(CachePeekMode.Onheap)); |
| |
| Assert.AreEqual(1, PeekInt(cache, key)); |
| } |
| |
| [Test] |
| [Ignore("IGNITE-4535")] |
| public void TestEvictAllKeys() |
| { |
| var cache = Cache(); |
| |
| List<int> keys = GetPrimaryKeysForCache(cache, 3); |
| |
| cache.Put(keys[0], 1); |
| cache.Put(keys[1], 2); |
| cache.Put(keys[2], 3); |
| |
| Assert.AreEqual(1, PeekInt(cache, keys[0])); |
| Assert.AreEqual(2, PeekInt(cache, keys[1])); |
| Assert.AreEqual(3, PeekInt(cache, keys[2])); |
| |
| cache.LocalEvict(new List<int> { -1, keys[0], keys[1] }); |
| |
| Assert.AreEqual(1, cache.GetLocalSize(CachePeekMode.Onheap)); |
| |
| Assert.AreEqual(0, PeekInt(cache, keys[0])); |
| Assert.AreEqual(0, PeekInt(cache, keys[1])); |
| Assert.AreEqual(3, PeekInt(cache, keys[2])); |
| |
| Assert.AreEqual(1, cache.Get(keys[0])); |
| Assert.AreEqual(2, cache.Get(keys[1])); |
| |
| Assert.AreEqual(3, cache.GetLocalSize()); |
| |
| Assert.AreEqual(1, PeekInt(cache, keys[0])); |
| Assert.AreEqual(2, PeekInt(cache, keys[1])); |
| Assert.AreEqual(3, PeekInt(cache, keys[2])); |
| } |
| |
| [Test] |
| public void TestClear() |
| { |
| for (int i = 0; i < GridCount(); i++) |
| { |
| var cache = Cache(i); |
| |
| cache.Put(GetPrimaryKeyForCache(cache, 500), 1); |
| |
| Assert.IsFalse(cache.IsEmpty()); |
| } |
| |
| Cache().Clear(); |
| |
| for (int i = 0; i < GridCount(); i++) |
| Assert.IsTrue(Cache(i).IsEmpty()); |
| } |
| |
| [Test] |
| public void TestClearKey() |
| { |
| var cache = Cache(); |
| var keys = GetPrimaryKeysForCache(cache, 10); |
| |
| foreach (var key in keys) |
| cache.Put(key, 3); |
| |
| var i = cache.GetSize(); |
| |
| foreach (var key in keys) |
| { |
| cache.Clear(key); |
| |
| Assert.IsFalse(cache.ContainsKey(key)); |
| Assert.Throws<KeyNotFoundException>(() => cache.Get(key)); |
| |
| Assert.Less(cache.GetSize(), i); |
| |
| i = cache.GetSize(); |
| } |
| } |
| |
| [Test] |
| public void TestClearKeys() |
| { |
| var cache = Cache(); |
| var keys = GetPrimaryKeysForCache(cache, 10); |
| |
| foreach (var key in keys) |
| cache.Put(key, 3); |
| |
| cache.ClearAll(keys); |
| |
| Assert.IsFalse(cache.ContainsKeys(keys)); |
| } |
| |
| [Test] |
| public void TestLocalClearKey() |
| { |
| var cache = Cache(); |
| var keys = GetPrimaryKeysForCache(cache, 10); |
| |
| foreach (var key in keys) |
| cache.Put(key, 3); |
| |
| var i = cache.GetSize(); |
| |
| foreach (var key in keys) |
| { |
| cache.LocalClear(key); |
| |
| int unused; |
| Assert.IsFalse(cache.TryLocalPeek(key, out unused)); |
| |
| Assert.Less(cache.GetSize(), i); |
| |
| i = cache.GetSize(); |
| } |
| |
| cache.Clear(); |
| } |
| |
| [Test] |
| public void TestLocalClearKeys() |
| { |
| var cache = Cache(); |
| var keys = GetPrimaryKeysForCache(cache, 10); |
| |
| foreach (var key in keys) |
| cache.Put(key, 3); |
| |
| cache.LocalClearAll(keys); |
| |
| int unused; |
| |
| foreach (var key in keys) |
| Assert.IsFalse(cache.TryLocalPeek(key, out unused)); |
| |
| cache.Clear(); |
| } |
| |
| [Test] |
| public void TestRemove() |
| { |
| var cache = Cache(); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.AreEqual(true, cache.Remove(1)); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.IsFalse(cache.Remove(1, -1)); |
| Assert.IsTrue(cache.Remove(1, 1)); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| } |
| |
| [Test] |
| public void TestGetAndRemoveAsync() |
| { |
| var cache = Cache().WrapAsync(); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.AreEqual(1, cache.GetAndRemove(1).Value); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.IsFalse(cache.Remove(1, -1)); |
| Assert.IsTrue(cache.Remove(1, 1)); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| } |
| |
| [Test] |
| public void TestRemovex() |
| { |
| var cache = Cache(); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.IsFalse(cache.Remove(-1)); |
| Assert.IsTrue(cache.Remove(1)); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| } |
| |
| [Test] |
| public void TestRemoveAsync() |
| { |
| var cache = Cache().WrapAsync(); |
| |
| cache.Put(1, 1); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| |
| Assert.IsFalse(cache.Remove(-1)); |
| Assert.IsTrue(cache.Remove(1)); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| Assert.IsFalse(cache.ContainsKey(1)); |
| } |
| |
| [Test] |
| public void TestRemoveAll() |
| { |
| var cache = Cache(); |
| |
| var keys = GetPrimaryKeysForCache(cache, 2); |
| |
| cache.Put(keys[0], 1); |
| cache.Put(keys[1], 2); |
| |
| Assert.AreEqual(1, cache.Get(keys[0])); |
| Assert.AreEqual(2, cache.Get(keys[1])); |
| |
| cache.RemoveAll(); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| Assert.IsFalse(cache.ContainsKeys(keys)); |
| } |
| |
| [Test] |
| public void TestRemoveAllAsync() |
| { |
| var cache = Cache().WrapAsync(); |
| |
| List<int> keys = GetPrimaryKeysForCache(cache, 2); |
| |
| cache.Put(keys[0], 1); |
| cache.Put(keys[1], 2); |
| |
| Assert.AreEqual(1, cache.Get(keys[0])); |
| Assert.AreEqual(2, cache.Get(keys[1])); |
| |
| cache.RemoveAll(); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| Assert.IsFalse(cache.ContainsKeys(keys)); |
| } |
| |
| [Test] |
| public void TestRemoveAllKeys() |
| { |
| var cache = Cache(); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| cache.Put(1, 1); |
| cache.Put(2, 2); |
| cache.Put(3, 3); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| Assert.AreEqual(2, cache.Get(2)); |
| Assert.AreEqual(3, cache.Get(3)); |
| |
| cache.RemoveAll(new List<int> { 0, 1, 2 }); |
| |
| Assert.AreEqual(1, cache.GetSize(CachePeekMode.Primary)); |
| |
| Assert.IsFalse(cache.ContainsKeys(new[] {1, 2})); |
| Assert.AreEqual(3, cache.Get(3)); |
| } |
| |
| [Test] |
| public void TestRemoveAllKeysAsync() |
| { |
| var cache = Cache().WrapAsync(); |
| |
| Assert.AreEqual(0, cache.GetSize()); |
| |
| cache.Put(1, 1); |
| cache.Put(2, 2); |
| cache.Put(3, 3); |
| |
| Assert.AreEqual(1, cache.Get(1)); |
| Assert.AreEqual(2, cache.Get(2)); |
| Assert.AreEqual(3, cache.Get(3)); |
| |
| cache.RemoveAll(new List<int> { 0, 1, 2 }); |
| |
| Assert.AreEqual(1, cache.GetSize(CachePeekMode.Primary)); |
| |
| Assert.IsFalse(cache.ContainsKeys(new[] {1, 2})); |
| Assert.AreEqual(3, cache.Get(3)); |
| } |
| |
| [Test] |
| public void TestSizes([Values(true, false)] bool async) |
| { |
| for (int i = 0; i < GridCount(); i++) |
| { |
| var cache = Cache(i, async); |
| |
| List<int> keys = GetPrimaryKeysForCache(cache, 2); |
| |
| foreach (int key in keys) |
| cache.Put(key, 1); |
| |
| Assert.IsTrue(cache.GetSize() >= 2); |
| Assert.AreEqual(cache.GetSize(), cache.GetSizeLong()); |
| Assert.AreEqual(2, cache.GetLocalSizeLong(CachePeekMode.Primary)); |
| Assert.AreEqual(2, cache.GetLocalSize(CachePeekMode.Primary)); |
| |
| foreach (var key in keys) |
| { |
| var p = GetIgnite(i).GetAffinity(cache.Name).GetPartition(key); |
| |
| Assert.GreaterOrEqual(cache.GetSizeLong(p, CachePeekMode.Primary), 1); |
| } |
| } |
| |
| ICache<int, int> cache0 = Cache(async); |
| |
| Assert.AreEqual(GridCount() * 2, cache0.GetSize(CachePeekMode.Primary)); |
| Assert.AreEqual(GridCount() * 2, cache0.GetSizeLong(CachePeekMode.Primary)); |
| |
| if (!ReplicatedCache()) |
| { |
| int nearKey = NearKeyForCache(cache0); |
| |
| cache0.Put(nearKey, 1); |
| |
| Assert.AreEqual(NearEnabled() ? 1 : 0, cache0.GetSize(CachePeekMode.Near)); |
| Assert.AreEqual(NearEnabled() ? 1 : 0, cache0.GetSizeLong(CachePeekMode.Near)); |
| } |
| } |
| |
| [Test] |
| public void TestLocalSize() |
| { |
| var cache = Cache(); |
| var keys = GetPrimaryKeysForCache(cache, 3); |
| |
| cache.Put(keys[0], 1); |
| cache.Put(keys[1], 2); |
| |
| var localSize = cache.GetLocalSize(); |
| Assert.AreEqual(localSize, cache.GetLocalSizeLong()); |
| |
| cache.LocalEvict(keys.Take(2).ToArray()); |
| |
| Assert.AreEqual(0, cache.GetLocalSize(CachePeekMode.Onheap)); |
| Assert.AreEqual(0, cache.GetLocalSizeLong(CachePeekMode.Onheap)); |
| Assert.AreEqual(localSize, cache.GetLocalSize(CachePeekMode.All)); |
| Assert.AreEqual(localSize, cache.GetLocalSizeLong(CachePeekMode.All)); |
| |
| cache.Put(keys[2], 3); |
| |
| Assert.AreEqual(localSize + 1, cache.GetLocalSize(CachePeekMode.All)); |
| Assert.AreEqual(localSize + 1, cache.GetLocalSizeLong(CachePeekMode.All)); |
| |
| foreach (var key in keys) |
| { |
| var p = Affinity().GetPartition(key); |
| |
| Assert.GreaterOrEqual(cache.GetLocalSizeLong(p, CachePeekMode.All), 1); |
| } |
| |
| cache.RemoveAll(keys.Take(2).ToArray()); |
| } |
| |
| /// <summary> |
| /// Test enumerators. |
| /// </summary> |
| [Test] |
| [SuppressMessage("ReSharper", "PossibleMultipleEnumeration")] |
| public void TestEnumerators() |
| { |
| var cache = Cache(); |
| var keys = GetPrimaryKeysForCache(cache, 2); |
| |
| cache.Put(keys[0], keys[0] + 1); |
| cache.Put(keys[1], keys[1] + 1); |
| |
| // Check distributed enumerator. |
| IEnumerable<ICacheEntry<int, int>> e = cache; |
| |
| CheckEnumerator(e.GetEnumerator(), keys); |
| CheckEnumerator(e.GetEnumerator(), keys); |
| |
| // Check local enumerator. |
| e = cache.GetLocalEntries(); |
| |
| CheckEnumerator(e.GetEnumerator(), keys); |
| CheckEnumerator(e.GetEnumerator(), keys); |
| |
| // Evict and check peek modes. |
| cache.LocalEvict(new List<int> { keys[0] } ); |
| |
| // TODO: IGNITE-4535 |
| //e = cache.GetLocalEntries(CachePeekMode.Onheap); |
| //CheckEnumerator(e.GetEnumerator(), new List<int> { keys[1] }); |
| //CheckEnumerator(e.GetEnumerator(), new List<int> { keys[1] }); |
| |
| e = cache.GetLocalEntries(CachePeekMode.All); |
| CheckEnumerator(e.GetEnumerator(), keys); |
| CheckEnumerator(e.GetEnumerator(), keys); |
| |
| cache.Remove(keys[0]); |
| } |
| |
| /// <summary> |
| /// Check enumerator content. |
| /// </summary> |
| /// <param name="e">Enumerator.</param> |
| /// <param name="keys">Keys.</param> |
| private static void CheckEnumerator(IEnumerator<ICacheEntry<int, int>> e, IList<int> keys) |
| { |
| CheckEnumerator0(e, keys); |
| |
| e.Reset(); |
| |
| CheckEnumerator0(e, keys); |
| |
| e.Dispose(); |
| |
| Assert.Throws<ObjectDisposedException>(() => { e.MoveNext(); }); |
| Assert.Throws<ObjectDisposedException>(() => { var entry = e.Current; }); |
| Assert.Throws<ObjectDisposedException>(e.Reset); |
| |
| e.Dispose(); |
| } |
| |
| /// <summary> |
| /// Check enumerator content. |
| /// </summary> |
| /// <param name="e">Enumerator.</param> |
| /// <param name="keys">Keys.</param> |
| private static void CheckEnumerator0(IEnumerator<ICacheEntry<int, int>> e, IList<int> keys) |
| { |
| Assert.Throws<InvalidOperationException>(() => { var entry = e.Current; }); |
| |
| int cnt = 0; |
| |
| while (e.MoveNext()) |
| { |
| ICacheEntry<int, int> entry = e.Current; |
| |
| Assert.IsNotNull(entry); |
| |
| Assert.IsTrue(keys.Contains(entry.Key), "Unexpected entry: " + entry); |
| |
| Assert.AreEqual(entry.Key + 1, entry.Value); |
| |
| cnt++; |
| } |
| |
| Assert.AreEqual(keys.Count, cnt); |
| |
| Assert.IsFalse(e.MoveNext()); |
| |
| Assert.Throws<InvalidOperationException>(() => { var entry = e.Current; }); |
| } |
| |
| [Test] |
| public void TestPutGetBinary() |
| { |
| var cache = Cache<int, BinarizablePerson>(); |
| |
| BinarizablePerson obj1 = new BinarizablePerson("obj1", 1); |
| |
| cache.Put(1, obj1); |
| |
| obj1 = cache.Get(1); |
| |
| Assert.AreEqual("obj1", obj1.Name); |
| Assert.AreEqual(1, obj1.Age); |
| } |
| |
| [Test] |
| public void TestPutGetBinaryAsync() |
| { |
| var cache = Cache<int, BinarizablePerson>().WrapAsync(); |
| |
| BinarizablePerson obj1 = new BinarizablePerson("obj1", 1); |
| |
| cache.Put(1, obj1); |
| |
| obj1 = cache.Get(1); |
| |
| Assert.AreEqual("obj1", obj1.Name); |
| Assert.AreEqual(1, obj1.Age); |
| } |
| |
| [Test] |
| public void TestPutGetBinaryKey() |
| { |
| var cache = Cache<CacheTestKey, string>(); |
| |
| int cnt = 100; |
| |
| for (int i = 0; i < cnt; i++) |
| cache.Put(new CacheTestKey(i), "val-" + i); |
| |
| for (int i = 0; i < cnt; i++) |
| Assert.AreEqual("val-" + i, cache.Get(new CacheTestKey(i))); |
| } |
| |
| [Test] |
| public void TestGetAsync2() |
| { |
| var cache = Cache(); |
| |
| for (int i = 0; i < 100; i++) |
| cache.Put(i, i); |
| |
| var futs = new List<Task<int>>(); |
| |
| for (int i = 0; i < 1000; i++) |
| { |
| futs.Add(cache.GetAsync(i % 100)); |
| } |
| |
| for (int i = 0; i < 1000; i++) { |
| Assert.AreEqual(i % 100, futs[i].Result, "Unexpected result: " + i); |
| |
| Assert.IsTrue(futs[i].IsCompleted); |
| } |
| } |
| |
| [Test] |
| [Category(TestUtils.CategoryIntensive)] |
| public void TestGetAsyncMultithreaded() |
| { |
| var cache = Cache(); |
| |
| for (int i = 0; i < 100; i++) |
| cache.Put(i, i); |
| |
| TestUtils.RunMultiThreaded(() => |
| { |
| for (int i = 0; i < 100; i++) |
| { |
| var futs = new List<Task<int>>(); |
| |
| for (int j = 0; j < 100; j++) |
| futs.Add(cache.GetAsync(j)); |
| |
| for (int j = 0; j < 100; j++) |
| Assert.AreEqual(j, futs[j].Result); |
| } |
| }, 10); |
| } |
| |
| [Test] |
| [Category(TestUtils.CategoryIntensive)] |
| public void TestPutxAsyncMultithreaded() |
| { |
| var cache = Cache(); |
| |
| TestUtils.RunMultiThreaded(() => |
| { |
| Random rnd = new Random(); |
| |
| for (int i = 0; i < 50; i++) |
| { |
| var futs = new List<Task>(); |
| |
| for (int j = 0; j < 10; j++) |
| futs.Add(cache.PutAsync(rnd.Next(1000), i)); |
| |
| foreach (var fut in futs) |
| fut.Wait(); |
| } |
| }, 5); |
| } |
| |
| [Test] |
| [Category(TestUtils.CategoryIntensive)] |
| public void TestPutGetAsyncMultithreaded() |
| { |
| var cache = Cache<CacheTestKey, BinarizablePerson>(); |
| |
| const int threads = 10; |
| const int objPerThread = 1000; |
| |
| int cntr = 0; |
| |
| TestUtils.RunMultiThreaded(() => |
| { |
| // ReSharper disable once AccessToModifiedClosure |
| int threadIdx = Interlocked.Increment(ref cntr); |
| |
| var futs = new List<Task>(); |
| |
| for (int i = 0; i < objPerThread; i++) |
| { |
| int key = threadIdx * objPerThread + i; |
| |
| futs.Add(cache.PutAsync(new CacheTestKey(key), new BinarizablePerson("Person-" + key, key))); |
| } |
| |
| foreach (var fut in futs) |
| { |
| fut.Wait(); |
| |
| Assert.IsTrue(fut.IsCompleted); |
| } |
| }, threads); |
| |
| for (int i = 0; i < threads; i++) |
| { |
| int threadIdx = i + 1; |
| |
| for (int j = 0; j < objPerThread; j++) |
| { |
| int key = threadIdx * objPerThread + i; |
| |
| var p = cache.GetAsync(new CacheTestKey(key)).Result; |
| |
| Assert.IsNotNull(p); |
| Assert.AreEqual(key, p.Age); |
| Assert.AreEqual("Person-" + key, p.Name); |
| } |
| } |
| |
| cntr = 0; |
| |
| TestUtils.RunMultiThreaded(() => |
| { |
| int threadIdx = Interlocked.Increment(ref cntr); |
| |
| for (int i = 0; i < objPerThread; i++) |
| { |
| int key = threadIdx * objPerThread + i; |
| |
| cache.PutAsync(new CacheTestKey(key), new BinarizablePerson("Person-" + key, key)).Wait(); |
| } |
| }, threads); |
| |
| cntr = 0; |
| |
| TestUtils.RunMultiThreaded(() => |
| { |
| int threadIdx = Interlocked.Increment(ref cntr); |
| |
| var futs = new List<Task<BinarizablePerson>>(); |
| |
| for (int i = 0; i < objPerThread; i++) |
| { |
| int key = threadIdx * objPerThread + i; |
| |
| futs.Add(cache.GetAsync(new CacheTestKey(key))); |
| } |
| |
| for (int i = 0; i < objPerThread; i++) |
| { |
| var fut = futs[i]; |
| |
| int key = threadIdx * objPerThread + i; |
| |
| var p = fut.Result; |
| |
| Assert.IsNotNull(p); |
| Assert.AreEqual(key, p.Age); |
| Assert.AreEqual("Person-" + key, p.Name); |
| } |
| }, threads); |
| } |
| |
| [Test] |
| [Category(TestUtils.CategoryIntensive)] |
| public void TestAsyncMultithreadedKeepBinary() |
| { |
| var cache = Cache().WithKeepBinary<CacheTestKey, BinarizablePerson>(); |
| var portCache = Cache().WithKeepBinary<CacheTestKey, IBinaryObject>(); |
| |
| const int threads = 10; |
| const int objPerThread = 1000; |
| |
| int cntr = 0; |
| |
| TestUtils.RunMultiThreaded(() => |
| { |
| // ReSharper disable once AccessToModifiedClosure |
| int threadIdx = Interlocked.Increment(ref cntr); |
| |
| var futs = new List<Task>(); |
| |
| for (int i = 0; i < objPerThread; i++) |
| { |
| int key = threadIdx * objPerThread + i; |
| |
| var task = cache.PutAsync(new CacheTestKey(key), new BinarizablePerson("Person-" + key, key)); |
| |
| futs.Add(task); |
| } |
| |
| foreach (var fut in futs) |
| fut.Wait(); |
| }, threads); |
| |
| for (int i = 0; i < threads; i++) |
| { |
| int threadIdx = i + 1; |
| |
| for (int j = 0; j < objPerThread; j++) |
| { |
| int key = threadIdx * objPerThread + i; |
| |
| IBinaryObject p = portCache.Get(new CacheTestKey(key)); |
| |
| Assert.IsNotNull(p); |
| Assert.AreEqual(key, p.GetField<int>("age")); |
| Assert.AreEqual("Person-" + key, p.GetField<string>("name")); |
| } |
| } |
| |
| cntr = 0; |
| |
| TestUtils.RunMultiThreaded(() => |
| { |
| int threadIdx = Interlocked.Increment(ref cntr); |
| |
| var futs = new List<Task<IBinaryObject>>(); |
| |
| for (int i = 0; i < objPerThread; i++) |
| { |
| int key = threadIdx * objPerThread + i; |
| |
| futs.Add(portCache.GetAsync(new CacheTestKey(key))); |
| } |
| |
| for (int i = 0; i < objPerThread; i++) |
| { |
| var fut = futs[i]; |
| |
| int key = threadIdx * objPerThread + i; |
| |
| var p = fut.Result; |
| |
| Assert.IsNotNull(p); |
| Assert.AreEqual(key, p.GetField<int>("age")); |
| Assert.AreEqual("Person-" + key, p.GetField<string>("name")); |
| } |
| }, threads); |
| |
| cntr = 0; |
| |
| TestUtils.RunMultiThreaded(() => |
| { |
| int threadIdx = Interlocked.Increment(ref cntr); |
| |
| var futs = new List<Task<bool>>(); |
| |
| for (int i = 0; i < objPerThread; i++) |
| { |
| int key = threadIdx * objPerThread + i; |
| |
| futs.Add(cache.RemoveAsync(new CacheTestKey(key))); |
| } |
| |
| for (int i = 0; i < objPerThread; i++) |
| { |
| var fut = futs[i]; |
| |
| Assert.IsTrue(fut.Result); |
| } |
| }, threads); |
| } |
| |
| /// <summary> |
| /// Test thraed-locals leak. |
| /// </summary> |
| [Test] |
| [Category(TestUtils.CategoryIntensive)] |
| public void TestThreadLocalLeak() |
| { |
| var cache = Cache<string, string>(); |
| |
| Exception err = null; |
| |
| const int threadCnt = 10; |
| |
| Thread[] threads = new Thread[threadCnt]; |
| |
| ThreadStart[] threadStarts = new ThreadStart[threadCnt]; |
| |
| for (int j = 0; j < threadCnt; j++) |
| { |
| string key = "key" + j; |
| |
| threadStarts[j] = () => |
| { |
| try |
| { |
| cache.Put(key, key); |
| |
| Assert.AreEqual(key, cache.Get(key)); |
| } |
| catch (Exception e) |
| { |
| Interlocked.CompareExchange(ref err, e, null); |
| |
| Assert.Fail("Unexpected error: " + e); |
| } |
| }; |
| } |
| |
| for (int i = 0; i < 100 && err == null; i++) |
| { |
| for (int j = 0 ; j < threadCnt; j++) { |
| Thread t = new Thread(threadStarts[j]); |
| |
| threads[j] = t; |
| } |
| |
| foreach (Thread t in threads) |
| t.Start(); |
| |
| foreach (Thread t in threads) |
| t.Join(); |
| |
| if (i % 500 == 0) |
| { |
| Console.WriteLine("Iteration: " + i); |
| |
| GC.Collect(); |
| } |
| } |
| |
| Assert.IsNull(err); |
| } |
| |
| /** |
| * Test tries to provoke garbage collection for .NET future before it was completed to verify |
| * futures pinning works. |
| */ |
| [Test] |
| [Category(TestUtils.CategoryIntensive)] |
| public void TestFuturesGc() |
| { |
| var cache = Cache(); |
| |
| cache.PutAsync(1, 1); |
| |
| for (int i = 0; i < 10; i++) |
| { |
| TestUtils.RunMultiThreaded(() => |
| { |
| for (int j = 0; j < 1000; j++) |
| cache.GetAsync(1); |
| }, 5); |
| |
| GC.Collect(); |
| |
| Assert.AreEqual(1, cache.GetAsync(1).Result); |
| } |
| |
| Thread.Sleep(2000); |
| } |
| |
| [Test] |
| public void TestPartitions() |
| { |
| ICacheAffinity aff = Affinity(); |
| |
| for (int i = 0; i < 5; i++ ) |
| Assert.AreEqual(CachePartitions(), aff.Partitions); |
| } |
| |
| [Test] |
| public void TestKeyPartition() |
| { |
| ICacheAffinity aff = Affinity(); |
| |
| { |
| ISet<int> parts = new HashSet<int>(); |
| |
| for (int i = 0; i < 1000; i++) |
| parts.Add(aff.GetPartition(i)); |
| |
| Assert.IsTrue(parts.Count > 10); |
| } |
| |
| { |
| ISet<int> parts = new HashSet<int>(); |
| |
| for (int i = 0; i < 1000; i++) |
| parts.Add(aff.GetPartition("key" + i)); |
| |
| Assert.IsTrue(parts.Count > 10); |
| } |
| } |
| |
| [Test] |
| public void TestIsPrimaryOrBackup() |
| { |
| ICacheAffinity aff = Affinity(); |
| |
| ICollection<IClusterNode> nodes = GetIgnite(0).GetCluster().GetNodes(); |
| |
| Assert.IsTrue(nodes.Count > 0); |
| |
| IClusterNode node = nodes.First(); |
| |
| { |
| bool found = false; |
| |
| for (int i = 0; i < 1000; i++) |
| { |
| if (aff.IsPrimary(node, i)) |
| { |
| Assert.IsTrue(aff.IsPrimaryOrBackup(node, i)); |
| |
| found = true; |
| |
| if (nodes.Count > 1) |
| Assert.IsFalse(aff.IsPrimary(nodes.Last(), i)); |
| |
| break; |
| } |
| } |
| |
| Assert.IsTrue(found, "Failed to find primary key for node " + node); |
| } |
| |
| if (nodes.Count > 1) |
| { |
| bool found = false; |
| |
| for (int i = 0; i < 1000; i++) |
| { |
| if (aff.IsBackup(node, i)) |
| { |
| Assert.IsTrue(aff.IsPrimaryOrBackup(node, i)); |
| |
| found = true; |
| |
| break; |
| } |
| } |
| |
| Assert.IsTrue(found, "Failed to find backup key for node " + node); |
| } |
| } |
| |
| [Test] |
| public void TestNodePartitions() |
| { |
| ICacheAffinity aff = Affinity(); |
| |
| ICollection<IClusterNode> nodes = GetIgnite(0).GetCluster().GetNodes(); |
| |
| Assert.IsTrue(nodes.Count > 0); |
| |
| if (nodes.Count == 1) |
| { |
| IClusterNode node = nodes.First(); |
| |
| int[] parts = aff.GetBackupPartitions(node); |
| |
| Assert.AreEqual(0, parts.Length); |
| |
| parts = aff.GetAllPartitions(node); |
| |
| Assert.AreEqual(CachePartitions(), parts.Length); |
| } |
| else |
| { |
| IList<int> allPrimaryParts = new List<int>(); |
| IList<int> allBackupParts = new List<int>(); |
| IList<int> allParts = new List<int>(); |
| |
| foreach(IClusterNode node in nodes) { |
| int[] parts = aff.GetPrimaryPartitions(node); |
| |
| foreach (int part in parts) |
| allPrimaryParts.Add(part); |
| |
| parts = aff.GetBackupPartitions(node); |
| |
| foreach (int part in parts) |
| allBackupParts.Add(part); |
| |
| parts = aff.GetAllPartitions(node); |
| |
| foreach (int part in parts) |
| allParts.Add(part); |
| } |
| |
| Assert.AreEqual(CachePartitions(), allPrimaryParts.Count); |
| Assert.AreEqual(CachePartitions() * Backups(), allBackupParts.Count); |
| Assert.AreEqual(CachePartitions() * (Backups() + 1), allParts.Count); |
| } |
| } |
| |
| [Test] |
| public void TestAffinityKey() |
| { |
| ICacheAffinity aff = Affinity(); |
| |
| Assert.AreEqual(10, aff.GetAffinityKey<int, int>(10)); |
| |
| Assert.AreEqual("string", aff.GetAffinityKey<string, string>("string")); |
| } |
| |
| [Test] |
| public void TestMapToNode() |
| { |
| ICacheAffinity aff = Affinity(); |
| |
| const int key = 1; |
| |
| IClusterNode node = aff.MapKeyToNode(key); |
| |
| Assert.IsNotNull(node); |
| |
| Assert.IsTrue(GetIgnite(0).GetCluster().GetNodes().Contains(node)); |
| |
| Assert.IsTrue(aff.IsPrimary(node, key)); |
| |
| Assert.IsTrue(aff.IsPrimaryOrBackup(node, key)); |
| |
| Assert.IsFalse(aff.IsBackup(node, key)); |
| |
| int part = aff.GetPartition(key); |
| |
| IClusterNode partNode = aff.MapPartitionToNode(part); |
| |
| Assert.AreEqual(node, partNode); |
| } |
| |
| [Test] |
| public void TestMapToPrimaryAndBackups() |
| { |
| ICacheAffinity aff = Affinity(); |
| |
| const int key = 1; |
| |
| IList<IClusterNode> nodes = aff.MapKeyToPrimaryAndBackups(key); |
| |
| Assert.IsTrue(nodes.Count > 0); |
| |
| for (int i = 0; i < nodes.Count; i++) |
| { |
| if (i == 0) |
| Assert.IsTrue(aff.IsPrimary(nodes[i], key)); |
| else |
| Assert.IsTrue(aff.IsBackup(nodes[i], key)); |
| } |
| |
| int part = aff.GetPartition(key); |
| |
| IList<IClusterNode> partNodes = aff.MapPartitionToPrimaryAndBackups(part); |
| |
| Assert.AreEqual(nodes, partNodes); |
| } |
| |
| [Test] |
| public void TestMapKeysToNodes() |
| { |
| ICacheAffinity aff = Affinity(); |
| |
| IList<int> keys = new List<int> {1, 2, 3}; |
| |
| IDictionary<IClusterNode, IList<int>> map = aff.MapKeysToNodes(keys); |
| |
| Assert.IsTrue(map.Count > 0); |
| |
| foreach (int key in keys) |
| { |
| IClusterNode primary = aff.MapKeyToNode(key); |
| |
| Assert.IsTrue(map.ContainsKey(primary)); |
| |
| IList<int> nodeKeys = map[primary]; |
| |
| Assert.IsNotNull(nodeKeys); |
| |
| Assert.IsTrue(nodeKeys.Contains(key)); |
| } |
| } |
| |
| [Test] |
| public void TestMapPartitionsToNodes() |
| { |
| ICacheAffinity aff = Affinity(); |
| |
| IList<int> parts = new List<int> { 1, 2, 3 }; |
| |
| IDictionary<int, IClusterNode> map = aff.MapPartitionsToNodes(parts); |
| |
| Assert.AreEqual(parts.Count, map.Count); |
| |
| foreach (int part in parts) |
| { |
| Assert.IsTrue(map.ContainsKey(part)); |
| |
| IClusterNode primary = aff.MapPartitionToNode(part); |
| |
| Assert.AreEqual(primary, map[part], "Wrong node for partition: " + part); |
| } |
| } |
| |
| [Test] |
| public void TestKeepBinaryFlag() |
| { |
| TestKeepBinaryFlag(false); |
| } |
| |
| [Test] |
| public void TestKeepBinaryFlagAsync() |
| { |
| TestKeepBinaryFlag(true); |
| } |
| |
| [Test] |
| public void TestNearKeys() |
| { |
| if (!NearEnabled()) |
| return; |
| |
| const int count = 20; |
| |
| var cache = Cache(); |
| var aff = cache.Ignite.GetAffinity(cache.Name); |
| var node = cache.Ignite.GetCluster().GetLocalNode(); |
| |
| for (int i = 0; i < count; i++) |
| cache.Put(i, -i - 1); |
| |
| var nearKeys = Enumerable.Range(0, count).Where(x => !aff.IsPrimaryOrBackup(node, x)).ToArray(); |
| |
| var nearKeysString = nearKeys.Select(x => x.ToString()).Aggregate((x, y) => x + ", " + y); |
| |
| Console.WriteLine("Near keys: " + nearKeysString); |
| |
| foreach (var nearKey in nearKeys.Take(3)) |
| Assert.AreNotEqual(0, cache.Get(nearKey)); |
| } |
| |
| [Test] |
| public void TestSerializable() |
| { |
| var cache = Cache<int, TestSerializableObject>(); |
| |
| var obj = new TestSerializableObject {Name = "Vasya", Id = 128}; |
| |
| cache.Put(1, obj); |
| |
| var resultObj = cache.Get(1); |
| |
| Assert.AreEqual(obj, resultObj); |
| } |
| |
| [Test] |
| public void TestSerializableKeepBinary() |
| { |
| var cache = Cache<int, TestSerializableObject>(); |
| |
| var obj = new TestSerializableObject {Name = "Vasya", Id = 128}; |
| |
| cache.Put(1, obj); |
| |
| var binaryRes = cache.WithKeepBinary<int, IBinaryObject>().Get(1); |
| |
| var resultObj = binaryRes.Deserialize<TestSerializableObject>(); |
| |
| Assert.AreEqual(obj, resultObj); |
| } |
| |
| [Test] |
| public void TestInvoke() |
| { |
| TestInvoke(false); |
| } |
| |
| [Test] |
| public void TestInvokeAsync() |
| { |
| TestInvoke(true); |
| } |
| |
| private void TestInvoke(bool async) |
| { |
| TestInvoke<AddArgCacheEntryProcessor>(async); |
| TestInvoke<BinarizableAddArgCacheEntryProcessor>(async); |
| |
| Assert.Throws<Exception>(() => TestInvoke<NonSerializableCacheEntryProcessor>(async)); |
| } |
| |
| private void TestInvoke<T>(bool async) where T: AddArgCacheEntryProcessor, new() |
| { |
| var cache = async ? Cache().WrapAsync() : Cache(); |
| |
| cache.Clear(); |
| |
| const int key = 1; |
| const int value = 3; |
| const int arg = 5; |
| |
| cache.Put(key, value); |
| |
| // Existing entry |
| Assert.AreEqual(value + arg, cache.Invoke(key, new T(), arg)); |
| Assert.AreEqual(value + arg, cache.Get(key)); |
| |
| // Non-existing entry |
| Assert.AreEqual(arg, cache.Invoke(10, new T {Exists = false}, arg)); |
| Assert.AreEqual(arg, cache.Get(10)); |
| |
| // Remove entry |
| Assert.AreEqual(0, cache.Invoke(key, new T {Remove = true}, arg)); |
| Assert.AreEqual(false, cache.ContainsKey(key)); |
| |
| // Test exceptions |
| AssertThrowsCacheEntryProcessorException(() => cache.Invoke(key, new T {ThrowErr = true}, arg)); |
| AssertThrowsCacheEntryProcessorException( |
| () => cache.Invoke(key, new T {ThrowErrBinarizable = true}, arg)); |
| AssertThrowsCacheEntryProcessorException( |
| () => cache.Invoke(key, new T { ThrowErrNonSerializable = true }, arg), "ExpectedException"); |
| } |
| |
| /// <summary> |
| /// Asserts that specified action throws a CacheEntryProcessorException. |
| /// </summary> |
| private static void AssertThrowsCacheEntryProcessorException(Action action, string containsText = null) |
| { |
| var ex = Assert.Throws<CacheEntryProcessorException>(() => action()); |
| |
| Assert.IsInstanceOf<JavaException>(ex.InnerException); |
| |
| if (string.IsNullOrEmpty(containsText)) |
| { |
| Assert.AreEqual(AddArgCacheEntryProcessor.ExceptionText, ex.GetBaseException().Message); |
| } |
| else |
| { |
| Assert.IsTrue(ex.ToString().Contains(containsText), "Expected: " + containsText + ", actual: " + ex); |
| } |
| } |
| |
| [Test] |
| public void TestInvokeAll() |
| { |
| TestInvokeAll(false); |
| } |
| |
| [Test] |
| public void TestInvokeAllAsync() |
| { |
| TestInvokeAll(true); |
| } |
| |
| private void TestInvokeAll(bool async) |
| { |
| for (var i = 1; i < 10; i++) |
| { |
| TestInvokeAll<AddArgCacheEntryProcessor>(async, i); |
| TestInvokeAll<BinarizableAddArgCacheEntryProcessor>(async, i); |
| Assert.Throws<Exception>(() => TestInvokeAll<NonSerializableCacheEntryProcessor>(async, i)); |
| } |
| } |
| |
| private void TestInvokeAll<T>(bool async, int entryCount) where T : AddArgCacheEntryProcessor, new() |
| { |
| var cache = async ? Cache().WrapAsync() : Cache(); |
| |
| var entries = Enumerable.Range(1, entryCount).ToDictionary(x => x, x => x + 1); |
| |
| cache.PutAll(entries); |
| |
| const int arg = 5; |
| |
| // Existing entries |
| var res = cache.InvokeAll(entries.Keys, new T(), arg); |
| |
| var results = res.OrderBy(x => x.Key).Select(x => x.Result); |
| var expectedResults = entries.OrderBy(x => x.Key).Select(x => x.Value + arg); |
| |
| Assert.IsTrue(results.SequenceEqual(expectedResults)); |
| |
| var resultEntries = cache.GetAll(entries.Keys); |
| |
| Assert.IsTrue(resultEntries.All(x => x.Value == x.Key + 1 + arg)); |
| |
| // Remove entries |
| res = cache.InvokeAll(entries.Keys, new T {Remove = true}, arg); |
| |
| Assert.IsTrue(res.All(x => x.Result == 0)); |
| Assert.AreEqual(0, cache.GetAll(entries.Keys).Count); |
| |
| // Non-existing entries |
| res = cache.InvokeAll(entries.Keys, new T {Exists = false}, arg); |
| |
| Assert.IsTrue(res.All(x => x.Result == arg)); |
| Assert.IsTrue(cache.GetAll(entries.Keys).All(x => x.Value == arg)); |
| |
| // Test exceptions |
| var errKey = entries.Keys.Reverse().Take(5).Last(); |
| |
| TestInvokeAllException(cache, entries, new T { ThrowErr = true, ThrowOnKey = errKey }, arg, errKey); |
| TestInvokeAllException(cache, entries, new T { ThrowErrBinarizable = true, ThrowOnKey = errKey }, |
| arg, errKey); |
| TestInvokeAllException(cache, entries, new T { ThrowErrNonSerializable = true, ThrowOnKey = errKey }, |
| arg, errKey, "ExpectedException"); |
| |
| } |
| |
| private static void TestInvokeAllException<T>(ICache<int, int> cache, Dictionary<int, int> entries, |
| T processor, int arg, int errKey, string exceptionText = null) where T : AddArgCacheEntryProcessor |
| { |
| var res = cache.InvokeAll(entries.Keys, processor, arg); |
| |
| foreach (var procRes in res) |
| { |
| if (procRes.Key == errKey) |
| // ReSharper disable once AccessToForEachVariableInClosure |
| AssertThrowsCacheEntryProcessorException(() => { var x = procRes.Result; }, exceptionText); |
| else |
| Assert.Greater(procRes.Result, 0); |
| } |
| } |
| |
| /// <summary> |
| /// Test skip-store semantics. |
| /// </summary> |
| [Test] |
| public void TestSkipStore() |
| { |
| var cache = (CacheImpl<int, int>) Cache(); |
| |
| Assert.IsFalse(cache.IsSkipStore); |
| |
| // Ensure correct flag set. |
| var cacheSkipStore1 = (CacheImpl<int, int>) cache.WithSkipStore(); |
| |
| Assert.AreNotSame(cache, cacheSkipStore1); |
| Assert.IsFalse(cache.IsSkipStore); |
| Assert.IsTrue(cacheSkipStore1.IsSkipStore); |
| |
| // Ensure that the same instance is returned if flag is already set. |
| var cacheSkipStore2 = (CacheImpl<int, int>) cacheSkipStore1.WithSkipStore(); |
| |
| Assert.IsTrue(cacheSkipStore2.IsSkipStore); |
| Assert.AreSame(cacheSkipStore1, cacheSkipStore2); |
| |
| // Ensure other flags are preserved. |
| Assert.IsTrue(((CacheImpl<int, int>) cache.WithKeepBinary<int, int>().WithSkipStore()).IsKeepBinary); |
| } |
| |
| [Test] |
| public void TestRebalance() |
| { |
| var cache = Cache(); |
| |
| var task = cache.Rebalance(); |
| |
| task.Wait(); |
| } |
| |
| [Test] |
| public void TestCacheNames() |
| { |
| var cacheNames = GetIgnite(0).GetCacheNames(); |
| var expectedNames = new[] |
| { |
| "partitioned", "partitioned_atomic", |
| "partitioned_near", "partitioned_atomic_near", "replicated", "replicated_atomic" |
| }; |
| |
| Assert.AreEqual(0, expectedNames.Except(cacheNames).Count()); |
| } |
| |
| |
| [Test] |
| public void TestIndexer() |
| { |
| var cache = Cache(); |
| |
| Assert.Throws<KeyNotFoundException>(() => Console.WriteLine(cache[0])); // missing key throws |
| |
| cache[1] = 5; |
| |
| Assert.AreEqual(5, cache[1]); |
| } |
| |
| /// <summary> |
| /// Tests that operations in TransactionScope work correctly in any cache mode (tx or non-tx). |
| /// </summary> |
| [Test] |
| public void TestTransactionScope() |
| { |
| var cache = Cache(); |
| |
| cache[1] = 1; |
| |
| using (var ts = new TransactionScope()) |
| { |
| cache[1] = 2; |
| |
| ts.Complete(); |
| } |
| |
| Assert.AreEqual(2, cache[1]); |
| } |
| |
| /// <summary> |
| /// Tests that value object can reference key object. |
| /// </summary> |
| [Test] |
| public void TestPutGetWithKeyObjectReferenceInValue([Values(true, false)] bool async) |
| { |
| var cache = Cache<Container, Container>(async); |
| |
| var key = new Container {Id = 1}; |
| var val = new Container {Id = 2, Inner = key}; |
| |
| cache.Put(key, val); |
| |
| var res = cache.Get(key); |
| |
| Assert.AreEqual(2, res.Id); |
| Assert.AreEqual(1, res.Inner.Id); |
| } |
| |
| /// <summary> |
| /// Tests that key and value objects can reference the same nested object. |
| /// </summary> |
| [Test] |
| public void TestPutGetWithSharedObjectReferenceInKeyAndValue([Values(true, false)] bool async) |
| { |
| var cache = Cache<Container, Container>(async); |
| |
| var inner = new Container {Id = -1}; |
| var key = new Container {Id = 1, Inner = inner}; |
| var val = new Container {Id = 2, Inner = inner}; |
| |
| cache.Put(key, val); |
| |
| var res = cache.Get(key); |
| |
| Assert.AreEqual(2, res.Id); |
| Assert.AreEqual(-1, res.Inner.Id); |
| } |
| |
| private void TestKeepBinaryFlag(bool async) |
| { |
| var cache0 = async ? Cache().WrapAsync() : Cache(); |
| |
| var cache = cache0.WithKeepBinary<int, BinarizablePerson>(); |
| |
| var binCache = cache0.WithKeepBinary<int, IBinaryObject>(); |
| |
| int cnt = 10; |
| |
| IList<int> keys = new List<int>(); |
| |
| for (int i = 0; i < cnt; i++ ) { |
| cache.Put(i, new BinarizablePerson("person-" + i, i)); |
| |
| keys.Add(i); |
| } |
| |
| IList<IBinaryObject> objs = new List<IBinaryObject>(); |
| |
| for (int i = 0; i < cnt; i++) |
| { |
| var obj = binCache.Get(i); |
| |
| CheckPersonData(obj, "person-" + i, i); |
| |
| objs.Add(obj); |
| } |
| |
| // Check objects weren't corrupted by subsequent cache operations. |
| for (int i = 0; i < cnt; i++) |
| { |
| IBinaryObject obj = objs[i]; |
| |
| CheckPersonData(obj, "person-" + i, i); |
| } |
| |
| // Check keepBinary for GetAll operation. |
| var allObjs1 = binCache.GetAll(keys).ToDictionary(x => x.Key, x => x.Value); |
| |
| var allObjs2 = binCache.GetAll(keys).ToDictionary(x => x.Key, x => x.Value); |
| |
| for (int i = 0; i < cnt; i++) |
| { |
| CheckPersonData(allObjs1[i], "person-" + i, i); |
| |
| CheckPersonData(allObjs2[i], "person-" + i, i); |
| } |
| |
| // Check keepBinary for Remove operation. |
| var success0 = cache.Remove(0); |
| var success1 = cache.Remove(1); |
| |
| Assert.AreEqual(true, success0); |
| Assert.AreEqual(true, success1); |
| } |
| |
| private void CheckPersonData(IBinaryObject obj, string expName, int expAge) |
| { |
| Assert.AreEqual(expName, obj.GetField<string>("name")); |
| Assert.AreEqual(expAge, obj.GetField<int>("age")); |
| |
| BinarizablePerson person = obj.Deserialize<BinarizablePerson>(); |
| |
| Assert.AreEqual(expName, person.Name); |
| Assert.AreEqual(expAge, person.Age); |
| } |
| |
| private static int GetPrimaryKeyForCache(ICache<int, int> cache) |
| { |
| return GetPrimaryKeysForCacheFrom(cache, 0).First(); |
| } |
| |
| private static int GetPrimaryKeyForCache(ICache<int, int> cache, int startFrom) |
| { |
| return GetPrimaryKeysForCacheFrom(cache, startFrom).First(); |
| } |
| |
| private static List<int> GetPrimaryKeysForCache(ICache<int, int> cache, int cnt) |
| { |
| return GetPrimaryKeysForCacheFrom(cache, 0).Take(cnt).ToList(); |
| } |
| |
| private static IEnumerable<int> GetPrimaryKeysForCacheFrom(ICache<int, int> cache, int startFrom) |
| { |
| IClusterNode node = cache.Ignite.GetCluster().GetLocalNode(); |
| |
| ICacheAffinity aff = cache.Ignite.GetAffinity(cache.Name); |
| |
| return Enumerable.Range(startFrom, int.MaxValue - startFrom).Where(x => aff.IsPrimary(node, x)); |
| } |
| |
| private static int NearKeyForCache(ICache<int, int> cache) |
| { |
| IClusterNode node = cache.Ignite.GetCluster().GetLocalNode(); |
| |
| ICacheAffinity aff = cache.Ignite.GetAffinity(cache.Name); |
| |
| for (int i = 0; i < 100000; i++) |
| { |
| if (!aff.IsPrimaryOrBackup(node, i)) |
| return i; |
| } |
| |
| Assert.Fail("Failed to find near key."); |
| |
| return 0; |
| } |
| |
| private static string GetKeyAffinity(ICache<int, int> cache, int key) |
| { |
| if (cache.Ignite.GetAffinity(cache.Name).IsPrimary(cache.Ignite.GetCluster().GetLocalNode(), key)) |
| return "primary"; |
| |
| if (cache.Ignite.GetAffinity(cache.Name).IsBackup(cache.Ignite.GetCluster().GetLocalNode(), key)) |
| return "backup"; |
| |
| return "near"; |
| } |
| |
| protected virtual int CachePartitions() |
| { |
| return 1024; |
| } |
| |
| protected virtual int Backups() |
| { |
| return 0; |
| } |
| |
| protected virtual int GridCount() |
| { |
| return 1; |
| } |
| |
| protected virtual string CacheName() |
| { |
| return "partitioned"; |
| } |
| |
| protected virtual bool NearEnabled() |
| { |
| return false; |
| } |
| |
| protected virtual bool ReplicatedCache() |
| { |
| return true; |
| } |
| |
| private static int PeekInt(ICache<int, int> cache, int key) |
| { |
| int val; |
| |
| cache.TryLocalPeek(key, out val, CachePeekMode.Onheap); |
| |
| return val; |
| } |
| |
| /// <summary> |
| /// Test serializable object. |
| /// </summary> |
| [Serializable] |
| private class TestSerializableObject |
| { |
| public string Name { get; set; } |
| public int Id { get; set; } |
| |
| public override bool Equals(object obj) |
| { |
| if (ReferenceEquals(null, obj)) return false; |
| if (ReferenceEquals(this, obj)) return true; |
| |
| var other = (TestSerializableObject)obj; |
| return obj.GetType() == GetType() && (string.Equals(Name, other.Name) && Id == other.Id); |
| } |
| |
| public override int GetHashCode() |
| { |
| unchecked |
| { |
| return ((Name != null ? Name.GetHashCode() : 0) * 397) ^ Id; |
| } |
| } |
| } |
| |
| private class Container |
| { |
| public int Id; |
| |
| public Container Inner; |
| } |
| |
| private class ExpiryPolicyFactory : IFactory<IExpiryPolicy> |
| { |
| /** */ |
| private readonly IExpiryPolicy _expiryPolicy; |
| |
| /// <summary> |
| /// Initializes a new instance of the <see cref="ExpiryPolicyFactory"/> class. |
| /// </summary> |
| /// <param name="expiryPolicy">The expiry policy.</param> |
| public ExpiryPolicyFactory(IExpiryPolicy expiryPolicy) |
| { |
| _expiryPolicy = expiryPolicy; |
| } |
| |
| /** <inheritdoc /> */ |
| public IExpiryPolicy CreateInstance() |
| { |
| return _expiryPolicy; |
| } |
| } |
| } |
| } |