blob: 32068387551fbfd1eb39f02acb07df627cafed6b [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.
*/
// ReSharper disable NonReadonlyMemberInGetHashCode
namespace Apache.Ignite.Core.Tests.Binary
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
/// <summary>
/// Tests binary type interoperability between .NET and Java code.
/// </summary>
public class JavaBinaryInteropTest
{
/** */
private const string CacheName = "default";
/// <summary>
/// Sets up the fixture.
/// </summary>
[TestFixtureSetUp]
public void FixtureSetUp()
{
Ignition.Start(TestUtils.GetTestConfiguration());
}
/// <summary>
/// Tears down the fixture.
/// </summary>
[TestFixtureTearDown]
public void FixtureTearDown()
{
Ignition.StopAll(true);
}
/// <summary>
/// Tests that all kinds of values from .NET can be handled properly on Java side.
/// </summary>
[Test]
public void TestValueRoundtrip()
{
Ignition.GetIgnite().CreateCache<int, object>(CacheName);
// Basic types.
// Types which map directly to Java are returned properly when retrieved as object.
// Non-directly mapped types are returned as their counterpart.
CheckValueCaching((char) 128);
CheckValueCaching((byte) 255);
CheckValueCaching((sbyte) -10, false);
CheckValueCaching((short) -32000);
CheckValueCaching((ushort) 65350, false);
CheckValueCaching(int.MinValue);
CheckValueCaching(uint.MaxValue, false);
CheckValueCaching(long.MinValue);
CheckValueCaching(ulong.MaxValue, false);
CheckValueCaching((float) 1.1);
CheckValueCaching(2.2);
CheckValueCaching((decimal) 3.3, asArray: false);
CheckValueCaching(Guid.NewGuid(), asArray: false);
CheckValueCaching(DateTime.Now, asArray: false);
CheckValueCaching("foobar");
// Special arrays.
CheckValueCaching(new[] {Guid.Empty, Guid.NewGuid()}, false);
CheckValueCaching(new Guid?[] {Guid.Empty, Guid.NewGuid()});
CheckValueCaching(new[] {1.2m, -3.4m}, false);
CheckValueCaching(new decimal?[] {1.2m, -3.4m});
CheckValueCaching(new[] {DateTime.Now}, false);
// Custom types.
CheckValueCaching(new Foo {X = 10}, asArray: false);
CheckValueCaching(new Bar {X = 20}, asArray: false);
// Collections.
CheckValueCaching(new List<Foo>(GetFoo()));
CheckValueCaching(new List<Bar>(GetBar()));
CheckValueCaching(new HashSet<Foo>(GetFoo()));
CheckValueCaching(new HashSet<Bar>(GetBar()));
CheckValueCaching(GetFoo().ToDictionary(x => x.X, x => x));
CheckValueCaching(GetBar().ToDictionary(x => x.X, x => x));
// Custom type arrays.
// Array type is lost, because in binary mode on Java side we receive the value as Object[].
CheckValueCaching(new[] {new Foo {X = -1}, new Foo {X = 1}}, false);
CheckValueCaching(new[] {new Bar {X = -10}, new Bar {X = 10}}, false);
}
/// <summary>
/// Tests array of objects with shared list instance.
/// </summary>
[Test]
public void TestArrayOfObjectsWithSharedListProperty()
{
var cache = Ignition.GetIgnite().GetOrCreateCache<int, InnerList[]>(TestUtils.TestName);
var inner = new List<object>();
cache.Put(1, new[]
{
new InnerList {Inner = inner},
new InnerList {Inner = inner}
});
var res = cache.Get(1);
Assert.AreEqual(2, res.Length);
Assert.AreNotSame(res[0].Inner, res[1].Inner);
}
/// <summary>
/// Tests array of objects with shared object instance.
/// </summary>
[Test]
public void TestArrayOfObjectsWithSharedObjectProperty()
{
var cache = Ignition.GetIgnite().GetOrCreateCache<int, InnerObject[]>(TestUtils.TestName);
var inner = new object();
cache.Put(1, new[]
{
new InnerObject {Inner = inner},
new InnerObject {Inner = inner}
});
var res = cache.Get(1);
Assert.AreEqual(2, res.Length);
Assert.AreNotSame(res[0].Inner, res[1].Inner);
}
/// <summary>
/// Tests ArrayList of objects with shared object instance.
/// </summary>
[Test]
public void TestArrayListOfObjectsWithSharedObjectProperty()
{
var cache = Ignition.GetIgnite().GetOrCreateCache<int, ArrayList>(TestUtils.TestName);
var inner = new object();
cache.Put(1, new ArrayList
{
new InnerObject {Inner = inner},
new InnerObject {Inner = inner}
});
var res = cache.Get(1);
Assert.AreEqual(2, res.Count);
Assert.AreNotSame(((InnerObject)res[0]).Inner, ((InnerObject)res[1]).Inner);
}
/// <summary>
/// Tests ArrayList of objects with shared object instance.
/// </summary>
[Test]
public void TestListOfObjectsWithSharedObjectProperty()
{
var cache = Ignition.GetIgnite().GetOrCreateCache<int, List<InnerObject>>(TestUtils.TestName);
var inner = new object();
cache.Put(1, new List<InnerObject>
{
new InnerObject {Inner = inner},
new InnerObject {Inner = inner}
});
var res = cache.Get(1);
Assert.AreEqual(2, res.Count);
Assert.AreSame(res[0].Inner, res[1].Inner);
}
/// <summary>
/// Tests ArrayList of objects with shared object instance.
/// </summary>
[Test]
public void TestHashtableOfObjectsWithSharedObjectProperty()
{
var cache = Ignition.GetIgnite().GetOrCreateCache<int, Hashtable>(TestUtils.TestName);
var inner = new object();
cache.Put(1, new Hashtable
{
{0, new InnerObject {Inner = inner}},
{1, new InnerObject {Inner = inner}},
});
var res = cache.Get(1);
Assert.AreEqual(2, res.Count);
Assert.AreNotSame(((InnerObject)res[0]).Inner, ((InnerObject)res[1]).Inner);
}
/// <summary>
/// Tests ArrayList of objects with shared object instance.
/// </summary>
[Test]
public void TestDictionaryOfObjectsWithSharedObjectProperty()
{
var cache = Ignition.GetIgnite().GetOrCreateCache<int, Dictionary<int, InnerObject>>(TestUtils.TestName);
var inner = new object();
cache.Put(1, new Dictionary<int, InnerObject>
{
{0, new InnerObject {Inner = inner}},
{1, new InnerObject {Inner = inner}},
});
var res = cache.Get(1);
Assert.AreEqual(2, res.Count);
Assert.AreSame(res[0].Inner, res[1].Inner);
}
/// <summary>
/// Tests array of objects with a nested array with a shared element.
/// </summary>
[Test]
public void TestArrayOfObjectsWithSharedArrayElement()
{
var cache = Ignition.GetIgnite().GetOrCreateCache<int, InnerArray[]>(TestUtils.TestName);
var innerObj = new object();
var inner = new[] {innerObj};
cache.Put(1, new[]
{
new InnerArray {Inner = inner},
new InnerArray {Inner = inner}
});
var res = cache.Get(1);
Assert.AreEqual(2, res.Length);
Assert.AreNotSame(res[0].Inner[0], res[1].Inner[0]);
}
/// <summary>
/// Tests array of objects with a nested array with a reference loop.
/// </summary>
[Test]
public void TestArrayOfObjectsWithSharedArrayElementAndReferenceLoop()
{
var cache = Ignition.GetIgnite().GetOrCreateCache<int, InnerArray[]>(TestUtils.TestName);
var inner = new object[] {null};
inner[0] = inner;
cache.Put(1, new[]
{
new InnerArray {Inner = inner},
new InnerArray {Inner = inner}
});
var res = cache.Get(1);
Assert.AreEqual(2, res.Length);
Assert.AreNotSame(res[0], res[1]);
Assert.AreSame(res[0].Inner, res[0].Inner[0]);
}
/// <summary>
/// Checks caching of a value with generic cache.
/// </summary>
private static void CheckValueCaching<T>(T val, bool asObject = true, bool asArray = true)
{
var cache = Ignition.GetIgnite().GetCache<int, T>(CacheName);
cache[1] = val;
Assert.AreEqual(val, cache[1]);
if (asObject)
{
CheckValueCachingAsObject(val);
}
// Array of T
if (asArray && !(val is IEnumerable))
{
CheckValueCaching(new[] {val}, asObject, false);
}
}
/// <summary>
/// Checks caching of a value with object cache.
/// </summary>
private static void CheckValueCachingAsObject<T>(T val)
{
var cache = Ignition.GetIgnite().GetCache<int, object>("default");
cache[1] = val;
Assert.AreEqual(val, (T) cache[1]);
}
/// <summary>
/// Gets Foo collection.
/// </summary>
private static IEnumerable<Foo> GetFoo()
{
return Enumerable.Range(-50, 100).Select(x => new Foo {X = x});
}
/// <summary>
/// Gets Bar collection.
/// </summary>
private static IEnumerable<Bar> GetBar()
{
return Enumerable.Range(-50, 100).Select(x => new Bar {X = x});
}
/// <summary>
/// Test custom class.
/// </summary>
private class Foo
{
public int X { get; set; }
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return X == ((Foo) obj).X;
}
public override int GetHashCode()
{
return X;
}
}
/// <summary>
/// Test custom struct.
/// </summary>
private struct Bar
{
public int X { get; set; }
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is Bar && X == ((Bar) obj).X;
}
public override int GetHashCode()
{
return X;
}
}
/** */
private class InnerList
{
public IList<object> Inner { get; set; }
}
/** */
private class InnerObject
{
public object Inner { get; set; }
}
/** */
private class InnerArray
{
public object[] Inner { get; set; }
}
}
}