text:
// ReSharper disable NonReadonlyMemberInGetHashCode
// ReSharper disable CompareOfFloatsByEqualityOperator
// ReSharper disable PossibleInvalidOperationException
// ReSharper disable UnusedAutoPropertyAccessor.Global
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Local
namespace Apache.Ignite.Core.Tests.Binary
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using Apache.Ignite.Core.Binary;
    using Apache.Ignite.Core.Common;
    using Apache.Ignite.Core.Impl.Binary;
    using Apache.Ignite.Core.Impl.Binary.IO;
    using Apache.Ignite.Core.Impl.Common;
    using NUnit.Framework;
    using BinaryReader = Apache.Ignite.Core.Impl.Binary.BinaryReader;
    using BinaryWriter = Apache.Ignite.Core.Impl.Binary.BinaryWriter;

    ///
    /// Binary tests.
    ///
    [TestFixture]
    public class BinarySelfTest {
        /** */
        private Marshaller _marsh;

        ///
        ///
        ///
        [TestFixtureSetUp]
        public void BeforeTest()
        {
            _marsh = new Marshaller(GetBinaryConfiguration());
        }

        ///
        /// Gets the binary configuration.
        ///
        /// <returns></returns>
        protected virtual BinaryConfiguration GetBinaryConfiguration()
        {
            return new BinaryConfiguration { CompactFooter = true };
        }

        /**
         * Check write of primitive boolean.
         */
        [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);
        }

        /**
         * Check write of primitive boolean array.
         */
        [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);
        }

        /**
         * Check write of primitive sbyte.
         */
        [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);
        }

        /**
         * Check write of primitive sbyte array.
         */
        [Test]
        public void TestWritePrimitiveSbyteArray()
        {
            sbyte[] vals = { sbyte.MinValue, 0, 1, sbyte.MaxValue };
            sbyte[] newVals = _marsh.Unmarshal<sbyte[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of primitive byte.
         */
        [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);
        }

        /**
         * Check write of primitive byte array.
         */
        [Test]
        public void TestWritePrimitiveByteArray()
        {
            byte[] vals = { byte.MinValue, 0, 1, byte.MaxValue };
            byte[] newVals = _marsh.Unmarshal<byte[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of primitive short.
         */
        [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);
        }

        /**
         * Check write of primitive short array.
         */
        [Test]
        public void TestWritePrimitiveShortArray()
        {
            short[] vals = { short.MinValue, 0, 1, short.MaxValue };
            short[] newVals = _marsh.Unmarshal<short[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of primitive ushort.
         */
        [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);
        }

        /**
         * Check write of primitive short array.
         */
        [Test]
        public void TestWritePrimitiveUshortArray()
        {
            ushort[] vals = { ushort.MinValue, 0, 1, ushort.MaxValue };
            ushort[] newVals = _marsh.Unmarshal<ushort[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of primitive char.
         */
        [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);
        }

        /**
         * Check write of primitive uint array.
         */
        [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);
        }

        /**
         * Check write of primitive int.
         */
        [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);
        }

        /**
         * Check write of primitive uint array.
         */
        [Test]
        public void TestWritePrimitiveIntArray()
        {
            int[] vals = { int.MinValue, 0, 1, int.MaxValue };
            int[] newVals = _marsh.Unmarshal<int[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of primitive uint.
         */
        [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);
        }

        /**
         * Check write of primitive uint array.
         */
        [Test]
        public void TestWritePrimitiveUintArray()
        {
            uint[] vals = { uint.MinValue, 0, 1, uint.MaxValue };
            uint[] newVals = _marsh.Unmarshal<uint[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of primitive long.
         */
        [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);
        }

        /**
         * Check write of primitive long array.
         */
        [Test]
        public void TestWritePrimitiveLongArray()
        {
            long[] vals = { long.MinValue, 0, 1, long.MaxValue };
            long[] newVals = _marsh.Unmarshal<long[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of primitive ulong.
         */
        [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);
        }

        /**
         * Check write of primitive ulong array.
         */
        [Test]
        public void TestWritePrimitiveUlongArray()
        {
            ulong[] vals = { ulong.MinValue, 0, 1, ulong.MaxValue };
            ulong[] newVals = _marsh.Unmarshal<ulong[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of primitive float.
         */
        [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);
        }

        /**
         * Check write of primitive float array.
         */
        [Test]
        public void TestWritePrimitiveFloatArray()
        {
            float[] vals = { float.MinValue, 0, 1, float.MaxValue };
            float[] newVals = _marsh.Unmarshal<float[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of primitive double.
         */
        [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);
        }

        /**
         * Check write of primitive double array.
         */
        [Test]
        public void TestWritePrimitiveDoubleArray()
        {
            double[] vals = { double.MinValue, 0, 1, double.MaxValue };
            double[] newVals = _marsh.Unmarshal<double[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of decimal.
         */
        [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);
        }

        /**
         * Check write of decimal array.
         */
        [Test]
        public void TestWritePrimitiveDecimalArray()
        {
            decimal?[] vals = { decimal.One, decimal.Parse("11,12") };
            var newVals = _marsh.Unmarshal<decimal?[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of string.
         */
        [Test]
        public void TestWriteString()
        {
            Assert.AreEqual(_marsh.Unmarshal<string>(_marsh.Marshal("str")), "str");
            Assert.AreEqual(_marsh.Unmarshal<string>(_marsh.Marshal((string) null)), null);
        }

        /**
         * Check write of string array.
         */
        [Test]
        public void TestWriteStringArray()
        {
            string[] vals = { "str1", null, "", "str2", null};
            string[] newVals = _marsh.Unmarshal<string[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        /**
         * Check write of Guid.
         */
        [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);
        }

        /**
         * Check write of string array.
         */
        [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);
        }

        ///
        /// Checks that both methods produce identical results.
        ///
        [Test]
        public void TestGuidSlowFast()
        {
            var stream = new BinaryHeapStream(128);

            var guid = Guid.NewGuid();

            BinaryUtils.WriteGuidFast(guid, stream);

            stream.Seek(0, SeekOrigin.Begin);
            Assert.AreEqual(guid, BinaryUtils.ReadGuidFast(stream));

            stream.Seek(0, SeekOrigin.Begin);
            Assert.AreEqual(guid, BinaryUtils.ReadGuidSlow(stream));

            stream.Seek(0, SeekOrigin.Begin);
            BinaryUtils.WriteGuidFast(guid, stream);

            stream.Seek(0, SeekOrigin.Begin);
            Assert.AreEqual(guid, BinaryUtils.ReadGuidFast(stream));

            stream.Seek(0, SeekOrigin.Begin);
            Assert.AreEqual(guid, BinaryUtils.ReadGuidSlow(stream));
        }

        /**
        * Check write of enum.
        */
        [Test]
        [SuppressMessage("ReSharper", "ExpressionIsAlwaysNull")]
        public void TestWriteEnum()
        {
            TestEnum val = TestEnum.Val1;

            Assert.AreEqual(_marsh.Unmarshal<TestEnum>(_marsh.Marshal(val)), val);

            TestEnum? val2 = TestEnum.Val1;
            Assert.AreEqual(_marsh.Unmarshal<TestEnum?>(_marsh.Marshal(val2)), val2);

            val2 = null;
            Assert.AreEqual(_marsh.Unmarshal<TestEnum?>(_marsh.Marshal(val2)), val2);
        }

        ///
        /// Tests the write of registered enum.
        ///
        [Test]
        public void TestWriteEnumRegistered()
        {
            var marsh =
                new Marshaller(new BinaryConfiguration
                {
                    TypeConfigurations = new[] { new BinaryTypeConfiguration(typeof(TestEnum)) }
                });

            TestEnum val = TestEnum.Val1;

            var data = marsh.Marshal(val);

            Assert.AreEqual(marsh.Unmarshal<TestEnum>(data), val);

            var binEnum = marsh.Unmarshal<IBinaryObject>(data, true);

            Assert.AreEqual(val, (TestEnum) binEnum.EnumValue);
        }

        /**
        * Check write of enum.
        */
        [Test]
        public void TestWriteEnumArray()
        {
            TestEnum[] vals = { TestEnum.Val2, TestEnum.Val3 };
            TestEnum[] newVals = _marsh.Unmarshal<TestEnum[]>(_marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        ///
        /// Tests the write of registered enum array.
        ///
        [Test]
        public void TestWriteEnumArrayRegistered()
        {
            var marsh =
                new Marshaller(new BinaryConfiguration
                {
                    TypeConfigurations = new[] { new BinaryTypeConfiguration(typeof(TestEnum)) }
                });

            TestEnum[] vals = { TestEnum.Val2, TestEnum.Val3 };
            TestEnum[] newVals = marsh.Unmarshal<TestEnum[]>(marsh.Marshal(vals));

            Assert.AreEqual(vals, newVals);
        }

        ///
        /// Test object with dates.
        ///
        [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);
        }

        ///
        /// Tests the DateTime marshalling.
        ///
        [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));
        }

        /**
         * Check generic collections.
         */
        [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);
        }

        ///
        /// Tests marshal aware type with generic collections.
        ///
        [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);
        }

        /**
         * Check property read.
         */
        [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.IsTrue(portNewObj.HasField("field1"));
            Assert.IsTrue(portNewObj.HasField("field2"));
            Assert.IsFalse(portNewObj.HasField("field3"));

            Assert.AreEqual(obj.Field1, portNewObj.GetField<int>("field1"));
            Assert.AreEqual(obj.Field2, portNewObj.GetField<int>("Field2"));
            Assert.AreEqual(0, portNewObj.GetField<int>("field3"));
        }

        /**
         * Check write of primitive fields through reflection.
         */
        [Test]
        public void TestPrimitiveFieldsReflective([Values(false, true)] bool raw)
        {
            var serializer = new BinaryReflectiveSerializer {RawMode = raw};

            Assert.AreEqual(raw, serializer.RawMode);

            var marsh = new Marshaller(new BinaryConfiguration
            {
                TypeConfigurations = new[]
                {
                    new BinaryTypeConfiguration(typeof (PrimitiveFieldType))
                    {
                        Serializer = serializer
                    }
                }
            });

            PrimitiveFieldType obj = new PrimitiveFieldType();

            CheckPrimitiveFields(marsh, obj);
        }

        /**
         * Check write of primitive fields through binary interface.
         */
        [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);
        }

        /**
         * Check write of primitive fields through binary interface.
         */
        [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);
        }

        /**
         * Check write of primitive fields through binary interface.
         */
        [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);
        }

        /**
         * Check decimals.
         */
        [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);
        }

        /**
         * Check write of primitive fields through raw serializer.
         */
        [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);
        }

        /**
         * Check write of object with enums.
         */
        [Test]
        public void TestEnumsReflective([Values(false, true)] bool raw)
        {
            Marshaller marsh =
                new Marshaller(new BinaryConfiguration
                {
                    TypeConfigurations = new[]
                    {
                        new BinaryTypeConfiguration(typeof (EnumType))
                        {
                            Serializer = new BinaryReflectiveSerializer {RawMode = raw}
                        },
                        new BinaryTypeConfiguration(typeof (TestEnum))
                        {
                            Serializer = new BinaryReflectiveSerializer {RawMode = raw}
                        }
                    }
                });

            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());

            if (!raw)
            {
                // Test enum field in binary form
                var binEnum = portObj.GetField<IBinaryObject>("PEnum");
                Assert.AreEqual(obj.PEnum.GetHashCode(), binEnum.GetHashCode());
                Assert.AreEqual((int) obj.PEnum, binEnum.EnumValue);
                Assert.AreEqual(obj.PEnum, binEnum.Deserialize<TestEnum>());
                Assert.AreEqual(obj.PEnum, binEnum.Deserialize<object>());
                Assert.AreEqual(typeof (TestEnum), binEnum.Deserialize<object>().GetType());
                Assert.AreEqual(null, binEnum.GetField<object>("someField"));
                Assert.IsFalse(binEnum.HasField("anyField"));

                var binEnumArr = portObj.GetField<IBinaryObject[]>("PEnumArray");
                Assert.IsTrue(binEnumArr.Select(x => x.Deserialize<TestEnum>()).SequenceEqual(obj.PEnumArray));
            }
            else
            {
                Assert.IsFalse(portObj.HasField("PEnum"));
                Assert.IsFalse(portObj.HasField("PEnumArray"));
            }

            EnumType newObj = portObj.Deserialize<EnumType>();

            Assert.AreEqual(obj.PEnum, newObj.PEnum);
            Assert.AreEqual(obj.PEnumArray, newObj.PEnumArray);
        }

        /**
         * Check write of object with collections.
         */
        [Test]
        public void TestCollectionsReflective([Values(false, true)] bool raw)
        {
            var marsh = new Marshaller(new BinaryConfiguration
            {
                TypeConfigurations = new[]
                {
                    new BinaryTypeConfiguration(typeof (CollectionsType))
                    {
                        Serializer = new BinaryReflectiveSerializer {RawMode = raw}
                    },
                    new BinaryTypeConfiguration(typeof (InnerObjectType))
                    {
                        Serializer = new BinaryReflectiveSerializer {RawMode = raw}
                    }
                }
            });

            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)));
        }

        /**
         * Check write of object fields through reflective serializer.
         */
        [Test]
        public void TestObjectReflective([Values(false, true)] bool raw)
        {
            var marsh = new Marshaller(new BinaryConfiguration
            {
                TypeConfigurations = new[]
                {
                    new BinaryTypeConfiguration(typeof (OuterObjectType))
                    {
                        Serializer = new BinaryReflectiveSerializer {RawMode = raw}
                    },
                    new BinaryTypeConfiguration(typeof (InnerObjectType))
                    {
                        Serializer = new BinaryReflectiveSerializer {RawMode = raw}
                    }
                }
            });

            CheckObject(marsh, new OuterObjectType(), new InnerObjectType());
        }

        [Test]
        public void TestStructsReflective([Values(false, true)] bool raw)
        {
            var marsh = new Marshaller(new BinaryConfiguration
            {
                TypeConfigurations =
                    new[]
                    {
                        new BinaryTypeConfiguration(typeof (ReflectiveStruct))
                        {
                            Serializer = new BinaryReflectiveSerializer {RawMode = raw}
                        }
                    }
            });

            var obj = new ReflectiveStruct(15, 28.8);
            var res = marsh.Unmarshal<ReflectiveStruct>(marsh.Marshal(obj));

            Assert.AreEqual(res, obj);
        }

        /**
         * Test handles.
         */
        [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);
        }

        /**
         * Test handles with exclusive writes.
         */
        [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 Binary(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);
        }

        [Test]
        public void TestHandlesCollections()
        {
            var marsh = new Marshaller(new BinaryConfiguration
            {
                TypeConfigurations = new[]
                {
                    new BinaryTypeConfiguration(typeof (HandleCollection))
                }
            });

            // Collection in collection dependency loop
            var collection = new ArrayList {1, 2};
            collection.Add(collection);

            var collectionRaw = new ArrayList(collection);
            collectionRaw.Add(collectionRaw);

            var collectionObj = new ArrayList(collectionRaw);
            collectionObj.Add(collectionObj);

            var dict = new Hashtable { { 1, 1 }, { 2, 2 } };
            dict.Add(3, dict);

            var arr = collectionObj.ToArray();
            arr[1] = arr;

            object entry = new DictionaryEntry(1, 2);
            var dictionaryEntryValSetter = DelegateConverter.CompileFieldSetter(typeof (DictionaryEntry)
                .GetField("_value", BindingFlags.Instance | BindingFlags.NonPublic));
            dictionaryEntryValSetter(entry, entry);  // modify boxed copy to create reference loop

            var data = new HandleCollection
            {
                Collection = collection,
                CollectionRaw = collectionRaw,
                Object = collectionObj,
                Dictionary = dict,
                Array = arr,
                DictionaryEntry = (DictionaryEntry) entry
            };

            var res = marsh.Unmarshal<HandleCollection>(marsh.Marshal(data));

            var resCollection = (ArrayList) res.Collection;
            Assert.AreEqual(collection[0], resCollection[0]);
            Assert.AreEqual(collection[1], resCollection[1]);
            Assert.AreSame(resCollection, resCollection[2]);

            var resCollectionRaw = (ArrayList) res.CollectionRaw;
            Assert.AreEqual(collectionRaw[0], resCollectionRaw[0]);
            Assert.AreEqual(collectionRaw[1], resCollectionRaw[1]);
            Assert.AreSame(resCollection, resCollectionRaw[2]);
            Assert.AreSame(resCollectionRaw, resCollectionRaw[3]);

            var resCollectionObj = (ArrayList) res.Object;
            Assert.AreEqual(collectionObj[0], resCollectionObj[0]);
            Assert.AreEqual(collectionObj[1], resCollectionObj[1]);
            Assert.AreSame(resCollection, resCollectionObj[2]);
            Assert.AreSame(resCollectionRaw, resCollectionObj[3]);
            Assert.AreSame(resCollectionObj, resCollectionObj[4]);

            var resDict = (Hashtable) res.Dictionary;
            Assert.AreEqual(1, resDict[1]);
            Assert.AreEqual(2, resDict[2]);
            Assert.AreSame(resDict, resDict[3]);

            var resArr = res.Array;
            Assert.AreEqual(arr[0], resArr[0]);
            Assert.AreSame(resArr, resArr[1]);
            Assert.AreSame(resCollection, resArr[2]);
            Assert.AreSame(resCollectionRaw, resArr[3]);
            Assert.AreSame(resCollectionObj, resArr[4]);

            var resEntry = res.DictionaryEntry;
            var innerEntry = (DictionaryEntry) resEntry.Value;
            Assert.AreEqual(1, resEntry.Key);
            Assert.AreEqual(1, innerEntry.Key);
            Assert.IsTrue(ReferenceEquals(innerEntry.Value, ((DictionaryEntry) innerEntry.Value).Value));
        }

        ///
        /// Test KeepSerialized property
        ///
        [Test]
        public void TestKeepSerializedDefault()
        {
            CheckKeepSerialized(new BinaryConfiguration(), true);
        }

        ///
        /// Test KeepSerialized property
        ///
        [Test]
        public void TestKeepSerializedDefaultFalse()
        {
            BinaryConfiguration cfg = new BinaryConfiguration();

            cfg.DefaultKeepDeserialized = false;

            CheckKeepSerialized(cfg, false);
        }

        ///
        /// Test KeepSerialized property
        ///
        [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);
        }

        ///
        /// Test KeepSerialized property
        ///
        [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);
        }

        ///
        /// Test correct serialization/deserialization of arrays of special types.
        ///
        [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);
        }

        ///
        /// Writes objects of various sizes to test schema compaction
        /// (where field offsets can be stored as 1, 2 or 4 bytes).
        ///
        [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);
            }
        }

        [Test]
        public void TestBinaryConfigurationValidation()
        {
            var cfg = new BinaryConfiguration(typeof (PropertyType)) {Types = new[] {"PropertyType"}};

            // ReSharper disable once ObjectCreationAsStatement
            Assert.Throws<BinaryObjectException>(() => new Marshaller(cfg));
        }

        ///
        /// Tests the compact footer setting.
        ///
        [Test]
        public void TestCompactFooterSetting()
        {
            Assert.AreEqual(GetBinaryConfiguration().CompactFooter, _marsh.CompactFooter);
        }

        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 HandleCollection : IBinarizable
        {
            public ICollection Collection { get; set; }
            public IDictionary Dictionary { get; set; }
            public DictionaryEntry DictionaryEntry { get; set; }
            public ICollection CollectionRaw { get; set; }
            public object Object { get; set; }
            public object[] Array { get; set; }

            public void WriteBinary(IBinaryWriter writer)
            {
                writer.WriteCollection("col", Collection);
                writer.WriteDictionary("dict", Dictionary);
                writer.WriteObject("dictEntry", DictionaryEntry);
                writer.WriteObject("obj", Object);
                writer.WriteArray("arr", Array);
                writer.GetRawWriter().WriteCollection(CollectionRaw);
            }

            public void ReadBinary(IBinaryReader reader)
            {
                Collection = reader.ReadCollection("col");
                Dictionary = reader.ReadDictionary("dict");
                DictionaryEntry = reader.ReadObject<DictionaryEntry>("dictEntry");
                Object = reader.ReadObject<object>("obj");
                Array = reader.ReadArray<object>("arr");
                CollectionRaw = reader.GetRawReader().ReadCollection();
            }
        }

        public class PropertyType
        {
            public int Field1;

            public int Field2
            {
                get;
                set;
            }
        }

        public enum TestEnum
        {
            Val1, Val2, Val3 = 10
        }

        public enum TestEnum2
        {
            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();
            }
        }

        ///
        /// Date time type.
        ///
        public class DateTimeType : IBinarizable
        {
            public DateTime Utc;

            public DateTime? UtcNull;

            public DateTime?[] UtcArr;

            public DateTime UtcRaw;

            public DateTime? UtcNullRaw;

            public DateTime?[] UtcArrRaw;

            ///
            /// Constructor.
            ///
            /// <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;
            }
        }

        private struct ReflectiveStruct : IEquatable<ReflectiveStruct>
        {
            private readonly int _x;
            private readonly double _y;

            public ReflectiveStruct(int x, double y)
            {
                _x = x;
                _y = y;
            }

            public int X
            {
                get { return _x; }
            }

            public double Y
            {
                get { return _y; }
            }

            public bool Equals(ReflectiveStruct other)
            {
                return _x == other._x && _y.Equals(other._y);
            }

            public override bool Equals(object obj)
            {
                if (ReferenceEquals(null, obj))
                    return false;

                return obj is ReflectiveStruct && Equals((ReflectiveStruct) obj);
            }

            public override int GetHashCode()
            {
                unchecked
                {
                    return (_x*397) ^ _y.GetHashCode();
                }
            }

            public static bool operator ==(ReflectiveStruct left, ReflectiveStruct right)
            {
                return left.Equals(right);
            }

            public static bool operator !=(ReflectiveStruct left, ReflectiveStruct right)
            {
                return !left.Equals(right);
            }
        }
    }
}


