http://git-wip-us.apache.org/repos/asf/ignite/blob/d69362f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs new file mode 100644 index 0000000..102afd1 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs @@ -0,0 +1,2157 @@ +/* + * 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 +// ReSharper disable CompareOfFloatsByEqualityOperator +// ReSharper disable PossibleInvalidOperationException +// ReSharper disable UnusedAutoPropertyAccessor.Global +// ReSharper disable MemberCanBePrivate.Global +namespace Apache.Ignite.Core.Tests.Binary +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Common; + using Apache.Ignite.Core.Impl.Binary; + using Apache.Ignite.Core.Impl.Binary.IO; + using NUnit.Framework; + + /// <summary> + /// + /// </summary> + [TestFixture] + public class BinarySelfTest { + /** */ + private Marshaller _marsh; + + /// <summary> + /// + /// </summary> + [TestFixtureSetUp] + public void BeforeTest() + { + _marsh = new Marshaller(null); + } + + /** + * <summary>Check write of primitive boolean.</summary> + */ + [Test] + public void TestWritePrimitiveBool() + { + Assert.AreEqual(_marsh.Unmarshal<bool>(_marsh.Marshal(false)), false); + Assert.AreEqual(_marsh.Unmarshal<bool>(_marsh.Marshal(true)), true); + + Assert.AreEqual(_marsh.Unmarshal<bool?>(_marsh.Marshal((bool?)false)), false); + Assert.AreEqual(_marsh.Unmarshal<bool?>(_marsh.Marshal((bool?)null)), null); + } + + /** + * <summary>Check write of primitive boolean array.</summary> + */ + [Test] + public void TestWritePrimitiveBoolArray() + { + bool[] vals = { true, false }; + + Assert.AreEqual(_marsh.Unmarshal<bool[]>(_marsh.Marshal(vals)), vals); + + bool?[] vals2 = { true, false }; + + Assert.AreEqual(_marsh.Unmarshal<bool?[]>(_marsh.Marshal(vals2)), vals2); + } + + /** + * <summary>Check write of primitive sbyte.</summary> + */ + [Test] + public void TestWritePrimitiveSbyte() + { + Assert.AreEqual(_marsh.Unmarshal<sbyte>(_marsh.Marshal((sbyte)1)), 1); + Assert.AreEqual(_marsh.Unmarshal<sbyte>(_marsh.Marshal(sbyte.MinValue)), sbyte.MinValue); + Assert.AreEqual(_marsh.Unmarshal<sbyte>(_marsh.Marshal(sbyte.MaxValue)), sbyte.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<sbyte?>(_marsh.Marshal((sbyte?)1)), (sbyte?)1); + Assert.AreEqual(_marsh.Unmarshal<sbyte?>(_marsh.Marshal((sbyte?)null)), null); + } + + /** + * <summary>Check write of primitive sbyte array.</summary> + */ + [Test] + public void TestWritePrimitiveSbyteArray() + { + sbyte[] vals = { sbyte.MinValue, 0, 1, sbyte.MaxValue }; + sbyte[] newVals = _marsh.Unmarshal<sbyte[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive byte.</summary> + */ + [Test] + public void TestWritePrimitiveByte() + { + Assert.AreEqual(_marsh.Unmarshal<byte>(_marsh.Marshal((byte)1)), 1); + Assert.AreEqual(_marsh.Unmarshal<byte>(_marsh.Marshal(byte.MinValue)), byte.MinValue); + Assert.AreEqual(_marsh.Unmarshal<byte>(_marsh.Marshal(byte.MaxValue)), byte.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<byte?>(_marsh.Marshal((byte?)1)), (byte?)1); + Assert.AreEqual(_marsh.Unmarshal<byte?>(_marsh.Marshal((byte?)null)), null); + } + + /** + * <summary>Check write of primitive byte array.</summary> + */ + [Test] + public void TestWritePrimitiveByteArray() + { + byte[] vals = { byte.MinValue, 0, 1, byte.MaxValue }; + byte[] newVals = _marsh.Unmarshal<byte[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive short.</summary> + */ + [Test] + public void TestWritePrimitiveShort() + { + Assert.AreEqual(_marsh.Unmarshal<short>(_marsh.Marshal((short)1)), 1); + Assert.AreEqual(_marsh.Unmarshal<short>(_marsh.Marshal(short.MinValue)), short.MinValue); + Assert.AreEqual(_marsh.Unmarshal<short>(_marsh.Marshal(short.MaxValue)), short.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<short?>(_marsh.Marshal((short?)1)), (short?)1); + Assert.AreEqual(_marsh.Unmarshal<short?>(_marsh.Marshal((short?)null)), null); + } + + /** + * <summary>Check write of primitive short array.</summary> + */ + [Test] + public void TestWritePrimitiveShortArray() + { + short[] vals = { short.MinValue, 0, 1, short.MaxValue }; + short[] newVals = _marsh.Unmarshal<short[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive ushort.</summary> + */ + [Test] + public void TestWritePrimitiveUshort() + { + Assert.AreEqual(_marsh.Unmarshal<ushort>(_marsh.Marshal((ushort)1)), 1); + Assert.AreEqual(_marsh.Unmarshal<ushort>(_marsh.Marshal(ushort.MinValue)), ushort.MinValue); + Assert.AreEqual(_marsh.Unmarshal<ushort>(_marsh.Marshal(ushort.MaxValue)), ushort.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<ushort?>(_marsh.Marshal((ushort?)1)), (ushort?)1); + Assert.AreEqual(_marsh.Unmarshal<ushort?>(_marsh.Marshal((ushort?)null)), null); + } + + /** + * <summary>Check write of primitive short array.</summary> + */ + [Test] + public void TestWritePrimitiveUshortArray() + { + ushort[] vals = { ushort.MinValue, 0, 1, ushort.MaxValue }; + ushort[] newVals = _marsh.Unmarshal<ushort[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive char.</summary> + */ + [Test] + public void TestWritePrimitiveChar() + { + Assert.AreEqual(_marsh.Unmarshal<char>(_marsh.Marshal((char)1)), (char)1); + Assert.AreEqual(_marsh.Unmarshal<char>(_marsh.Marshal(char.MinValue)), char.MinValue); + Assert.AreEqual(_marsh.Unmarshal<char>(_marsh.Marshal(char.MaxValue)), char.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<char?>(_marsh.Marshal((char?)1)), (char?)1); + Assert.AreEqual(_marsh.Unmarshal<char?>(_marsh.Marshal((char?)null)), null); + } + + /** + * <summary>Check write of primitive uint array.</summary> + */ + [Test] + public void TestWritePrimitiveCharArray() + { + char[] vals = { char.MinValue, (char)0, (char)1, char.MaxValue }; + char[] newVals = _marsh.Unmarshal<char[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive int.</summary> + */ + [Test] + public void TestWritePrimitiveInt() + { + Assert.AreEqual(_marsh.Unmarshal<int>(_marsh.Marshal(1)), 1); + Assert.AreEqual(_marsh.Unmarshal<int>(_marsh.Marshal(int.MinValue)), int.MinValue); + Assert.AreEqual(_marsh.Unmarshal<int>(_marsh.Marshal(int.MaxValue)), int.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<int?>(_marsh.Marshal((int?)1)), (int?)1); + Assert.AreEqual(_marsh.Unmarshal<int?>(_marsh.Marshal((int?)null)), null); + } + + /** + * <summary>Check write of primitive uint array.</summary> + */ + [Test] + public void TestWritePrimitiveIntArray() + { + int[] vals = { int.MinValue, 0, 1, int.MaxValue }; + int[] newVals = _marsh.Unmarshal<int[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive uint.</summary> + */ + [Test] + public void TestWritePrimitiveUint() + { + Assert.AreEqual(_marsh.Unmarshal<uint>(_marsh.Marshal((uint)1)), 1); + Assert.AreEqual(_marsh.Unmarshal<uint>(_marsh.Marshal(uint.MinValue)), uint.MinValue); + Assert.AreEqual(_marsh.Unmarshal<uint>(_marsh.Marshal(uint.MaxValue)), uint.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<uint?>(_marsh.Marshal((uint?)1)), (int?)1); + Assert.AreEqual(_marsh.Unmarshal<uint?>(_marsh.Marshal((uint?)null)), null); + } + + /** + * <summary>Check write of primitive uint array.</summary> + */ + [Test] + public void TestWritePrimitiveUintArray() + { + uint[] vals = { uint.MinValue, 0, 1, uint.MaxValue }; + uint[] newVals = _marsh.Unmarshal<uint[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive long.</summary> + */ + [Test] + public void TestWritePrimitiveLong() + { + Assert.AreEqual(_marsh.Unmarshal<long>(_marsh.Marshal((long)1)), 1); + Assert.AreEqual(_marsh.Unmarshal<long>(_marsh.Marshal(long.MinValue)), long.MinValue); + Assert.AreEqual(_marsh.Unmarshal<long>(_marsh.Marshal(long.MaxValue)), long.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<long?>(_marsh.Marshal((long?)1)), (long?)1); + Assert.AreEqual(_marsh.Unmarshal<long?>(_marsh.Marshal((long?)null)), null); + } + + /** + * <summary>Check write of primitive long array.</summary> + */ + [Test] + public void TestWritePrimitiveLongArray() + { + long[] vals = { long.MinValue, 0, 1, long.MaxValue }; + long[] newVals = _marsh.Unmarshal<long[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive ulong.</summary> + */ + [Test] + public void TestWritePrimitiveUlong() + { + Assert.AreEqual(_marsh.Unmarshal<ulong>(_marsh.Marshal((ulong)1)), 1); + Assert.AreEqual(_marsh.Unmarshal<ulong>(_marsh.Marshal(ulong.MinValue)), ulong.MinValue); + Assert.AreEqual(_marsh.Unmarshal<ulong>(_marsh.Marshal(ulong.MaxValue)), ulong.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<ulong?>(_marsh.Marshal((ulong?)1)), (ulong?)1); + Assert.AreEqual(_marsh.Unmarshal<ulong?>(_marsh.Marshal((ulong?)null)), null); + } + + /** + * <summary>Check write of primitive ulong array.</summary> + */ + [Test] + public void TestWritePrimitiveUlongArray() + { + ulong[] vals = { ulong.MinValue, 0, 1, ulong.MaxValue }; + ulong[] newVals = _marsh.Unmarshal<ulong[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive float.</summary> + */ + [Test] + public void TestWritePrimitiveFloat() + { + Assert.AreEqual(_marsh.Unmarshal<float>(_marsh.Marshal((float)1)), (float)1); + Assert.AreEqual(_marsh.Unmarshal<float>(_marsh.Marshal(float.MinValue)), float.MinValue); + Assert.AreEqual(_marsh.Unmarshal<float>(_marsh.Marshal(float.MaxValue)), float.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<float?>(_marsh.Marshal((float?)1)), (float?)1); + Assert.AreEqual(_marsh.Unmarshal<float?>(_marsh.Marshal((float?)null)), null); + } + + /** + * <summary>Check write of primitive float array.</summary> + */ + [Test] + public void TestWritePrimitiveFloatArray() + { + float[] vals = { float.MinValue, 0, 1, float.MaxValue }; + float[] newVals = _marsh.Unmarshal<float[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of primitive double.</summary> + */ + [Test] + public void TestWritePrimitiveDouble() + { + Assert.AreEqual(_marsh.Unmarshal<double>(_marsh.Marshal((double)1)), (double)1); + Assert.AreEqual(_marsh.Unmarshal<double>(_marsh.Marshal(double.MinValue)), double.MinValue); + Assert.AreEqual(_marsh.Unmarshal<double>(_marsh.Marshal(double.MaxValue)), double.MaxValue); + + Assert.AreEqual(_marsh.Unmarshal<double?>(_marsh.Marshal((double?)1)), (double?)1); + Assert.AreEqual(_marsh.Unmarshal<double?>(_marsh.Marshal((double?)null)), null); + } + + /** + * <summary>Check write of primitive double array.</summary> + */ + [Test] + public void TestWritePrimitiveDoubleArray() + { + double[] vals = { double.MinValue, 0, 1, double.MaxValue }; + double[] newVals = _marsh.Unmarshal<double[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of decimal.</summary> + */ + [Test] + public void TestWritePrimitiveDecimal() + { + decimal val; + + // Test positibe and negative. + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Zero)), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = new decimal(1, 0, 0, false, 0))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = new decimal(1, 0, 0, true, 0))), val); + + // Test 32, 64 and 96 bits + mixed. + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = new decimal(0, 1, 0, false, 0))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = new decimal(0, 1, 0, true, 0))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = new decimal(0, 0, 1, false, 0))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = new decimal(0, 0, 1, true, 0))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = new decimal(1, 1, 1, false, 0))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = new decimal(1, 1, 1, true, 0))), val); + + // Test extremes. + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("65536"))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("-65536"))), val); + + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("4294967296"))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("-4294967296"))), val); + + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("281474976710656"))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("-281474976710656"))), val); + + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("18446744073709551616"))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("-18446744073709551616"))), val); + + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("1208925819614629174706176"))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("-1208925819614629174706176"))), val); + + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.MaxValue)), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.MinValue)), val); + + // Test scale. + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("11,12"))), val); + Assert.AreEqual(_marsh.Unmarshal<decimal>(_marsh.Marshal(val = decimal.Parse("-11,12"))), val); + + // Test null. + Assert.AreEqual(_marsh.Unmarshal<decimal?>(_marsh.Marshal((decimal?)null)), null); + } + + /** + * <summary>Check write of decimal array.</summary> + */ + [Test] + public void TestWritePrimitiveDecimalArray() + { + decimal?[] vals = { decimal.One, decimal.Parse("11,12") }; + var newVals = _marsh.Unmarshal<decimal?[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of string.</summary> + */ + [Test] + public void TestWriteString() + { + Assert.AreEqual(_marsh.Unmarshal<string>(_marsh.Marshal("str")), "str"); + Assert.AreEqual(_marsh.Unmarshal<string>(_marsh.Marshal((string) null)), null); + } + + /** + * <summary>Check write of string array.</summary> + */ + [Test] + public void TestWriteStringArray() + { + string[] vals = { "str1", null, "", "str2", null}; + string[] newVals = _marsh.Unmarshal<string[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of Guid.</summary> + */ + [Test] + public void TestWriteGuid() + { + Guid guid = Guid.NewGuid(); + Guid? nGuid = guid; + + Assert.AreEqual(_marsh.Unmarshal<Guid>(_marsh.Marshal(guid)), guid); + Assert.AreEqual(_marsh.Unmarshal<Guid?>(_marsh.Marshal(nGuid)), nGuid); + + nGuid = null; + + // ReSharper disable once ExpressionIsAlwaysNull + Assert.AreEqual(_marsh.Unmarshal<Guid?>(_marsh.Marshal(nGuid)), null); + } + + /** + * <summary>Check write of string array.</summary> + */ + [Test] + public void TestWriteGuidArray() + { + Guid?[] vals = { Guid.NewGuid(), null, Guid.Empty, Guid.NewGuid(), null }; + Guid?[] newVals = _marsh.Unmarshal<Guid?[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /** + * <summary>Check write of enum.</summary> + */ + [Test] + public void TestWriteEnum() + { + TestEnum val = TestEnum.Val1; + + Assert.AreEqual(_marsh.Unmarshal<TestEnum>(_marsh.Marshal(val)), val); + } + + /** + * <summary>Check write of enum.</summary> + */ + [Test] + public void TestWriteEnumArray() + { + TestEnum[] vals = { TestEnum.Val2, TestEnum.Val3 }; + TestEnum[] newVals = _marsh.Unmarshal<TestEnum[]>(_marsh.Marshal(vals)); + + Assert.AreEqual(vals, newVals); + } + + /// <summary> + /// Test object with dates. + /// </summary> + [Test] + public void TestDateObject() + { + ICollection<BinaryTypeConfiguration> typeCfgs = + new List<BinaryTypeConfiguration>(); + + typeCfgs.Add(new BinaryTypeConfiguration(typeof(DateTimeType))); + + BinaryConfiguration cfg = new BinaryConfiguration {TypeConfigurations = typeCfgs}; + + Marshaller marsh = new Marshaller(cfg); + + DateTime now = DateTime.Now; + + DateTimeType obj = new DateTimeType(now); + + DateTimeType otherObj = marsh.Unmarshal<DateTimeType>(marsh.Marshal(obj)); + + Assert.AreEqual(obj.Utc, otherObj.Utc); + Assert.AreEqual(obj.UtcNull, otherObj.UtcNull); + Assert.AreEqual(obj.UtcArr, otherObj.UtcArr); + + Assert.AreEqual(obj.UtcRaw, otherObj.UtcRaw); + Assert.AreEqual(obj.UtcNullRaw, otherObj.UtcNullRaw); + Assert.AreEqual(obj.UtcArrRaw, otherObj.UtcArrRaw); + } + + /// <summary> + /// Tests the DateTime marshalling. + /// </summary> + [Test] + public void TestDateTime() + { + var time = DateTime.Now; + Assert.AreEqual(_marsh.Unmarshal<DateTime>(_marsh.Marshal(time)), time); + + var timeUtc = DateTime.UtcNow; + Assert.AreEqual(_marsh.Unmarshal<DateTime>(_marsh.Marshal(timeUtc)), timeUtc); + + // Check exception with non-UTC date + var stream = new BinaryHeapStream(128); + var writer = _marsh.StartMarshal(stream); + Assert.Throws<InvalidOperationException>(() => writer.WriteTimestamp(DateTime.Now)); + } + + /** + * <summary>Check generic collections.</summary> + */ + [Test] + public void TestGenericCollections() + { + var list = new List<string> {"1"}; + + var data = _marsh.Marshal(list); + + var newObjList = _marsh.Unmarshal<IList<string>>(data); + + CollectionAssert.AreEquivalent(list, newObjList); + } + + /// <summary> + /// Tests marshal aware type with generic collections. + /// </summary> + [Test] + public void TestGenericCollectionsType() + { + var marsh = new Marshaller(new BinaryConfiguration + { + TypeConfigurations = new List<BinaryTypeConfiguration> + { + new BinaryTypeConfiguration(typeof (PrimitiveFieldType)), + new BinaryTypeConfiguration(typeof (GenericCollectionsType<PrimitiveFieldType, SerializableObject>)) + } + }); + + var obj = new GenericCollectionsType<PrimitiveFieldType, SerializableObject> + { + Keys = new[] {new PrimitiveFieldType(), new PrimitiveFieldType()}, + Values = + new List<SerializableObject> + { + new SerializableObject {Foo = 1}, + new SerializableObject {Foo = 5} + }, + Pairs = new Dictionary<PrimitiveFieldType, SerializableObject> + { + {new PrimitiveFieldType(), new SerializableObject {Foo = 10}}, + {new PrimitiveFieldType {PByte = 10}, new SerializableObject {Foo = 20}} + }, + Objects = new object[] {1, 2, "3", 4.4} + }; + + var data = marsh.Marshal(obj); + + var result = marsh.Unmarshal<GenericCollectionsType<PrimitiveFieldType, SerializableObject>>(data); + + CollectionAssert.AreEquivalent(obj.Keys, result.Keys); + CollectionAssert.AreEquivalent(obj.Values, result.Values); + CollectionAssert.AreEquivalent(obj.Pairs, result.Pairs); + CollectionAssert.AreEquivalent(obj.Objects, result.Objects); + } + + /** + * <summary>Check property read.</summary> + */ + [Test] + public void TestProperty() + { + ICollection<BinaryTypeConfiguration> typeCfgs = + new List<BinaryTypeConfiguration>(); + + typeCfgs.Add(new BinaryTypeConfiguration(typeof(PropertyType))); + + BinaryConfiguration cfg = new BinaryConfiguration {TypeConfigurations = typeCfgs}; + + Marshaller marsh = new Marshaller(cfg); + + PropertyType obj = new PropertyType + { + Field1 = 1, + Field2 = 2 + }; + + byte[] data = marsh.Marshal(obj); + + PropertyType newObj = marsh.Unmarshal<PropertyType>(data); + + Assert.AreEqual(obj.Field1, newObj.Field1); + Assert.AreEqual(obj.Field2, newObj.Field2); + + IBinaryObject portNewObj = marsh.Unmarshal<IBinaryObject>(data, BinaryMode.ForceBinary); + + Assert.AreEqual(obj.Field1, portNewObj.GetField<int>("field1")); + Assert.AreEqual(obj.Field2, portNewObj.GetField<int>("Field2")); + } + + /** + * <summary>Check write of primitive fields through reflection.</summary> + */ + [Test] + public void TestPrimitiveFieldsReflective() + { + ICollection<BinaryTypeConfiguration> typeCfgs = + new List<BinaryTypeConfiguration>(); + + typeCfgs.Add(new BinaryTypeConfiguration(typeof(PrimitiveFieldType))); + + BinaryConfiguration cfg = new BinaryConfiguration {TypeConfigurations = typeCfgs}; + + Marshaller marsh = new Marshaller(cfg); + + PrimitiveFieldType obj = new PrimitiveFieldType(); + + CheckPrimitiveFields(marsh, obj); + } + + /** + * <summary>Check write of primitive fields through binary interface.</summary> + */ + [Test] + public void TestPrimitiveFieldsBinary() + { + ICollection<BinaryTypeConfiguration> typeCfgs = + new List<BinaryTypeConfiguration>(); + + typeCfgs.Add(new BinaryTypeConfiguration(typeof(PrimitiveFieldBinaryType))); + + BinaryConfiguration cfg = new BinaryConfiguration(); + + cfg.TypeConfigurations = typeCfgs; + + Marshaller marsh = new Marshaller(cfg); + + PrimitiveFieldBinaryType obj = new PrimitiveFieldBinaryType(); + + CheckPrimitiveFields(marsh, obj); + } + + /** + * <summary>Check write of primitive fields through binary interface.</summary> + */ + [Test] + public void TestPrimitiveFieldsRawBinary() + { + ICollection<BinaryTypeConfiguration> typeCfgs = + new List<BinaryTypeConfiguration>(); + + typeCfgs.Add(new BinaryTypeConfiguration(typeof(PrimitiveFieldRawBinaryType))); + + BinaryConfiguration cfg = new BinaryConfiguration(); + + cfg.TypeConfigurations = typeCfgs; + + Marshaller marsh = new Marshaller(cfg); + + PrimitiveFieldRawBinaryType obj = new PrimitiveFieldRawBinaryType(); + + CheckPrimitiveFields(marsh, obj); + } + + /** + * <summary>Check write of primitive fields through binary interface.</summary> + */ + [Test] + public void TestPrimitiveFieldsSerializer() + { + var typeCfgs = new List<BinaryTypeConfiguration> + { + new BinaryTypeConfiguration(typeof (PrimitiveFieldType)) + { + Serializer = new PrimitiveFieldsSerializer() + } + }; + + BinaryConfiguration cfg = new BinaryConfiguration {TypeConfigurations = typeCfgs}; + + Marshaller marsh = new Marshaller(cfg); + + PrimitiveFieldType obj = new PrimitiveFieldType(); + + CheckPrimitiveFields(marsh, obj); + } + + /** + * <summary>Check decimals.</summary> + */ + [Test] + public void TestDecimalFields() + { + BinaryConfiguration cfg = new BinaryConfiguration + { + TypeConfigurations = new List<BinaryTypeConfiguration> + { + new BinaryTypeConfiguration(typeof (DecimalReflective)), + new BinaryTypeConfiguration(typeof (DecimalMarshalAware)) + } + }; + + Marshaller marsh = new Marshaller(cfg); + + // 1. Test reflective stuff. + DecimalReflective obj1 = new DecimalReflective + { + Val = decimal.Zero, + ValArr = new decimal?[] {decimal.One, decimal.MinusOne} + }; + + IBinaryObject portObj = marsh.Unmarshal<IBinaryObject>(marsh.Marshal(obj1), BinaryMode.ForceBinary); + + Assert.AreEqual(obj1.Val, portObj.GetField<decimal>("val")); + Assert.AreEqual(obj1.ValArr, portObj.GetField<decimal?[]>("valArr")); + + Assert.AreEqual(obj1.Val, portObj.Deserialize<DecimalReflective>().Val); + Assert.AreEqual(obj1.ValArr, portObj.Deserialize<DecimalReflective>().ValArr); + + // 2. Test marshal aware stuff. + DecimalMarshalAware obj2 = new DecimalMarshalAware(); + + obj2.Val = decimal.Zero; + obj2.ValArr = new decimal?[] { decimal.One, decimal.MinusOne }; + obj2.RawVal = decimal.MaxValue; + obj2.RawValArr = new decimal?[] { decimal.MinusOne, decimal.One} ; + + portObj = marsh.Unmarshal<IBinaryObject>(marsh.Marshal(obj2), BinaryMode.ForceBinary); + + Assert.AreEqual(obj2.Val, portObj.GetField<decimal>("val")); + Assert.AreEqual(obj2.ValArr, portObj.GetField<decimal?[]>("valArr")); + + Assert.AreEqual(obj2.Val, portObj.Deserialize<DecimalMarshalAware>().Val); + Assert.AreEqual(obj2.ValArr, portObj.Deserialize<DecimalMarshalAware>().ValArr); + Assert.AreEqual(obj2.RawVal, portObj.Deserialize<DecimalMarshalAware>().RawVal); + Assert.AreEqual(obj2.RawValArr, portObj.Deserialize<DecimalMarshalAware>().RawValArr); + } + + /** + * <summary>Check write of primitive fields through raw serializer.</summary> + */ + [Test] + public void TestPrimitiveFieldsRawSerializer() + { + ICollection<BinaryTypeConfiguration> typeCfgs = + new List<BinaryTypeConfiguration>(); + + BinaryTypeConfiguration typeCfg = + new BinaryTypeConfiguration(typeof(PrimitiveFieldType)); + + typeCfg.Serializer = new PrimitiveFieldsRawSerializer(); + + typeCfgs.Add(typeCfg); + + BinaryConfiguration cfg = new BinaryConfiguration(); + + cfg.TypeConfigurations = typeCfgs; + + Marshaller marsh = new Marshaller(cfg); + + PrimitiveFieldType obj = new PrimitiveFieldType(); + + CheckPrimitiveFields(marsh, obj); + } + + private void CheckPrimitiveFields(Marshaller marsh, PrimitiveFieldType obj) + { + obj.PBool = true; + obj.PByte = 2; + obj.PSbyte = 3; + obj.PShort = 4; + obj.PUshort = 5; + obj.PInt = 6; + obj.PUint = 7; + obj.PLong = 8; + obj.PUlong = 9; + obj.PChar = 'a'; + obj.PFloat = 10; + obj.PDouble = 11; + obj.PString = "abc"; + obj.PGuid = Guid.NewGuid(); + obj.PnGuid = Guid.NewGuid(); + obj.IgniteGuid = new IgniteGuid(Guid.NewGuid(), 123); + + CheckPrimitiveFieldsSerialization(marsh, obj); + } + + private void CheckPrimitiveFieldsSerialization(Marshaller marsh, PrimitiveFieldType obj) + { + byte[] bytes = marsh.Marshal(obj); + + IBinaryObject portObj = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary); + + Assert.AreEqual(obj.GetHashCode(), portObj.GetHashCode()); + + PrimitiveFieldType newObj = portObj.Deserialize<PrimitiveFieldType>(); + + Assert.AreEqual(obj, newObj); + } + + /** + * <summary>Check write of object with enums.</summary> + */ + [Test] + public void TestEnumsReflective() + { + Marshaller marsh = + new Marshaller(new BinaryConfiguration + { + TypeConfigurations = + new List<BinaryTypeConfiguration> {new BinaryTypeConfiguration(typeof (EnumType))} + }); + + EnumType obj = new EnumType + { + PEnum = TestEnum.Val1, + PEnumArray = new[] {TestEnum.Val2, TestEnum.Val3} + }; + + byte[] bytes = marsh.Marshal(obj); + + IBinaryObject portObj = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary); + + Assert.AreEqual(obj.GetHashCode(), portObj.GetHashCode()); + + EnumType newObj = portObj.Deserialize<EnumType>(); + + Assert.AreEqual(obj.PEnum, newObj.PEnum); + Assert.AreEqual(obj.PEnumArray, newObj.PEnumArray); + } + + /** + * <summary>Check write of object with collections.</summary> + */ + [Test] + public void TestCollectionsReflective() + { + var marsh = new Marshaller(new BinaryConfiguration + { + TypeConfigurations = new List<BinaryTypeConfiguration> + { + new BinaryTypeConfiguration(typeof (CollectionsType)), + new BinaryTypeConfiguration(typeof (InnerObjectType)) + } + }); + + var obj = new CollectionsType + { + Hashtable = new Hashtable {{1, 2}, {3, 4}}, + LinkedList = new LinkedList<int>(new[] {1, 2, 3}), + SortedDict = new SortedDictionary<string, int> {{"1", 2}}, + Dict = new Dictionary<int, string> {{1, "2"}}, + Arr = new[] {new InnerObjectType()} + }; + + var list = new ArrayList + { + true, + (byte) 1, + (short) 2, + 'a', + 3, + (long) 4, + (float) 5, + (double) 6, + "string", + Guid.NewGuid(), + new InnerObjectType + { + PInt1 = 1, + PInt2 = 2 + } + }; + + obj.Col1 = list; + + byte[] bytes = marsh.Marshal(obj); + + IBinaryObject portObj = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary); + + Assert.AreEqual(obj.GetHashCode(), portObj.GetHashCode()); + + CollectionsType newObj = portObj.Deserialize<CollectionsType>(); + + Assert.AreEqual(obj, newObj); + + obj.Col1 = null; + + Assert.AreEqual(obj, marsh.Unmarshal<CollectionsType>(marsh.Marshal(obj))); + + obj.Col1 = list; + obj.Col2 = list; + + Assert.AreEqual(obj, marsh.Unmarshal<CollectionsType>(marsh.Marshal(obj))); + + obj.Col2 = new TestList(); + + Assert.AreEqual(obj, marsh.Unmarshal<CollectionsType>(marsh.Marshal(obj))); + } + + /** + * <summary>Check write of object fields through reflective serializer.</summary> + */ + [Test] + public void TestObjectReflective() + { + ICollection<BinaryTypeConfiguration> typeCfgs = + new List<BinaryTypeConfiguration>(); + + typeCfgs.Add(new BinaryTypeConfiguration(typeof(OuterObjectType))); + typeCfgs.Add(new BinaryTypeConfiguration(typeof(InnerObjectType))); + + BinaryConfiguration cfg = new BinaryConfiguration(); + + cfg.TypeConfigurations = typeCfgs; + + Marshaller marsh = new Marshaller(cfg); + + CheckObject(marsh, new OuterObjectType(), new InnerObjectType()); + } + + /** + * <summary>Test handles.</summary> + */ + [Test] + public void TestHandles() + { + ICollection<BinaryTypeConfiguration> typeCfgs = + new List<BinaryTypeConfiguration>(); + + typeCfgs.Add(new BinaryTypeConfiguration(typeof(HandleInner))); + typeCfgs.Add(new BinaryTypeConfiguration(typeof(HandleOuter))); + + BinaryConfiguration cfg = new BinaryConfiguration(); + + cfg.TypeConfigurations = typeCfgs; + + Marshaller marsh = new Marshaller(cfg); + + HandleOuter outer = new HandleOuter(); + + outer.Before = "outBefore"; + outer.After = "outAfter"; + outer.RawBefore = "outRawBefore"; + outer.RawAfter = "outRawAfter"; + + HandleInner inner = new HandleInner(); + + inner.Before = "inBefore"; + inner.After = "inAfter"; + inner.RawBefore = "inRawBefore"; + inner.RawAfter = "inRawAfter"; + + outer.Inner = inner; + outer.RawInner = inner; + + inner.Outer = outer; + inner.RawOuter = outer; + + byte[] bytes = marsh.Marshal(outer); + + IBinaryObject outerObj = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary); + + HandleOuter newOuter = outerObj.Deserialize<HandleOuter>(); + HandleInner newInner = newOuter.Inner; + + CheckHandlesConsistency(outer, inner, newOuter, newInner); + + // Get inner object by field. + IBinaryObject innerObj = outerObj.GetField<IBinaryObject>("inner"); + + newInner = innerObj.Deserialize<HandleInner>(); + newOuter = newInner.Outer; + + CheckHandlesConsistency(outer, inner, newOuter, newInner); + + // Get outer object from inner object by handle. + outerObj = innerObj.GetField<IBinaryObject>("outer"); + + newOuter = outerObj.Deserialize<HandleOuter>(); + newInner = newOuter.Inner; + + CheckHandlesConsistency(outer, inner, newOuter, newInner); + } + + /** + * <summary>Test handles with exclusive writes.</summary> + */ + [Test] + public void TestHandlesExclusive([Values(true, false)] bool detached, [Values(true, false)] bool asbinary) + { + var marsh = new Marshaller(new BinaryConfiguration + { + TypeConfigurations = new List<BinaryTypeConfiguration> + { + new BinaryTypeConfiguration(typeof (HandleInner)), + new BinaryTypeConfiguration(typeof (HandleOuterExclusive)) + } + }); + + var inner = new HandleInner + { + Before = "inBefore", + After = "inAfter", + RawBefore = "inRawBefore", + RawAfter = "inRawAfter" + }; + + var outer = new HandleOuterExclusive + { + Before = "outBefore", + After = "outAfter", + RawBefore = "outRawBefore", + RawAfter = "outRawAfter", + Inner = inner, + RawInner = inner + }; + + inner.Outer = outer; + inner.RawOuter = outer; + + var bytes = asbinary + ? marsh.Marshal(new IgniteBinary(marsh).ToBinary<IBinaryObject>(outer)) + : marsh.Marshal(outer); + + IBinaryObject outerObj; + + if (detached) + { + var reader = new BinaryReader(marsh, new Dictionary<long, IBinaryTypeDescriptor>(), + new BinaryHeapStream(bytes), BinaryMode.ForceBinary, null); + + reader.DetachNext(); + + outerObj = reader.Deserialize<IBinaryObject>(); + } + else + outerObj = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary); + + HandleOuter newOuter = outerObj.Deserialize<HandleOuter>(); + + Assert.IsFalse(newOuter == newOuter.Inner.Outer); + Assert.IsFalse(newOuter == newOuter.Inner.RawOuter); + Assert.IsFalse(newOuter == newOuter.RawInner.RawOuter); + Assert.IsFalse(newOuter == newOuter.RawInner.RawOuter); + + Assert.IsFalse(newOuter.Inner == newOuter.RawInner); + + Assert.IsTrue(newOuter.Inner.Outer == newOuter.Inner.RawOuter); + Assert.IsTrue(newOuter.RawInner.Outer == newOuter.RawInner.RawOuter); + + Assert.IsTrue(newOuter.Inner == newOuter.Inner.Outer.Inner); + Assert.IsTrue(newOuter.Inner == newOuter.Inner.Outer.RawInner); + Assert.IsTrue(newOuter.RawInner == newOuter.RawInner.Outer.Inner); + Assert.IsTrue(newOuter.RawInner == newOuter.RawInner.Outer.RawInner); + } + + /// + /// <summary>Test KeepSerialized property</summary> + /// + [Test] + public void TestKeepSerializedDefault() + { + CheckKeepSerialized(new BinaryConfiguration(), true); + } + + /// + /// <summary>Test KeepSerialized property</summary> + /// + [Test] + public void TestKeepSerializedDefaultFalse() + { + BinaryConfiguration cfg = new BinaryConfiguration(); + + cfg.DefaultKeepDeserialized = false; + + CheckKeepSerialized(cfg, false); + } + + /// + /// <summary>Test KeepSerialized property</summary> + /// + [Test] + public void TestKeepSerializedTypeCfgFalse() + { + BinaryTypeConfiguration typeCfg = new BinaryTypeConfiguration(typeof(PropertyType)); + + typeCfg.KeepDeserialized = false; + + BinaryConfiguration cfg = new BinaryConfiguration(); + + cfg.TypeConfigurations = new List<BinaryTypeConfiguration> { typeCfg }; + + CheckKeepSerialized(cfg, false); + } + + /// + /// <summary>Test KeepSerialized property</summary> + /// + [Test] + public void TestKeepSerializedTypeCfgTrue() + { + BinaryTypeConfiguration typeCfg = new BinaryTypeConfiguration(typeof(PropertyType)); + typeCfg.KeepDeserialized = true; + + BinaryConfiguration cfg = new BinaryConfiguration(); + cfg.DefaultKeepDeserialized = false; + + cfg.TypeConfigurations = new List<BinaryTypeConfiguration> { typeCfg }; + + CheckKeepSerialized(cfg, true); + } + + /// <summary> + /// Test correct serialization/deserialization of arrays of special types. + /// </summary> + [Test] + public void TestSpecialArrays() + { + ICollection<BinaryTypeConfiguration> typeCfgs = + new List<BinaryTypeConfiguration>(); + + typeCfgs.Add(new BinaryTypeConfiguration(typeof(SpecialArray))); + typeCfgs.Add(new BinaryTypeConfiguration(typeof(SpecialArrayMarshalAware))); + + BinaryConfiguration cfg = new BinaryConfiguration(); + + cfg.TypeConfigurations = typeCfgs; + + Marshaller marsh = new Marshaller(cfg); + + Guid[] guidArr = { Guid.NewGuid() }; + Guid?[] nGuidArr = { Guid.NewGuid() }; + DateTime[] dateArr = { DateTime.Now.ToUniversalTime() }; + DateTime?[] nDateArr = { DateTime.Now.ToUniversalTime() }; + + // Use special object. + SpecialArray obj1 = new SpecialArray + { + GuidArr = guidArr, + NGuidArr = nGuidArr, + DateArr = dateArr, + NDateArr = nDateArr + }; + + byte[] bytes = marsh.Marshal(obj1); + + IBinaryObject portObj = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary); + + Assert.IsNotNull(portObj.Deserialize<SpecialArray>()); + + Assert.AreEqual(guidArr, portObj.GetField<Guid[]>("guidArr")); + Assert.AreEqual(nGuidArr, portObj.GetField<Guid?[]>("nGuidArr")); + Assert.AreEqual(dateArr, portObj.GetField<DateTime[]>("dateArr")); + Assert.AreEqual(nDateArr, portObj.GetField<DateTime?[]>("nDateArr")); + + obj1 = portObj.Deserialize<SpecialArray>(); + + Assert.AreEqual(guidArr, obj1.GuidArr); + Assert.AreEqual(nGuidArr, obj1.NGuidArr); + Assert.AreEqual(dateArr, obj1.DateArr); + Assert.AreEqual(nDateArr, obj1.NDateArr); + + // Use special with IGridbinaryMarshalAware. + SpecialArrayMarshalAware obj2 = new SpecialArrayMarshalAware(); + + obj2.GuidArr = guidArr; + obj2.NGuidArr = nGuidArr; + obj2.DateArr = dateArr; + obj2.NDateArr = nDateArr; + + bytes = marsh.Marshal(obj2); + + portObj = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary); + + Assert.AreEqual(guidArr, portObj.GetField<Guid[]>("a")); + Assert.AreEqual(nGuidArr, portObj.GetField<Guid?[]>("b")); + Assert.AreEqual(dateArr, portObj.GetField<DateTime[]>("c")); + Assert.AreEqual(nDateArr, portObj.GetField<DateTime?[]>("d")); + + obj2 = portObj.Deserialize<SpecialArrayMarshalAware>(); + + Assert.AreEqual(guidArr, obj2.GuidArr); + Assert.AreEqual(nGuidArr, obj2.NGuidArr); + Assert.AreEqual(dateArr, obj2.DateArr); + Assert.AreEqual(nDateArr, obj2.NDateArr); + } + + /// <summary> + /// Writes objects of various sizes to test schema compaction + /// (where field offsets can be stored as 1, 2 or 4 bytes). + /// </summary> + [Test] + public void TestCompactSchema() + { + var marsh = new Marshaller(new BinaryConfiguration + { + TypeConfigurations = new List<BinaryTypeConfiguration> + { + new BinaryTypeConfiguration(typeof (SpecialArray)), + new BinaryTypeConfiguration(typeof (SpecialArrayMarshalAware)) + } + }); + + var dt = new SpecialArrayMarshalAware(); + + foreach (var i in new[] {1, 5, 10, 13, 14, 15, 100, 200, 1000, 5000, 15000, 30000}) + { + dt.NGuidArr = Enumerable.Range(1, i).Select(x => (Guid?) Guid.NewGuid()).ToArray(); + dt.NDateArr = Enumerable.Range(1, i).Select(x => (DateTime?) DateTime.Now.AddDays(x)).ToArray(); + + var bytes = marsh.Marshal(dt); + + var res = marsh.Unmarshal<SpecialArrayMarshalAware>(bytes); + + CollectionAssert.AreEquivalent(dt.NGuidArr, res.NGuidArr); + CollectionAssert.AreEquivalent(dt.NDateArr, res.NDateArr); + } + } + + private static void CheckKeepSerialized(BinaryConfiguration cfg, bool expKeep) + { + if (cfg.TypeConfigurations == null) + { + cfg.TypeConfigurations = new List<BinaryTypeConfiguration> + { + new BinaryTypeConfiguration(typeof(PropertyType)) + }; + } + + Marshaller marsh = new Marshaller(cfg); + + byte[] data = marsh.Marshal(new PropertyType()); + + IBinaryObject portNewObj = marsh.Unmarshal<IBinaryObject>(data, BinaryMode.ForceBinary); + + PropertyType deserialized1 = portNewObj.Deserialize<PropertyType>(); + PropertyType deserialized2 = portNewObj.Deserialize<PropertyType>(); + + Assert.NotNull(deserialized1); + + Assert.AreEqual(expKeep, deserialized1 == deserialized2); + } + + private void CheckHandlesConsistency(HandleOuter outer, HandleInner inner, HandleOuter newOuter, + HandleInner newInner) + { + Assert.True(newOuter != null); + Assert.AreEqual(outer.Before, newOuter.Before); + Assert.True(newOuter.Inner == newInner); + Assert.AreEqual(outer.After, newOuter.After); + Assert.AreEqual(outer.RawBefore, newOuter.RawBefore); + Assert.True(newOuter.RawInner == newInner); + Assert.AreEqual(outer.RawAfter, newOuter.RawAfter); + + Assert.True(newInner != null); + Assert.AreEqual(inner.Before, newInner.Before); + Assert.True(newInner.Outer == newOuter); + Assert.AreEqual(inner.After, newInner.After); + Assert.AreEqual(inner.RawBefore, newInner.RawBefore); + Assert.True(newInner.RawOuter == newOuter); + Assert.AreEqual(inner.RawAfter, newInner.RawAfter); + } + + private static void CheckObject(Marshaller marsh, OuterObjectType outObj, InnerObjectType inObj) + { + inObj.PInt1 = 1; + inObj.PInt2 = 2; + + outObj.InObj = inObj; + + byte[] bytes = marsh.Marshal(outObj); + + IBinaryObject portOutObj = marsh.Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary); + + Assert.AreEqual(outObj.GetHashCode(), portOutObj.GetHashCode()); + + OuterObjectType newOutObj = portOutObj.Deserialize<OuterObjectType>(); + + Assert.AreEqual(outObj, newOutObj); + } + + public class OuterObjectType + { + public InnerObjectType InObj { get; set; } + + /** <inheritdoc /> */ + public override bool Equals(object obj) + { + if (this == obj) + return true; + + var type = obj as OuterObjectType; + + return type != null && Equals(InObj, type.InObj); + } + + /** <inheritdoc /> */ + public override int GetHashCode() + { + return InObj != null ? InObj.GetHashCode() : 0; + } + } + + [Serializable] + public class InnerObjectType + { + public int PInt1 { get; set; } + + public int PInt2 { get; set; } + + /** <inheritdoc /> */ + public override bool Equals(object obj) + { + if (this == obj) + return true; + + var that = obj as InnerObjectType; + + return that != null && (PInt1 == that.PInt1 && PInt2 == that.PInt2); + } + + /** <inheritdoc /> */ + public override int GetHashCode() + { + return 31 * PInt1 + PInt2; + } + + /** <inheritdoc /> */ + public override string ToString() + { + return "InnerObjectType[pInt1=" + PInt1 + ", pInt2=" + PInt2 + ']'; + } + } + + public class CollectionsType + { + public ICollection Col1 { get; set; } + + public ArrayList Col2 { get; set; } + + public Hashtable Hashtable { get; set; } + + public Dictionary<int, string> Dict { get; set; } + + public InnerObjectType[] Arr { get; set; } + + public SortedDictionary<string, int> SortedDict { get; set; } + + public LinkedList<int> LinkedList { get; set; } + + /** <inheritdoc /> */ + public override bool Equals(object obj) + { + if (this == obj) + return true; + + var that = obj as CollectionsType; + + return that != null + && CompareCollections(Col1, that.Col1) + && CompareCollections(Col2, that.Col2) + && CompareCollections(Hashtable, that.Hashtable) + && CompareCollections(Dict, that.Dict) + && CompareCollections(Arr, that.Arr) + && CompareCollections(SortedDict, that.SortedDict) + && CompareCollections(LinkedList, that.LinkedList); + } + + /** <inheritdoc /> */ + public override int GetHashCode() + { + int res = 0; + + foreach (var col in new object[] {Col1, Col2, Hashtable, Dict, Arr, SortedDict, LinkedList}) + res = 31*res + (col != null ? col.GetHashCode() : 0); + + return res; + } + } + + public class GenericCollectionsType<TKey, TValue> : IBinarizable + { + public ICollection<TKey> Keys { get; set; } + + public ICollection<TValue> Values { get; set; } + + public IDictionary<TKey, TValue> Pairs { get; set; } + + public ICollection<object> Objects { get; set; } + + public void WriteBinary(IBinaryWriter writer) + { + writer.WriteObject("Keys", Keys); + writer.WriteObject("Values", Values); + writer.WriteObject("Pairs", Pairs); + writer.WriteObject("Objects", Objects); + } + + public void ReadBinary(IBinaryReader reader) + { + Keys = (ICollection<TKey>) reader.ReadObject<object>("Keys"); + Values = (ICollection<TValue>) reader.ReadObject<object>("Values"); + Pairs = (IDictionary<TKey, TValue>) reader.ReadObject<object>("Pairs"); + Objects = (ICollection<object>) reader.ReadObject<object>("Objects"); + } + } + + public class TestList : ArrayList + { + + } + + private static bool CompareCollections(ICollection col1, ICollection col2) + { + if (col1 == null && col2 == null) + return true; + if (col1 == null || col2 == null) + return false; + + return col1.OfType<object>().SequenceEqual(col2.OfType<object>()); + } + + public class PrimitiveArrayFieldType + { + public bool[] PBool { get; set; } + + public sbyte[] PSbyte { get; set; } + + public byte[] PByte { get; set; } + + public short[] PShort { get; set; } + + public ushort[] PUshort { get; set; } + + public char[] PChar { get; set; } + + public int[] PInt { get; set; } + + public uint[] PUint { get; set; } + + public long[] PLong { get; set; } + + public ulong[] PUlong { get; set; } + + public float[] PFloat { get; set; } + + public double[] PDouble { get; set; } + + public string[] PString { get; set; } + + public Guid?[] PGuid { get; set; } + + /** <inheritdoc /> */ + public override bool Equals(object obj) + { + if (this == obj) + return true; + + var other = obj as PrimitiveArrayFieldType; + + return other != null && (PBool == other.PBool && + PByte == other.PByte && + PSbyte == other.PSbyte && + PShort == other.PShort && + PUshort == other.PUshort && + PInt == other.PInt && + PUint == other.PUint && + PLong == other.PLong && + PUlong == other.PUlong && + PChar == other.PChar && + PFloat == other.PFloat && + PDouble == other.PDouble && + PString == other.PString && + PGuid == other.PGuid); + } + + /** <inheritdoc /> */ + public override int GetHashCode() + { + return PInt != null && PInt.Length > 0 ? PInt[0].GetHashCode() : 0; + } + } + + public class SpecialArray + { + public Guid[] GuidArr; + public Guid?[] NGuidArr; + public DateTime[] DateArr; + public DateTime?[] NDateArr; + } + + public class SpecialArrayMarshalAware : SpecialArray, IBinarizable + { + public void WriteBinary(IBinaryWriter writer) + { + writer.WriteObject("a", GuidArr); + writer.WriteObject("b", NGuidArr); + writer.WriteObject("c", DateArr); + writer.WriteObject("d", NDateArr); + } + + public void ReadBinary(IBinaryReader reader) + { + GuidArr = reader.ReadObject<Guid[]>("a"); + NGuidArr = reader.ReadObject<Guid?[]>("b"); + DateArr = reader.ReadObject<DateTime[]>("c"); + NDateArr = reader.ReadObject<DateTime?[]>("d"); + } + } + + public class EnumType + { + public TestEnum PEnum { get; set; } + + public TestEnum[] PEnumArray { get; set; } + } + + [Serializable] + public class PrimitiveFieldType + { + public bool PBool { get; set; } + + public sbyte PSbyte { get; set; } + + public byte PByte { get; set; } + + public short PShort { get; set; } + + public ushort PUshort { get; set; } + + public char PChar { get; set; } + + public int PInt { get; set; } + + public uint PUint { get; set; } + + public long PLong { get; set; } + + public ulong PUlong { get; set; } + + public float PFloat { get; set; } + + public double PDouble { get; set; } + + public string PString { get; set; } + + public Guid PGuid { get; set; } + + public Guid? PnGuid { get; set; } + + public IgniteGuid IgniteGuid { get; set; } + + /** <inheritdoc /> */ + public override bool Equals(object obj) + { + if (this == obj) + return true; + + if (obj != null && obj is PrimitiveFieldType) + { + PrimitiveFieldType that = (PrimitiveFieldType)obj; + + return PBool == that.PBool && + PByte == that.PByte && + PSbyte == that.PSbyte && + PShort == that.PShort && + PUshort == that.PUshort && + PInt == that.PInt && + PUint == that.PUint && + PLong == that.PLong && + PUlong == that.PUlong && + PChar == that.PChar && + PFloat == that.PFloat && + PDouble == that.PDouble && + (string.Equals(PString, that.PString)) && + PGuid.Equals(that.PGuid) && + IgniteGuid.Equals(that.IgniteGuid) && + (PnGuid == null && that.PnGuid == null || PnGuid != null && PnGuid.Equals(that.PnGuid)); + } + return false; + } + + /** <inheritdoc /> */ + public override int GetHashCode() + { + return PInt; + } + } + + public class PrimitiveFieldBinaryType : PrimitiveFieldType, IBinarizable + { + public unsafe void WriteBinary(IBinaryWriter writer) + { + writer.WriteBoolean("bool", PBool); + writer.WriteByte("byte", PByte); + writer.WriteShort("short", PShort); + writer.WriteInt("int", PInt); + writer.WriteLong("long", PLong); + writer.WriteChar("char", PChar); + writer.WriteFloat("float", PFloat); + writer.WriteDouble("double", PDouble); + + sbyte sByte = PSbyte; + ushort uShort = PUshort; + uint uInt = PUint; + ulong uLong = PUlong; + + writer.WriteByte("sbyte", *(byte*)&sByte); + writer.WriteShort("ushort", *(short*)&uShort); + writer.WriteInt("uint", *(int*)&uInt); + writer.WriteLong("ulong", *(long*)&uLong); + + writer.WriteString("string", PString); + writer.WriteGuid("guid", PGuid); + writer.WriteGuid("nguid", PnGuid); + + writer.WriteObject("iguid", IgniteGuid); + } + + public unsafe void ReadBinary(IBinaryReader reader) + { + PBool = reader.ReadBoolean("bool"); + PByte = reader.ReadByte("byte"); + PShort = reader.ReadShort("short"); + PInt = reader.ReadInt("int"); + + PLong = reader.ReadLong("long"); + PChar = reader.ReadChar("char"); + PFloat = reader.ReadFloat("float"); + PDouble = reader.ReadDouble("double"); + + byte sByte = reader.ReadByte("sbyte"); + short uShort = reader.ReadShort("ushort"); + int uInt = reader.ReadInt("uint"); + long uLong = reader.ReadLong("ulong"); + + PSbyte = *(sbyte*)&sByte; + PUshort = *(ushort*)&uShort; + PUint = *(uint*)&uInt; + PUlong = *(ulong*)&uLong; + + PString = reader.ReadString("string"); + PGuid = reader.ReadObject<Guid>("guid"); + PnGuid = reader.ReadGuid("nguid"); + + IgniteGuid = reader.ReadObject<IgniteGuid>("iguid"); + } + } + + public class PrimitiveFieldRawBinaryType : PrimitiveFieldType, IBinarizable + { + public unsafe void WriteBinary(IBinaryWriter writer) + { + IBinaryRawWriter rawWriter = writer.GetRawWriter(); + + rawWriter.WriteBoolean(PBool); + rawWriter.WriteByte(PByte); + rawWriter.WriteShort(PShort); + rawWriter.WriteInt(PInt); + rawWriter.WriteLong(PLong); + rawWriter.WriteChar(PChar); + rawWriter.WriteFloat(PFloat); + rawWriter.WriteDouble(PDouble); + + sbyte sByte = PSbyte; + ushort uShort = PUshort; + uint uInt = PUint; + ulong uLong = PUlong; + + rawWriter.WriteByte(*(byte*)&sByte); + rawWriter.WriteShort(*(short*)&uShort); + rawWriter.WriteInt(*(int*)&uInt); + rawWriter.WriteLong(*(long*)&uLong); + + rawWriter.WriteString(PString); + rawWriter.WriteGuid(PGuid); + rawWriter.WriteGuid(PnGuid); + + rawWriter.WriteObject(IgniteGuid); + } + + public unsafe void ReadBinary(IBinaryReader reader) + { + IBinaryRawReader rawReader = reader.GetRawReader(); + + PBool = rawReader.ReadBoolean(); + PByte = rawReader.ReadByte(); + PShort = rawReader.ReadShort(); + PInt = rawReader.ReadInt(); + + PLong = rawReader.ReadLong(); + PChar = rawReader.ReadChar(); + PFloat = rawReader.ReadFloat(); + PDouble = rawReader.ReadDouble(); + + byte sByte = rawReader.ReadByte(); + short uShort = rawReader.ReadShort(); + int uInt = rawReader.ReadInt(); + long uLong = rawReader.ReadLong(); + + PSbyte = *(sbyte*)&sByte; + PUshort = *(ushort*)&uShort; + PUint = *(uint*)&uInt; + PUlong = *(ulong*)&uLong; + + PString = rawReader.ReadString(); + PGuid = rawReader.ReadGuid().Value; + PnGuid = rawReader.ReadGuid(); + + IgniteGuid = rawReader.ReadObject<IgniteGuid>(); + } + } + + public class PrimitiveFieldsSerializer : IBinarySerializer + { + public unsafe void WriteBinary(object obj, IBinaryWriter writer) + { + PrimitiveFieldType obj0 = (PrimitiveFieldType)obj; + + writer.WriteBoolean("bool", obj0.PBool); + writer.WriteByte("byte", obj0.PByte); + writer.WriteShort("short", obj0.PShort); + writer.WriteInt("int", obj0.PInt); + writer.WriteLong("long", obj0.PLong); + writer.WriteChar("char", obj0.PChar); + writer.WriteFloat("float", obj0.PFloat); + writer.WriteDouble("double", obj0.PDouble); + + sbyte sByte = obj0.PSbyte; + ushort uShort = obj0.PUshort; + uint uInt = obj0.PUint; + ulong uLong = obj0.PUlong; + + writer.WriteByte("sbyte", *(byte*)&sByte); + writer.WriteShort("ushort", *(short*)&uShort); + writer.WriteInt("uint", *(int*)&uInt); + writer.WriteLong("ulong", *(long*)&uLong); + + writer.WriteString("string", obj0.PString); + writer.WriteGuid("guid", obj0.PGuid); + writer.WriteGuid("nguid", obj0.PnGuid); + + writer.WriteObject("iguid", obj0.IgniteGuid); + } + + public unsafe void ReadBinary(object obj, IBinaryReader reader) + { + PrimitiveFieldType obj0 = (PrimitiveFieldType)obj; + + obj0.PBool = reader.ReadBoolean("bool"); + obj0.PByte = reader.ReadByte("byte"); + obj0.PShort = reader.ReadShort("short"); + obj0.PInt = reader.ReadInt("int"); + + obj0.PLong = reader.ReadLong("long"); + obj0.PChar = reader.ReadChar("char"); + obj0.PFloat = reader.ReadFloat("float"); + obj0.PDouble = reader.ReadDouble("double"); + + byte sByte = reader.ReadByte("sbyte"); + short uShort = reader.ReadShort("ushort"); + int uInt = reader.ReadInt("uint"); + long uLong = reader.ReadLong("ulong"); + + obj0.PSbyte = *(sbyte*)&sByte; + obj0.PUshort = *(ushort*)&uShort; + obj0.PUint = *(uint*)&uInt; + obj0.PUlong = *(ulong*)&uLong; + + obj0.PString = reader.ReadString("string"); + obj0.PGuid = reader.ReadObject<Guid>("guid"); + obj0.PnGuid = reader.ReadGuid("nguid"); + + obj0.IgniteGuid = reader.ReadObject<IgniteGuid>("iguid"); + } + } + + public class PrimitiveFieldsRawSerializer : IBinarySerializer + { + public unsafe void WriteBinary(object obj, IBinaryWriter writer) + { + PrimitiveFieldType obj0 = (PrimitiveFieldType)obj; + + IBinaryRawWriter rawWriter = writer.GetRawWriter(); + + rawWriter.WriteBoolean(obj0.PBool); + rawWriter.WriteByte(obj0.PByte); + rawWriter.WriteShort( obj0.PShort); + rawWriter.WriteInt( obj0.PInt); + rawWriter.WriteLong( obj0.PLong); + rawWriter.WriteChar(obj0.PChar); + rawWriter.WriteFloat(obj0.PFloat); + rawWriter.WriteDouble( obj0.PDouble); + + sbyte sByte = obj0.PSbyte; + ushort uShort = obj0.PUshort; + uint uInt = obj0.PUint; + ulong uLong = obj0.PUlong; + + rawWriter.WriteByte(*(byte*)&sByte); + rawWriter.WriteShort(*(short*)&uShort); + rawWriter.WriteInt(*(int*)&uInt); + rawWriter.WriteLong(*(long*)&uLong); + + rawWriter.WriteString(obj0.PString); + rawWriter.WriteGuid(obj0.PGuid); + rawWriter.WriteGuid(obj0.PnGuid); + + rawWriter.WriteObject(obj0.IgniteGuid); + } + + public unsafe void ReadBinary(object obj, IBinaryReader reader) + { + PrimitiveFieldType obj0 = (PrimitiveFieldType)obj; + + IBinaryRawReader rawReader = reader.GetRawReader(); + + obj0.PBool = rawReader.ReadBoolean(); + obj0.PByte = rawReader.ReadByte(); + obj0.PShort = rawReader.ReadShort(); + obj0.PInt = rawReader.ReadInt(); + obj0.PLong = rawReader.ReadLong(); + obj0.PChar = rawReader.ReadChar(); + obj0.PFloat = rawReader.ReadFloat(); + obj0.PDouble = rawReader.ReadDouble(); + + byte sByte = rawReader.ReadByte(); + short uShort = rawReader.ReadShort(); + int uInt = rawReader.ReadInt(); + long uLong = rawReader.ReadLong(); + + obj0.PSbyte = *(sbyte*)&sByte; + obj0.PUshort = *(ushort*)&uShort; + obj0.PUint = *(uint*)&uInt; + obj0.PUlong = *(ulong*)&uLong; + + obj0.PString = rawReader.ReadString(); + obj0.PGuid = rawReader.ReadGuid().Value; + obj0.PnGuid = rawReader.ReadGuid(); + + obj0.IgniteGuid = rawReader.ReadObject<IgniteGuid>(); + } + } + + public class HandleOuter : IBinarizable + { + public string Before; + public HandleInner Inner; + public string After; + + public string RawBefore; + public HandleInner RawInner; + public string RawAfter; + + /** <inheritdoc /> */ + virtual public void WriteBinary(IBinaryWriter writer) + { + writer.WriteString("before", Before); + writer.WriteObject("inner", Inner); + writer.WriteString("after", After); + + IBinaryRawWriter rawWriter = writer.GetRawWriter(); + + rawWriter.WriteString(RawBefore); + rawWriter.WriteObject(RawInner); + rawWriter.WriteString(RawAfter); + } + + /** <inheritdoc /> */ + virtual public void ReadBinary(IBinaryReader reader) + { + Before = reader.ReadString("before"); + Inner = reader.ReadObject<HandleInner>("inner"); + After = reader.ReadString("after"); + + IBinaryRawReader rawReader = reader.GetRawReader(); + + RawBefore = rawReader.ReadString(); + RawInner = rawReader.ReadObject<HandleInner>(); + RawAfter = rawReader.ReadString(); + } + } + + public class HandleInner : IBinarizable + { + public string Before; + public HandleOuter Outer; + public string After; + + public string RawBefore; + public HandleOuter RawOuter; + public string RawAfter; + + /** <inheritdoc /> */ + virtual public void WriteBinary(IBinaryWriter writer) + { + writer.WriteString("before", Before); + writer.WriteObject("outer", Outer); + writer.WriteString("after", After); + + IBinaryRawWriter rawWriter = writer.GetRawWriter(); + + rawWriter.WriteString(RawBefore); + rawWriter.WriteObject(RawOuter); + rawWriter.WriteString(RawAfter); + } + + /** <inheritdoc /> */ + virtual public void ReadBinary(IBinaryReader reader) + { + Before = reader.ReadString("before"); + Outer = reader.ReadObject<HandleOuter>("outer"); + After = reader.ReadString("after"); + + IBinaryRawReader rawReader = reader.GetRawReader(); + + RawBefore = rawReader.ReadString(); + RawOuter = rawReader.ReadObject<HandleOuter>(); + RawAfter = rawReader.ReadString(); + } + } + + + public class HandleOuterExclusive : HandleOuter + { + /** <inheritdoc /> */ + override public void WriteBinary(IBinaryWriter writer) + { + BinaryWriter writer0 = (BinaryWriter)writer; + + writer.WriteString("before", Before); + + writer0.WithDetach(w => w.WriteObject("inner", Inner)); + + writer.WriteString("after", After); + + IBinaryRawWriter rawWriter = writer.GetRawWriter(); + + rawWriter.WriteString(RawBefore); + + writer0.WithDetach(w => w.WriteObject(RawInner)); + + rawWriter.WriteString(RawAfter); + } + + /** <inheritdoc /> */ + override public void ReadBinary(IBinaryReader reader) + { + var reader0 = (BinaryReader) reader; + + Before = reader0.ReadString("before"); + + reader0.DetachNext(); + Inner = reader0.ReadObject<HandleInner>("inner"); + + After = reader0.ReadString("after"); + + var rawReader = (BinaryReader) reader.GetRawReader(); + + RawBefore = rawReader.ReadString(); + + reader0.DetachNext(); + RawInner = rawReader.ReadObject<HandleInner>(); + + RawAfter = rawReader.ReadString(); + } + } + + public class PropertyType + { + public int Field1; + + public int Field2 + { + get; + set; + } + } + + public enum TestEnum + { + Val1, Val2, Val3 = 10 + } + + public class DecimalReflective + { + /** */ + public decimal? Val; + + /** */ + public decimal?[] ValArr; + } + + public class DecimalMarshalAware : DecimalReflective, IBinarizable + { + /** */ + public decimal? RawVal; + + /** */ + public decimal?[] RawValArr; + + /** <inheritDoc /> */ + public void WriteBinary(IBinaryWriter writer) + { + writer.WriteDecimal("val", Val); + writer.WriteDecimalArray("valArr", ValArr); + + IBinaryRawWriter rawWriter = writer.GetRawWriter(); + + rawWriter.WriteDecimal(RawVal); + rawWriter.WriteDecimalArray(RawValArr); + } + + /** <inheritDoc /> */ + public void ReadBinary(IBinaryReader reader) + { + Val = reader.ReadDecimal("val"); + ValArr = reader.ReadDecimalArray("valArr"); + + IBinaryRawReader rawReader = reader.GetRawReader(); + + RawVal = rawReader.ReadDecimal(); + RawValArr = rawReader.ReadDecimalArray(); + } + } + + /// <summary> + /// Date time type. + /// </summary> + public class DateTimeType : IBinarizable + { + public DateTime Utc; + + public DateTime? UtcNull; + + public DateTime?[] UtcArr; + + public DateTime UtcRaw; + + public DateTime? UtcNullRaw; + + public DateTime?[] UtcArrRaw; + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="now">Current local time.</param> + public DateTimeType(DateTime now) + { + Utc = now.ToUniversalTime(); + + UtcNull = Utc; + + UtcArr = new DateTime?[] { Utc }; + + UtcRaw = Utc; + + UtcNullRaw = UtcNull; + + UtcArrRaw = new[] { UtcArr[0] }; + } + + /** <inheritDoc /> */ + public void WriteBinary(IBinaryWriter writer) + { + writer.WriteTimestamp("utc", Utc); + writer.WriteTimestamp("utcNull", UtcNull); + writer.WriteTimestampArray("utcArr", UtcArr); + + IBinaryRawWriter rawWriter = writer.GetRawWriter(); + + rawWriter.WriteTimestamp(UtcRaw); + rawWriter.WriteTimestamp(UtcNullRaw); + rawWriter.WriteTimestampArray(UtcArrRaw); + } + + /** <inheritDoc /> */ + public void ReadBinary(IBinaryReader reader) + { + Utc = reader.ReadTimestamp("utc").Value; + UtcNull = reader.ReadTimestamp("utc").Value; + UtcArr = reader.ReadTimestampArray("utcArr"); + + IBinaryRawReader rawReader = reader.GetRawReader(); + + UtcRaw = rawReader.ReadTimestamp().Value; + UtcNullRaw = rawReader.ReadTimestamp().Value; + UtcArrRaw = rawReader.ReadTimestampArray(); + } + } + + [Serializable] + private class SerializableObject + { + public int Foo { get; set; } + + private bool Equals(SerializableObject other) + { + return Foo == other.Foo; + } + + 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 Equals((SerializableObject) obj); + } + + public override int GetHashCode() + { + return Foo; + } + } + } +}
http://git-wip-us.apache.org/repos/asf/ignite/blob/d69362f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryStructureTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryStructureTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryStructureTest.cs new file mode 100644 index 0000000..78ee8c0 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryStructureTest.cs @@ -0,0 +1,250 @@ +/* + * 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.Binary +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Impl; + using Apache.Ignite.Core.Impl.Binary; + using NUnit.Framework; + + /// <summary> + /// Contains tests for binary type structure. + /// </summary> + [TestFixture] + public class BinaryStructureTest + { + /** Repeat count. */ + public static readonly int RepeatCnt = 10; + + /** Objects per mode. */ + public static readonly int ObjectsPerMode = 5; + + /// <summary> + /// Test object write with different structures. + /// </summary> + [Test] + public void TestStructure() + { + for (int i = 1; i <= RepeatCnt; i++) + { + Console.WriteLine(">>> Iteration started: " + i); + + // 1. Generate and shuffle objects. + IList<BranchedType> objs = new List<BranchedType>(); + + for (int j = 0; j < 6 * ObjectsPerMode; j++) + objs.Add(new BranchedType((j%6) + 1)); + + objs = IgniteUtils.Shuffle(objs); + + // 2. Create new marshaller. + BinaryTypeConfiguration typeCfg = new BinaryTypeConfiguration(typeof(BranchedType)); + + BinaryConfiguration cfg = new BinaryConfiguration + { + TypeConfigurations = new List<BinaryTypeConfiguration> { typeCfg } + }; + + Marshaller marsh = new Marshaller(cfg); + + // 3. Marshal all data and ensure deserialized object is fine. + foreach (BranchedType obj in objs) + { + Console.WriteLine(">>> Write object [mode=" + obj.mode + ']'); + + byte[] data = marsh.Marshal(obj); + + BranchedType other = marsh.Unmarshal<BranchedType>(data); + + Assert.IsTrue(obj.Equals(other)); + } + + Console.WriteLine(); + + // 4. Ensure that all fields are recorded. + var desc = marsh.GetDescriptor(typeof (BranchedType)); + + CollectionAssert.AreEquivalent(new[] {"mode", "f2", "f3", "f4", "f5", "f6", "f7", "f8"}, + desc.WriterTypeStructure.FieldTypes.Keys); + } + } + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public class BranchedType : IBinarizable + { + public int mode; + public int f2; + public int f3; + public int f4; + public int f5; + public int f6; + public int f7; + public int f8; + + public BranchedType(int mode) + { + this.mode = mode; + + switch (mode) + { + case 1: + f2 = 2; + + break; + + case 2: + f2 = 2; + f3 = 3; + f4 = 4; + + break; + + case 3: + f2 = 2; + f3 = 3; + f5 = 5; + + break; + + case 4: + f2 = 2; + f3 = 3; + f5 = 5; + f6 = 6; + + break; + + case 5: + f2 = 2; + f3 = 3; + f7 = 7; + + break; + + case 6: + f8 = 8; + + break; + } + } + + public void WriteBinary(IBinaryWriter writer) + { + writer.WriteInt("mode", mode); + + switch (mode) + { + case 1: + writer.WriteInt("f2", f2); + + break; + + case 2: + writer.WriteInt("f2", f2); + writer.WriteInt("f3", f3); + writer.WriteInt("f4", f4); + + break; + + case 3: + writer.WriteInt("f2", f2); + writer.WriteInt("f3", f3); + writer.WriteInt("f5", f5); + + break; + + case 4: + writer.WriteInt("f2", f2); + writer.WriteInt("f3", f3); + writer.WriteInt("f5", f5); + writer.WriteInt("f6", f6); + + break; + + case 5: + writer.WriteInt("f2", f2); + writer.WriteInt("f3", f3); + writer.WriteInt("f7", f7); + + break; + + case 6: + writer.WriteInt("f8", f8); + + break; + } + } + + public void ReadBinary(IBinaryReader reader) + { + mode = reader.ReadInt("mode"); + + switch (mode) + { + case 1: + f2 = reader.ReadInt("f2"); + + break; + + case 2: + f2 = reader.ReadInt("f2"); + f3 = reader.ReadInt("f3"); + f4 = reader.ReadInt("f4"); + + break; + + case 3: + f2 = reader.ReadInt("f2"); + f3 = reader.ReadInt("f3"); + f5 = reader.ReadInt("f5"); + + break; + + case 4: + f2 = reader.ReadInt("f2"); + f3 = reader.ReadInt("f3"); + f5 = reader.ReadInt("f5"); + f6 = reader.ReadInt("f6"); + + break; + + case 5: + f2 = reader.ReadInt("f2"); + f3 = reader.ReadInt("f3"); + f7 = reader.ReadInt("f7"); + + break; + + case 6: + f8 = reader.ReadInt("f8"); + + break; + } + } + + public bool Equals(BranchedType other) + { + return mode == other.mode && f2 == other.f2 && f3 == other.f3 && f4 == other.f4 && f5 == other.f5 && + f6 == other.f6 && f7 == other.f7 && f8 == other.f8; + } + } +}