blob: b69b402b10e767b679ea57b997558f943f672fe8 [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.Store
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Apache.Ignite.Core.Cache.Store;
using Apache.Ignite.Core.Resource;
using NUnit.Framework;
/// <summary>
/// Tests for store session.
/// </summary>
public class CacheStoreSessionTest
{
/** Cache 1 name. */
protected const string Cache1 = "cache1";
/** Cache 2 name. */
protected const string Cache2 = "cache2";
/** Operations. */
private static ConcurrentBag<ICollection<Operation>> _dumps;
/// <summary>
/// Set up routine.
/// </summary>
[TestFixtureSetUp]
public void BeforeTests()
{
Ignition.Start(GetIgniteConfiguration());
}
/// <summary>
/// Gets the ignite configuration.
/// </summary>
protected virtual IgniteConfiguration GetIgniteConfiguration()
{
return new IgniteConfiguration(TestUtils.GetTestConfiguration())
{
SpringConfigUrl = @"Config/Cache/Store/cache-store-session.xml"
};
}
/// <summary>
/// Gets the store count.
/// </summary>
protected virtual int StoreCount
{
get { return 2; }
}
/// <summary>
/// Tear down routine.
/// </summary>
[TestFixtureTearDown]
public void AfterTests()
{
try
{
TestUtils.AssertHandleRegistryHasItems(Ignition.GetIgnite(), 2, 1000);
}
finally
{
Ignition.StopAll(true);
}
}
/// <summary>
/// Test basic session API.
/// </summary>
[Test]
[Timeout(30000)]
public void TestSession()
{
_dumps = new ConcurrentBag<ICollection<Operation>>();
var ignite = Ignition.GetIgnite();
var cache1 = ignite.GetCache<int, int>(Cache1);
var cache2 = ignite.GetCache<int, int>(Cache2);
// 1. Test rollback.
using (var tx = ignite.GetTransactions().TxStart())
{
cache1.Put(1, 1);
cache2.Put(2, 2);
tx.Rollback();
}
// SessionEnd should not be called.
Assert.AreEqual(0, _dumps.Count);
// 2. Test puts.
using (var tx = ignite.GetTransactions().TxStart())
{
cache1.Put(1, 1);
cache2.Put(2, 2);
tx.Commit();
}
Assert.AreEqual(StoreCount, _dumps.Count);
foreach (var ops in _dumps)
{
Assert.AreEqual(2 + StoreCount, ops.Count);
Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Write
&& Cache1 == op.CacheName && 1 == op.Key && 1 == op.Value));
Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Write
&& Cache2 == op.CacheName && 2 == op.Key && 2 == op.Value));
Assert.AreEqual(StoreCount, ops.Count(op => op.Type == OperationType.SesEnd && op.Commit));
}
_dumps = new ConcurrentBag<ICollection<Operation>>();
// 3. Test removes.
using (var tx = ignite.GetTransactions().TxStart())
{
cache1.Remove(1);
cache2.Remove(2);
tx.Commit();
}
Assert.AreEqual(StoreCount, _dumps.Count);
foreach (var ops in _dumps)
{
Assert.AreEqual(2 + StoreCount, ops.Count);
Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Delete
&& Cache1 == op.CacheName && 1 == op.Key));
Assert.AreEqual(1, ops.Count(op => op.Type == OperationType.Delete
&& Cache2 == op.CacheName && 2 == op.Key));
Assert.AreEqual(StoreCount, ops.Count(op => op.Type == OperationType.SesEnd && op.Commit));
}
}
/// <summary>
/// Dump operations.
/// </summary>
/// <param name="dump">Dump.</param>
private static void DumpOperations(ICollection<Operation> dump)
{
_dumps.Add(dump);
}
/// <summary>
/// Test store implementation.
/// </summary>
// ReSharper disable once UnusedMember.Global
public class Store : CacheStoreAdapter<object, object>
{
/** Store session. */
[StoreSessionResource]
#pragma warning disable 649
private ICacheStoreSession _ses;
#pragma warning restore 649
/** <inheritdoc /> */
public override object Load(object key)
{
throw new NotImplementedException();
}
/** <inheritdoc /> */
public override void Write(object key, object val)
{
GetOperations().Add(new Operation(_ses.CacheName, OperationType.Write, (int)key, (int)val));
}
/** <inheritdoc /> */
public override void Delete(object key)
{
GetOperations().Add(new Operation(_ses.CacheName, OperationType.Delete, (int)key, 0));
}
/** <inheritdoc /> */
public override void SessionEnd(bool commit)
{
Operation op = new Operation(_ses.CacheName, OperationType.SesEnd) { Commit = commit };
ICollection<Operation> ops = GetOperations();
ops.Add(op);
DumpOperations(ops);
}
/// <summary>
/// Get collection with operations.
/// </summary>
/// <returns>Operations.</returns>
private ICollection<Operation> GetOperations()
{
object ops;
if (!_ses.Properties.TryGetValue("ops", out ops))
{
ops = new List<Operation>();
_ses.Properties["ops"] = ops;
}
return (ICollection<Operation>) ops;
}
}
/// <summary>
/// Logged operation.
/// </summary>
private class Operation
{
/// <summary>
/// Constructor.
/// </summary>
/// <param name="cacheName">Cache name.</param>
/// <param name="type">Operation type.</param>
public Operation(string cacheName, OperationType type)
{
CacheName = cacheName;
Type = type;
}
/// <summary>
/// Constructor.
/// </summary>
/// <param name="cacheName">Cache name.</param>
/// <param name="type">Operation type.</param>
/// <param name="key">Key.</param>
/// <param name="val">Value.</param>
public Operation(string cacheName, OperationType type, int key, int val) : this(cacheName, type)
{
Key = key;
Value = val;
}
/// <summary>
/// Cache name.
/// </summary>
public string CacheName { get; private set; }
/// <summary>
/// Operation type.
/// </summary>
public OperationType Type { get; private set; }
/// <summary>
/// Key.
/// </summary>
public int Key { get; private set; }
/// <summary>
/// Value.
/// </summary>
public int Value { get; private set; }
/// <summary>
/// Commit flag.
/// </summary>
public bool Commit { get; set; }
}
/// <summary>
/// Operation types.
/// </summary>
private enum OperationType
{
/** Write. */
Write,
/** Delete. */
Delete,
/** Session end. */
SesEnd
}
}
}