text:
package uk.ac.ed.ph.snuggletex.samples;

import uk.ac.ed.ph.snuggletex.SnuggleInput;
import uk.ac.ed.ph.snuggletex.SnuggleEngine;
import uk.ac.ed.ph.snuggletex.SnuggleSession;

import java.io.IOException;

/**
 * Example demonstrating a minimal example use of SnuggleTeX.
 * <p>
 * This simply converts a fixed input String of LaTeX to XML.
 * (In this case, the result is a fragment of MathML.)
 *
 * @see XMLStringOutputExample
 * @see WebPageExample
 *
 * @author  David McKain
 * @version $Revision$
 */
public final class MinimalExample {

    public static void main(String[] args) throws IOException {
        /* Create vanilla SnuggleEngine and new SnuggleSession */
        SnuggleEngine engine = new SnuggleEngine();
        SnuggleSession session = engine.createSession();

        /* Parse some very basic Math Mode input */
        SnuggleInput input = new SnuggleInput("$$ x+2=3 $$");
        session.parseInput(input);

        /* Convert the results to an XML String, which in this case will
         * be a single MathML <math>...</math> element. */
        String xmlString = session.buildXMLString();
        System.out.println("Input " + input.getString()
                + " was converted to:\n" + xmlString);
    }
}

redpajama_set_name: RedPajamaGithub


