blob: 9f0528cd792f6ef7a0b03b19f43ab8b20f257c65 [file] [log] [blame]
/*
* 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 System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
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;
using Apache.Ignite.Core.Impl.Cache;
using Apache.Ignite.Core.Tests.Query;
using Apache.Ignite.Core.Transactions;
using NUnit.Framework;
/// <summary>
///
/// </summary>
class CacheTestKey
{
/// <summary>
/// Default constructor.
/// </summary>
public CacheTestKey()
{
// No-op.
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="id">ID.</param>
public CacheTestKey(int id)
{
Id = id;
}
/// <summary>
/// ID.
/// </summary>
public int Id
{
get;
set;
}
/** <inheritdoc /> */
public override bool Equals(object obj)
{
CacheTestKey other = obj as CacheTestKey;
return other != null && Id == other.Id;
}
/** <inheritdoc /> */
public override int GetHashCode()
{
return Id;
}
/** <inheritdoc /> */
public override string ToString()
{
return new StringBuilder()
.Append(typeof(CacheTestKey).Name)
.Append(" [id=").Append(Id)
.Append(']').ToString();
}
}
/// <summary>
///
/// </summary>
class TestReferenceObject
{
public TestReferenceObject Obj;
/// <summary>
/// Default constructor.
/// </summary>
public TestReferenceObject()
{
// No-op.
}
public TestReferenceObject(TestReferenceObject obj)
{
Obj = obj;
}
}
[Serializable]
public 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;
}
}
}
/// <summary>
/// Cache entry processor that adds argument value to the entry value.
/// </summary>
[Serializable]
public class AddArgCacheEntryProcessor : ICacheEntryProcessor<int, int, int, int>
{
// Expected exception text
public const string ExceptionText = "Exception from AddArgCacheEntryProcessor.";
// Error flag
public bool ThrowErr { get; set; }
// Error flag
public bool ThrowErrBinarizable { get; set; }
// Error flag
public bool ThrowErrNonSerializable { get; set; }
// Key value to throw error on
public int ThrowOnKey { get; set; }
// Remove flag
public bool Remove { get; set; }
// Exists flag
public bool Exists { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="AddArgCacheEntryProcessor"/> class.
/// </summary>
public AddArgCacheEntryProcessor()
{
Exists = true;
ThrowOnKey = -1;
}
/** <inheritdoc /> */
int ICacheEntryProcessor<int, int, int, int>.Process(IMutableCacheEntry<int, int> entry, int arg)
{
if (ThrowOnKey < 0 || ThrowOnKey == entry.Key)
{
if (ThrowErr)
throw new Exception(ExceptionText);
if (ThrowErrBinarizable)
throw new BinarizableTestException {Info = ExceptionText};
if (ThrowErrNonSerializable)
throw new NonSerializableException();
}
Assert.AreEqual(Exists, entry.Exists);
if (Remove)
entry.Remove();
else
entry.Value = entry.Value + arg;
return entry.Value;
}
/** <inheritdoc /> */
public int Process(IMutableCacheEntry<int, int> entry, int arg)
{
throw new Exception("Invalid method");
}
}
/// <summary>
/// Binary add processor.
/// </summary>
public class BinarizableAddArgCacheEntryProcessor : AddArgCacheEntryProcessor, IBinarizable
{
/** <inheritdoc /> */
public void WriteBinary(IBinaryWriter writer)
{
var w = writer.GetRawWriter();
w.WriteBoolean(ThrowErr);
w.WriteBoolean(ThrowErrBinarizable);
w.WriteBoolean(ThrowErrNonSerializable);
w.WriteInt(ThrowOnKey);
w.WriteBoolean(Remove);
w.WriteBoolean(Exists);
}
/** <inheritdoc /> */
public void ReadBinary(IBinaryReader reader)
{
var r = reader.GetRawReader();
ThrowErr = r.ReadBoolean();
ThrowErrBinarizable = r.ReadBoolean();
ThrowErrNonSerializable = r.ReadBoolean();
ThrowOnKey = r.ReadInt();
Remove = r.ReadBoolean();
Exists = r.ReadBoolean();
}
}
/// <summary>
/// Non-serializable processor.
/// </summary>
public class NonSerializableCacheEntryProcessor : AddArgCacheEntryProcessor
{
// No-op.
}
/// <summary>
/// Binary exception.
/// </summary>
public class BinarizableTestException : Exception, IBinarizable
{
/// <summary>
/// Gets or sets exception info.
/// </summary>
public string Info { get; set; }
/** <inheritdoc /> */
public override string Message
{
get { return Info; }
}
/** <inheritdoc /> */
public void WriteBinary(IBinaryWriter writer)
{
writer.GetRawWriter().WriteString(Info);
}
/** <inheritdoc /> */
public void ReadBinary(IBinaryReader reader)
{
Info = reader.GetRawReader().ReadString();
}
}
/// <summary>
/// Non-serializable exception.
/// </summary>
public class NonSerializableException : Exception
{
// No-op
}
/// <summary>
///
/// </summary>
[SuppressMessage("ReSharper", "UnusedVariable")]
public abstract class CacheAbstractTest {
/// <summary>
///
/// </summary>
[TestFixtureSetUp]
public virtual void StartGrids() {
TestUtils.KillProcesses();
IgniteConfiguration cfg = new IgniteConfiguration();
BinaryConfiguration portCfg = new BinaryConfiguration();
ICollection<BinaryTypeConfiguration> portTypeCfgs = new List<BinaryTypeConfiguration>();
portTypeCfgs.Add(new BinaryTypeConfiguration(typeof(BinarizablePerson)));
portTypeCfgs.Add(new BinaryTypeConfiguration(typeof(CacheTestKey)));
portTypeCfgs.Add(new BinaryTypeConfiguration(typeof(TestReferenceObject)));
portTypeCfgs.Add(new BinaryTypeConfiguration(typeof(BinarizableAddArgCacheEntryProcessor)));
portTypeCfgs.Add(new BinaryTypeConfiguration(typeof(BinarizableTestException)));
portCfg.TypeConfigurations = portTypeCfgs;
cfg.BinaryConfiguration = portCfg;
cfg.JvmClasspath = TestUtils.CreateTestClasspath();
cfg.JvmOptions = TestUtils.TestJavaOptions();
cfg.SpringConfigUrl = "config\\native-client-test-cache.xml";
for (int i = 0; i < GridCount(); i++) {
cfg.GridName = "grid-" + i;
Ignition.Start(cfg);
}
}
/// <summary>
///
/// </summary>
[TestFixtureTearDown]
public virtual void StopGrids() {
for (int i = 0; i < GridCount(); 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() {
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.ToString() + 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);
}
public IIgnite GetIgnite(int idx)
{
return Ignition.GetIgnite("grid-" + idx);
}
public ICache<int, int> Cache(int idx) {
return Cache<int, int>(idx);
}
public ICache<TK, TV> Cache<TK, TV>(int idx) {
return GetIgnite(idx).GetCache<TK, TV>(CacheName());
}
public ICache<int, int> Cache()
{
return Cache<int, int>(0);
}
public ICache<TK, TV> Cache<TK, TV>()
{
return Cache<TK, TV>(0);
}
public ICacheAffinity Affinity()
{
return GetIgnite(0).GetAffinity(CacheName());
}
public 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(PrimaryKeyForCache(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 = PrimaryKeyForCache(cache);
cache.Put(key, 1);
Assert.IsTrue(cache.ContainsKey(key));
Assert.IsFalse(cache.ContainsKey(-1));
}
[Test]
public void TestContainsKeys()
{
var cache = Cache();
var keys = PrimaryKeysForCache(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 = PrimaryKeyForCache(cache);
cache.Put(key1, 1);
int val;
Assert.AreEqual(1, cache.LocalPeek(key1));
Assert.Throws<KeyNotFoundException>(() => cache.LocalPeek(-1));
Assert.IsFalse(cache.TryLocalPeek(-1, out val));
Assert.AreEqual(1, cache.LocalPeek(key1, CachePeekMode.All));
Assert.Throws<KeyNotFoundException>(() => cache.LocalPeek(-1, CachePeekMode.All));
Assert.AreEqual(false, cache.TryLocalPeek(-1, out val, 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);
IDictionary<int, int> map = cache.GetAll(new List<int> { 0, 1, 2, 5 });
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 });
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()
{
var cache = Cache();
cache.Put(1, 1);
Assert.AreEqual(1, cache.Get(1));
}
[Test]
public void TestPutxAsync()
{
var cache = Cache().WrapAsync();
cache.Put(1, 1);
Assert.AreEqual(1, cache.Get(1));
}
[Test]
public void TestPutIfAbsent()
{
var cache = Cache();
Assert.IsFalse(cache.ContainsKey(1));
Assert.AreEqual(true, cache.PutIfAbsent(1, 1));
Assert.AreEqual(1, cache.Get(1));
Assert.AreEqual(false, cache.PutIfAbsent(1, 2));
Assert.AreEqual(1, cache.Get(1));
}
[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().WrapAsync();
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 TestPutIfAbsentAsync()
{
var cache = Cache().WrapAsync();
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]
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()
{
var cache = Cache();
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));
}
[Test]
public void TestPutAllAsync()
{
var cache = Cache().WrapAsync();
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));
}
/// <summary>
/// Expiry policy tests.
/// </summary>
[Test]
public void TestWithExpiryPolicy()
{
ICache<int, int> cache0 = Cache(0);
int key0;
int key1;
if (LocalCache())
{
key0 = 0;
key1 = 1;
}
else
{
key0 = PrimaryKeyForCache(cache0);
key1 = PrimaryKeyForCache(Cache(1));
}
// Test unchanged expiration.
ICache<int, int> cache = cache0.WithExpiryPolicy(new ExpiryPolicy(null, null, null));
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 = cache0.WithExpiryPolicy(new ExpiryPolicy(TimeSpan.MaxValue, TimeSpan.MaxValue, TimeSpan.MaxValue));
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 = cache0.WithExpiryPolicy(new ExpiryPolicy(TimeSpan.FromMilliseconds(100),
TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(100)));
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));
cache0.Put(key0, key0);
cache0.Put(key1, key1);
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;
if (LocalCache())
{
key0 = 0;
key1 = 1;
}
else
{
key0 = PrimaryKeyForCache(cache0);
key1 = PrimaryKeyForCache(Cache(1));
}
var cache = cache0.WithExpiryPolicy(new ExpiryPolicy(null, null, null));
// Test zero expiration.
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]
public void TestEvict()
{
var cache = Cache();
int key = PrimaryKeyForCache(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]
public void TestEvictAllKeys()
{
var cache = Cache();
List<int> keys = PrimaryKeysForCache(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(PrimaryKeyForCache(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 = PrimaryKeysForCache(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 = PrimaryKeysForCache(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 = PrimaryKeysForCache(cache, 10);
foreach (var key in keys)
cache.Put(key, 3);
var i = cache.GetSize();
foreach (var key in keys)
{
cache.LocalClear(key);
int val;
Assert.IsFalse(cache.TryLocalPeek(key, out val));
Assert.Less(cache.GetSize(), i);
i = cache.GetSize();
}
cache.Clear();
}
[Test]
public void TestLocalClearKeys()
{
var cache = Cache();
var keys = PrimaryKeysForCache(cache, 10);
foreach (var key in keys)
cache.Put(key, 3);
cache.LocalClearAll(keys);
int val;
foreach (var key in keys)
Assert.IsFalse(cache.TryLocalPeek(key, out val));
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 = PrimaryKeysForCache(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 = PrimaryKeysForCache(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()
{
for (int i = 0; i < GridCount(); i++)
{
var cache = Cache(i);
List<int> keys = PrimaryKeysForCache(cache, 2);
foreach (int key in keys)
cache.Put(key, 1);
Assert.IsTrue(cache.GetSize() >= 2);
Assert.AreEqual(2, cache.GetLocalSize(CachePeekMode.Primary));
}
ICache<int, int> cache0 = Cache();
Assert.AreEqual(GridCount() * 2, cache0.GetSize(CachePeekMode.Primary));
if (!LocalCache() && !ReplicatedCache())
{
int nearKey = NearKeyForCache(cache0);
cache0.Put(nearKey, 1);
Assert.AreEqual(NearEnabled() ? 1 : 0, cache0.GetSize(CachePeekMode.Near));
}
}
[Test]
public void TestLocalSize()
{
var cache = Cache();
var keys = PrimaryKeysForCache(cache, 3);
cache.Put(keys[0], 1);
cache.Put(keys[1], 2);
var localSize = cache.GetLocalSize();
cache.LocalEvict(keys.Take(2).ToArray());
Assert.AreEqual(0, cache.GetLocalSize(CachePeekMode.Onheap));
Assert.AreEqual(localSize, cache.GetLocalSize(CachePeekMode.All));
cache.Put(keys[2], 3);
Assert.AreEqual(localSize + 1, cache.GetLocalSize(CachePeekMode.All));
cache.RemoveAll(keys.Take(2).ToArray());
}
/// <summary>
/// Test enumerators.
/// </summary>
[Test]
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
public void TestEnumerators()
{
var cache = Cache();
var keys = PrimaryKeysForCache(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] } );
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);
e = cache.GetLocalEntries(CachePeekMode.Onheap, CachePeekMode.Swap);
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.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 TestPromote()
{
var cache = Cache();
int key = PrimaryKeyForCache(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));
cache.LocalPromote(new[] { key });
Assert.AreEqual(1, cache.GetLocalSize(CachePeekMode.Onheap));
Assert.AreEqual(1, PeekInt(cache, key));
}
[Test]
public void TestPromoteAll()
{
var cache = Cache();
List<int> keys = PrimaryKeysForCache(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]));
cache.LocalPromote(new[] {keys[0], keys[1]});
Assert.AreEqual(3, cache.GetLocalSize(CachePeekMode.Onheap));
Assert.AreEqual(1, PeekInt(cache, keys[0]));
Assert.AreEqual(2, PeekInt(cache, keys[1]));
Assert.AreEqual(3, PeekInt(cache, keys[2]));
}
[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.CATEGORY_INTENSIVE)]
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);
}
[Test]
[Ignore("IGNITE-835")]
public void TestLock()
{
if (!LockingEnabled())
return;
var cache = Cache();
const int key = 7;
// Lock
CheckLock(cache, key, () => cache.Lock(key));
// LockAll
CheckLock(cache, key, () => cache.LockAll(new[] { key, 2, 3, 4, 5 }));
}
/// <summary>
/// Internal lock test routine.
/// </summary>
/// <param name="cache">Cache.</param>
/// <param name="key">Key.</param>
/// <param name="getLock">Function to get the lock.</param>
private static void CheckLock(ICache<int, int> cache, int key, Func<ICacheLock> getLock)
{
var sharedLock = getLock();
using (sharedLock)
{
Assert.Throws<InvalidOperationException>(() => sharedLock.Exit()); // can't exit if not entered
sharedLock.Enter();
try
{
Assert.IsTrue(cache.IsLocalLocked(key, true));
Assert.IsTrue(cache.IsLocalLocked(key, false));
EnsureCannotLock(getLock, sharedLock);
sharedLock.Enter();
try
{
Assert.IsTrue(cache.IsLocalLocked(key, true));
Assert.IsTrue(cache.IsLocalLocked(key, false));
EnsureCannotLock(getLock, sharedLock);
}
finally
{
sharedLock.Exit();
}
Assert.IsTrue(cache.IsLocalLocked(key, true));
Assert.IsTrue(cache.IsLocalLocked(key, false));
EnsureCannotLock(getLock, sharedLock);
Assert.Throws<SynchronizationLockException>(() => sharedLock.Dispose()); // can't dispose while locked
}
finally
{
sharedLock.Exit();
}
Assert.IsFalse(cache.IsLocalLocked(key, true));
Assert.IsFalse(cache.IsLocalLocked(key, false));
var innerTask = new Task(() =>
{
Assert.IsTrue(sharedLock.TryEnter());
sharedLock.Exit();
using (var otherLock = getLock())
{
Assert.IsTrue(otherLock.TryEnter());
otherLock.Exit();
}
});
innerTask.Start();
innerTask.Wait();
}
Assert.IsFalse(cache.IsLocalLocked(key, true));
Assert.IsFalse(cache.IsLocalLocked(key, false));
var outerTask = new Task(() =>
{
using (var otherLock = getLock())
{
Assert.IsTrue(otherLock.TryEnter());
otherLock.Exit();
}
});
outerTask.Start();
outerTask.Wait();
Assert.Throws<ObjectDisposedException>(() => sharedLock.Enter()); // Can't enter disposed lock
}
/// <summary>
/// ENsure taht lock cannot be obtained by other threads.
/// </summary>
/// <param name="getLock">Get lock function.</param>
/// <param name="sharedLock">Shared lock.</param>
private static void EnsureCannotLock(Func<ICacheLock> getLock, ICacheLock sharedLock)
{
var task = new Task(() =>
{
Assert.IsFalse(sharedLock.TryEnter());
Assert.IsFalse(sharedLock.TryEnter(TimeSpan.FromMilliseconds(100)));
using (var otherLock = getLock())
{
Assert.IsFalse(otherLock.TryEnter());
Assert.IsFalse(otherLock.TryEnter(TimeSpan.FromMilliseconds(100)));
}
});
task.Start();
task.Wait();
}
[Test]
public void TestTxCommit()
{
TestTxCommit(false);
}
[Test]
public void TestTxCommitAsync()
{
TestTxCommit(true);
}
private void TestTxCommit(bool async)
{
if (!TxEnabled())
return;
var cache = Cache();
ITransaction tx = Transactions.Tx;
Assert.IsNull(tx);
tx = Transactions.TxStart();
try
{
cache.Put(1, 1);
cache.Put(2, 2);
if (async)
{
var task = tx.CommitAsync();
task.Wait();
Assert.IsTrue(task.IsCompleted);
}
else
tx.Commit();
}
finally
{
tx.Dispose();
}
Assert.AreEqual(1, cache.Get(1));
Assert.AreEqual(2, cache.Get(2));
tx = Transactions.Tx;
Assert.IsNull(tx);
}
[Test]
public void TestTxRollback()
{
if (!TxEnabled())
return;
var cache = Cache();
cache.Put(1, 1);
cache.Put(2, 2);
ITransaction tx = Transactions.Tx;
Assert.IsNull(tx);
tx = Transactions.TxStart();
try {
cache.Put(1, 10);
cache.Put(2, 20);
}
finally {
tx.Rollback();
}
Assert.AreEqual(1, cache.Get(1));
Assert.AreEqual(2, cache.Get(2));
Assert.IsNull(Transactions.Tx);
}
[Test]
public void TestTxClose()
{
if (!TxEnabled())
return;
var cache = Cache();
cache.Put(1, 1);
cache.Put(2, 2);
ITransaction tx = Transactions.Tx;
Assert.IsNull(tx);
tx = Transactions.TxStart();
try
{
cache.Put(1, 10);
cache.Put(2, 20);
}
finally
{
tx.Dispose();
}
Assert.AreEqual(1, cache.Get(1));
Assert.AreEqual(2, cache.Get(2));
tx = Transactions.Tx;
Assert.IsNull(tx);
}
[Test]
public void TestTxAllModes()
{
TestTxAllModes(false);
TestTxAllModes(true);
Console.WriteLine("Done");
}
protected void TestTxAllModes(bool withTimeout)
{
if (!TxEnabled())
return;
var cache = Cache();
int cntr = 0;
foreach (TransactionConcurrency concurrency in Enum.GetValues(typeof(TransactionConcurrency))) {
foreach (TransactionIsolation isolation in Enum.GetValues(typeof(TransactionIsolation))) {
Console.WriteLine("Test tx [concurrency=" + concurrency + ", isolation=" + isolation + "]");
ITransaction tx = Transactions.Tx;
Assert.IsNull(tx);
tx = withTimeout
? Transactions.TxStart(concurrency, isolation, TimeSpan.FromMilliseconds(1100), 10)
: Transactions.TxStart(concurrency, isolation);
Assert.AreEqual(concurrency, tx.Concurrency);
Assert.AreEqual(isolation, tx.Isolation);
if (withTimeout)
Assert.AreEqual(1100, tx.Timeout.TotalMilliseconds);
try {
cache.Put(1, cntr);
tx.Commit();
}
finally {
tx.Dispose();
}
tx = Transactions.Tx;
Assert.IsNull(tx);
Assert.AreEqual(cntr, cache.Get(1));
cntr++;
}
}
}
[Test]
public void TestTxAttributes()
{
if (!TxEnabled())
return;
ITransaction tx = Transactions.TxStart(TransactionConcurrency.Optimistic,
TransactionIsolation.RepeatableRead, TimeSpan.FromMilliseconds(2500), 100);
Assert.IsFalse(tx.IsRollbackOnly);
Assert.AreEqual(TransactionConcurrency.Optimistic, tx.Concurrency);
Assert.AreEqual(TransactionIsolation.RepeatableRead, tx.Isolation);
Assert.AreEqual(2500, tx.Timeout.TotalMilliseconds);
Assert.AreEqual(TransactionState.Active, tx.State);
Assert.IsTrue(tx.StartTime.Ticks > 0);
Assert.AreEqual(tx.NodeId, GetIgnite(0).GetCluster().GetLocalNode().Id);
DateTime startTime1 = tx.StartTime;
tx.Commit();
Assert.IsFalse(tx.IsRollbackOnly);
Assert.AreEqual(TransactionState.Committed, tx.State);
Assert.AreEqual(TransactionConcurrency.Optimistic, tx.Concurrency);
Assert.AreEqual(TransactionIsolation.RepeatableRead, tx.Isolation);
Assert.AreEqual(2500, tx.Timeout.TotalMilliseconds);
Assert.AreEqual(startTime1, tx.StartTime);
Thread.Sleep(100);
tx = Transactions.TxStart(TransactionConcurrency.Pessimistic, TransactionIsolation.ReadCommitted,
TimeSpan.FromMilliseconds(3500), 200);
Assert.IsFalse(tx.IsRollbackOnly);
Assert.AreEqual(TransactionConcurrency.Pessimistic, tx.Concurrency);
Assert.AreEqual(TransactionIsolation.ReadCommitted, tx.Isolation);
Assert.AreEqual(3500, tx.Timeout.TotalMilliseconds);
Assert.AreEqual(TransactionState.Active, tx.State);
Assert.IsTrue(tx.StartTime.Ticks > 0);
Assert.IsTrue(tx.StartTime > startTime1);
DateTime startTime2 = tx.StartTime;
tx.Rollback();
Assert.AreEqual(TransactionState.RolledBack, tx.State);
Assert.AreEqual(TransactionConcurrency.Pessimistic, tx.Concurrency);
Assert.AreEqual(TransactionIsolation.ReadCommitted, tx.Isolation);
Assert.AreEqual(3500, tx.Timeout.TotalMilliseconds);
Assert.AreEqual(startTime2, tx.StartTime);
Thread.Sleep(100);
tx = Transactions.TxStart(TransactionConcurrency.Optimistic, TransactionIsolation.RepeatableRead,
TimeSpan.FromMilliseconds(2500), 100);
Assert.IsFalse(tx.IsRollbackOnly);
Assert.AreEqual(TransactionConcurrency.Optimistic, tx.Concurrency);
Assert.AreEqual(TransactionIsolation.RepeatableRead, tx.Isolation);
Assert.AreEqual(2500, tx.Timeout.TotalMilliseconds);
Assert.AreEqual(TransactionState.Active, tx.State);
Assert.IsTrue(tx.StartTime > startTime2);
DateTime startTime3 = tx.StartTime;
tx.Commit();
Assert.IsFalse(tx.IsRollbackOnly);
Assert.AreEqual(TransactionState.Committed, tx.State);
Assert.AreEqual(TransactionConcurrency.Optimistic, tx.Concurrency);
Assert.AreEqual(TransactionIsolation.RepeatableRead, tx.Isolation);
Assert.AreEqual(2500, tx.Timeout.TotalMilliseconds);
Assert.AreEqual(startTime3, tx.StartTime);
}
[Test]
public void TestTxRollbackOnly()
{
if (!TxEnabled())
return;
var cache = Cache();
cache.Put(1, 1);
cache.Put(2, 2);
ITransaction tx = Transactions.TxStart();
cache.Put(1, 10);
cache.Put(2, 20);
Assert.IsFalse(tx.IsRollbackOnly);
tx.SetRollbackonly();
Assert.IsTrue(tx.IsRollbackOnly);
Assert.AreEqual(TransactionState.MarkedRollback, tx.State);
try
{
tx.Commit();
Assert.Fail("Commit must fail.");
}
catch (IgniteException e)
{
Console.WriteLine("Expected exception: " + e);
}
tx.Dispose();
Assert.AreEqual(TransactionState.RolledBack, tx.State);
Assert.IsTrue(tx.IsRollbackOnly);
Assert.AreEqual(1, cache.Get(1));
Assert.AreEqual(2, cache.Get(2));
tx = Transactions.Tx;
Assert.IsNull(tx);
}
[Test]
public void TestTxMetrics()
{
if (!TxEnabled())
return;
var cache = Cache();
var startTime = DateTime.UtcNow.AddSeconds(-1);
Transactions.ResetMetrics();
var metrics = Transactions.GetMetrics();
Assert.AreEqual(0, metrics.TxCommits);
Assert.AreEqual(0, metrics.TxRollbacks);
using (Transactions.TxStart())
{
cache.Put(1, 1);
}
using (var tx = Transactions.TxStart())
{
cache.Put(1, 1);
tx.Commit();
}
metrics = Transactions.GetMetrics();
Assert.AreEqual(1, metrics.TxCommits);
Assert.AreEqual(1, metrics.TxRollbacks);
Assert.LessOrEqual(startTime, metrics.CommitTime);
Assert.LessOrEqual(startTime, metrics.RollbackTime);
Assert.GreaterOrEqual(DateTime.UtcNow, metrics.CommitTime);
Assert.GreaterOrEqual(DateTime.UtcNow, metrics.RollbackTime);
}
[Test]
public void TestTxStateAndExceptions()
{
if (!TxEnabled())
return;
var tx = Transactions.TxStart();
Assert.AreEqual(TransactionState.Active, tx.State);
tx.Rollback();
Assert.AreEqual(TransactionState.RolledBack, tx.State);
try
{
tx.Commit();
Assert.Fail();
}
catch (InvalidOperationException)
{
// Expected
}
tx = Transactions.TxStart();
Assert.AreEqual(TransactionState.Active, tx.State);
tx.CommitAsync().Wait();
Assert.AreEqual(TransactionState.Committed, tx.State);
var task = tx.RollbackAsync(); // Illegal, but should not fail here; will fail in task
try
{
task.Wait();
Assert.Fail();
}
catch (AggregateException)
{
// Expected
}
}
/// <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));
if (LocalCache())
Assert.AreEqual(1, parts.Count);
else
Assert.IsTrue(parts.Count > 10);
}
{
ISet<int> parts = new HashSet<int>();
for (int i = 0; i < 1000; i++)
parts.Add(aff.GetPartition("key" + i));
if (LocalCache())
Assert.AreEqual(1, parts.Count);
else
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();
if (LocalCache())
{
IList<int> parts = new List<int> { 0 };
IDictionary<int, IClusterNode> map = aff.MapPartitionsToNodes(parts);
Assert.AreEqual(parts.Count, map.Count);
Assert.AreEqual(GetIgnite(0).GetCluster().GetLocalNode(), map[0]);
}
else
{
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);
try
{
TestInvoke<NonSerializableCacheEntryProcessor>(async);
Assert.Fail();
}
catch (BinaryObjectException)
{
// Expected
}
}
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), "BinaryObjectException");
}
private static void AssertThrowsCacheEntryProcessorException(Action action, string containsText = null)
{
try
{
action();
Assert.Fail();
}
catch (Exception ex)
{
Assert.IsInstanceOf<CacheEntryProcessorException>(ex);
if (string.IsNullOrEmpty(containsText))
Assert.AreEqual(ex.InnerException.Message, AddArgCacheEntryProcessor.ExceptionText);
else
Assert.IsTrue(ex.ToString().Contains(containsText));
}
}
[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);
try
{
TestInvokeAll<NonSerializableCacheEntryProcessor>(async, i);
Assert.Fail();
}
catch (BinaryObjectException)
{
// Expected
}
}
}
public 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.Value.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.Value.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.Value.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, "BinaryObjectException");
}
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.Value.Result; }, exceptionText);
else
Assert.Greater(procRes.Value.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 TestCacheMetrics()
{
var cache = Cache();
cache.Put(1, 1);
var m = cache.GetMetrics();
Assert.AreEqual(cache.Name, m.CacheName);
Assert.AreEqual(cache.GetSize(), m.Size);
}
[Test]
public void TestRebalance()
{
var cache = Cache();
var fut = cache.Rebalance();
}
[Test]
public void TestCreate()
{
// Create a cache with random name
var randomName = "template" + Guid.NewGuid();
// Can't get non-existent cache with Cache method
Assert.Throws<ArgumentException>(() => GetIgnite(0).GetCache<int, int>(randomName));
var cache = GetIgnite(0).CreateCache<int, int>(randomName);
cache.Put(1, 10);
Assert.AreEqual(10, cache.Get(1));
// Can't create again
Assert.Throws<IgniteException>(() => GetIgnite(0).CreateCache<int, int>(randomName));
var cache0 = GetIgnite(0).GetCache<int, int>(randomName);
Assert.AreEqual(10, cache0.Get(1));
}
[Test]
public void TestGetOrCreate()
{
// Create a cache with random name
var randomName = "template" + Guid.NewGuid();
// Can't get non-existent cache with Cache method
Assert.Throws<ArgumentException>(() => GetIgnite(0).GetCache<int, int>(randomName));
var cache = GetIgnite(0).GetOrCreateCache<int, int>(randomName);
cache.Put(1, 10);
Assert.AreEqual(10, cache.Get(1));
var cache0 = GetIgnite(0).GetOrCreateCache<int, int>(randomName);
Assert.AreEqual(10, cache0.Get(1));
var cache1 = GetIgnite(0).GetCache<int, int>(randomName);
Assert.AreEqual(10, cache1.Get(1));
}
[Test]
public void TestDestroy()
{
var cacheName = "template" + Guid.NewGuid();
var ignite = GetIgnite(0);
var cache = ignite.CreateCache<int, int>(cacheName);
Assert.IsNotNull(ignite.GetCache<int, int>(cacheName));
ignite.DestroyCache(cache.Name);
var ex = Assert.Throws<ArgumentException>(() => ignite.GetCache<int, int>(cacheName));
Assert.IsTrue(ex.Message.StartsWith("Cache doesn't exist"));
Assert.Throws<InvalidOperationException>(() => cache.Get(1));
}
[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]);
}
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);
var allObjs2 = binCache.GetAll(keys);
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);
}
protected static int PrimaryKeyForCache(ICache<int, int> cache)
{
return PrimaryKeysForCache(cache, 1, 0).First();
}
protected static int PrimaryKeyForCache(ICache<int, int> cache, int startFrom)
{
return PrimaryKeysForCache(cache, 1, startFrom).First();
}
protected static List<int> PrimaryKeysForCache(ICache<int, int> cache, int cnt)
{
return PrimaryKeysForCache(cache, cnt, 0).Take(cnt).ToList();
}
protected static IEnumerable<int> PrimaryKeysForCache(ICache<int, int> cache, int cnt, 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));
}
protected 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;
}
protected 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 TxEnabled()
{
return true;
}
protected virtual bool LockingEnabled()
{
return TxEnabled();
}
protected virtual bool LocalCache()
{
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;
}
}
}