text:
package java.lang;

public class String {

}


text:
URL shortening mongo/node service

A very simple and high performance web service used for link shortening.
Works out of the box on heroku.com platform, just deploy it as a heroku app with active mongodb addon using heroku's github integration.

Default behaviour is to delete every link if it's not used for 1 hour or longer.
Also, protocol prefix (http://) is ommited from the shortened url.
These two settings can be modified using EXPIRE_SECONDS and PREFIX env variables.

Also, MONGODB_URI env variable is used to determine the mongo database uri.
Shortener's listening port is determened by the env variable PORT.
Env variable CODE_SIZE is used for setting the length of the code for shortened link. Default is 5.

## API
There are only two endpoints:
1) GET HOSTNAME/generate/URL which returns a shortened url (as a string) in a form of HOSTNAME/XXXXX
2) GET HOSTNAME/XXXXX which redirects to the original URL

If nonexisting (or deleted due to expiration) url is requested, a HTTP 404 with message "NOT FOUND" is returned.


text:
FROM nginx:1.9

COPY nginx.conf /etc/nginx/nginx.conf

ARG BUILD_DATE=""
ARG VCS_REF=""
ARG IMAGE_VERSION=""

EXPOSE 27017

LABEL maintainer="acdifran@gmail.com" \
      org.label-schema.build-date=$BUILD_DATE \
      org.label-schema.name="MongoDB-Nginx" \
      org.label-schema.vcs-ref=$VCS_REF \
      org.label-schema.version=$IMAGE_VERSION \
      org.label-schema.vcs-url="https://github.com/deepcortex/dockers" \
      org.label-schema.vendor="DeepCortex" \
      org.label-schema.schema-version="1.0" \
      org.label-schema.docker.cmd="docker run --rm -it deepcortex/mongodb-nginx R"


text:
@interface PhotoBrowserVC : UIViewController

//图片轮播图
@property (nonatomic,strong) UIScrollView * photoScrollView;

//主标题
@property (nonatomic,strong) UILabel * mainLabel;

//副标题
@property (nonatomic,strong) UILabel * subLabel;

//浏览位置
@property (nonatomic,strong) UILabel *locationLabel;

//图片信息数组 ----主要利用副标题
@property (nonatomic,strong) NSMutableArray * photoInfoArr;

//保存图片imgview的数组,添加到scrollView
@property (nonatomic,strong) NSMutableArray * imgArr;

//主标题字符串
@property (nonatomic,strong) NSString * strMain;

//图片索引
@property (nonatomic,assign) NSInteger pageIndex;

@end


text:
// Copyright (c) Christof Senn. All rights reserved. See license.txt in the project root for license information.

namespace Server
{
    using Aqua.Dynamic;
    using Remote.Linq.ExpressionExecution;
    using Remote.Linq.Expressions;
    using System.Threading;
    using System.Threading.Tasks;

    public class QueryService
    {
        public ValueTask<DynamicObject> ExecuteQueryAsync(Expression queryExpression, CancellationToken cancellation)
        {
            using NHContext nhContext = new NHContext();
            return new ValueTask<DynamicObject>(queryExpression.Execute(nhContext.GetQueryable));
        }
    }
}


text:
<?php

namespace Kunstmaan\NodeBundle\EventListener;

use Doctrine\ORM\Event\LoadClassMetadataEventArgs;

/**
 * Class MappingListener
 */
class MappingListener
{
    /**
     * @var string
     */
    private $className;

    /**
     * Constructor
     *
     * @param string $className
     */
    public function __construct($className)
    {
        $this->className = $className;
    }

    /**
     * Called when class meta data is fetched.
     * @param LoadClassMetadataEventArgs $eventArgs
     */
    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
    {
        $classMetadata = $eventArgs->getClassMetadata();
        $entityName = strval($classMetadata->getName());

        // We dynamically set the user class that was configured in the configuration
        if ($entityName == 'Kunstmaan\NodeBundle\Entity\QueuedNodeTranslationAction') {
            $mapping = array(
                'fieldName' => 'user',
                'targetEntity' => $this->className,
                'joinColumns' => array(array(
                    'name' => 'user_id',
                    'referencedColumnName' => 'id',
                    'unique' => false,
                    'nullable' => true
                )),
            );
            $classMetadata->mapManyToOne($mapping);
        }
    }
}


text:
module ManageusersHelper
end


text:
require 'ting_yun/agent'
require 'ting_yun/support/local_environment'
require 'ting_yun/frameworks'

module TingYun
  module Frameworks
    module ClassMethods
      def instance
        framework = TingYun::Agent.config[:framework]
        if framework == :test
          @instance ||= load_test_framework
        else
          @instance ||= load_framework_class(framework).new(local_env)
        end

      end

      def load_test_framework
        config = File.expand_path(File.join('..','..', 'test','config','tingyun.yml'), __FILE__)
        require 'config/test'
        TingYun::Frameworks::Test.new(local_env, config)
      end

      def load_framework_class(framework)
        begin
          require 'ting_yun/frameworks/' + framework.to_s
        rescue LoadError
          #to avoid error
        end
        TingYun::Frameworks.const_get(framework.to_s.capitalize)
      end

      def local_env
        @local_env ||= TingYun::Support::LocalEnvironment.new
      end

      # clear out memoized Framework and LocalEnv instances
      def reset
        @instance = nil
        @local_env = nil
      end
    end
  end
end


text:
import java.io.*;
import java.util.*;

public class BigTruck {

	public static void main(String[] args) throws IOException {
		IO io = new IO(System.in);

    int numLocations = io.nextInt();
    V[] nodes = new V[numLocations];
    for (int i = 0; i < numLocations; i++) {
      nodes[i] = new V(i, io.nextInt());
    }

    int numRoads = io.nextInt();
    int from, to, weight;
    for (int i = 0; i < numRoads; i++) {
      from = io.nextInt() - 1;
      to = io.nextInt() - 1;
      weight = io.nextInt();
      nodes[from].adj.add(new E(nodes[to], weight));
      nodes[to].adj.add(new E(nodes[from], weight));
    }

    compute(nodes[numLocations-1]);

    if (nodes[0].dist == Double.POSITIVE_INFINITY) {
      io.println("impossible");
    } else {
      io.printf("%.0f %d\n", nodes[0].dist, nodes[0].val);
    }

		io.close();
	}

  static class V implements Comparable<V> {
    public final int name;
    public List<E> adj;
    public int w;
    public double dist = Double.POSITIVE_INFINITY;
    public int val = 0;
    public V prev;

    public V(int _n, int _w) {
      name = _n;
      adj = new ArrayList<E>();
      w = _w;
    }

    public int compareTo(V o) {
      return Double.compare(dist, o.dist);
    }
  }

  static class E {
    public final V end;
    public final double w;

    public E(V _e, double _w) {
      end = _e;
      w = _w;
    }
  }

  static void compute(V source) {
    source.dist = 0.;
    source.val = source.w;

    PriorityQueue<V> q = new PriorityQueue<>();
    q.add(source);

    while (!q.isEmpty()) {
      V v = q.poll();
      for (E e : v.adj) {
        V u = e.end;
        double uDist = v.dist + e.w;
        int uVal = v.val + u.w;
        if (uDist < u.dist || (uDist == u.dist && uVal > u.val)) {
          q.remove(u);
          u.dist = uDist;
          u.val = uVal;
          u.prev = v;
          q.add(u);
        }
      }
    }
  }

	static class IO extends PrintWriter {
		static BufferedReader r;
		static StringTokenizer t;

		public IO(InputStream i) {
			super(new BufferedOutputStream(System.out));
			r = new BufferedReader(new InputStreamReader(i));
			t = new StringTokenizer("");
		}

      public String nextLine() throws IOException {
        return r.readLine();
      }

		public String next() throws IOException {
			while (!t.hasMoreTokens()) {
				t = new StringTokenizer(nextLine());
			}
			return t.nextToken();
		}

		public int nextInt() throws IOException{
			return Integer.parseInt(next());
		}

		public long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}
	}
}