using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; using Xunit; using ZeroLevel.DocumentObjectModel; using ZeroLevel.Network; using ZeroLevel.Services.Serialization; using ZeroLevel.UnitTests.Models; namespace ZeroLevel.Serialization { public class SerializationTests { private static bool TestOrderingEquals(IEnumerable A, IEnumerable B, Func comparer) { if (A == null && B == null) return true; if (A == null || B == null) return false; if (A.Count() != B.Count()) return false; var enumA = A.GetEnumerator(); var enumB = B.GetEnumerator(); while (enumA.MoveNext() && enumB.MoveNext()) { if (enumA.Current == null && enumB.Current == null) continue; if (comparer(enumA.Current, enumB.Current) == false) return false; } return true; } private void MakePrimitiveTest(T value, Func comparator = null) { // Act var data = MessageSerializer.SerializeCompatible(value); var clone = MessageSerializer.DeserializeCompatible(data); // Assert if (comparator == null) { Assert.Equal(value, clone); } else { Assert.True(comparator(value, clone)); } } private void MakeCollectionTest(IEnumerable value, Func comparator = null) { // Act var data = MessageSerializer.SerializeCompatible>(value); var clone = MessageSerializer.DeserializeCompatible>(data); // Assert if (value == null && clone != null && !clone.Any()) return; // OK if (comparator == null) { Assert.True(CollectionComparsionExtensions.OrderingEquals(value, clone)); } else { Assert.True(TestOrderingEquals(value, clone, comparator)); } } private void MakeDictionaryTest(Dictionary value , Func keyComparator = null , Func valueComparator = null) { byte[] data; Dictionary clone; // Act using (var writer = new MemoryStreamWriter()) { writer.WriteDictionary(value); data = writer.Complete(); } using (var reader = new MemoryStreamReader(data)) { clone = reader.ReadDictionary(); } // Assert if (value == null && clone != null && !clone.Any()) return; // OK if (value != null && clone == null) throw new Exception("Fail"); var original_keys = value.Keys.ToArray(); var clone_keys = clone.Keys.ToArray(); if (keyComparator == null) { Assert.True(CollectionComparsionExtensions.NoOrderingEquals(original_keys, clone_keys)); } else { Assert.True(CollectionComparsionExtensions.NoOrderingEquals(original_keys, clone_keys, keyComparator)); } foreach (var key in original_keys) { if (valueComparator == null) { Assert.Equal(value[key], clone[key]); } else { Assert.True(valueComparator(value[key], clone[key])); } } } [Fact] public void SerializeDateTime() { MakePrimitiveTest(DateTime.Now); MakePrimitiveTest(DateTime.UtcNow); MakePrimitiveTest(DateTime.Today); MakePrimitiveTest(DateTime.Now.AddYears(2000)); MakePrimitiveTest(DateTime.MinValue); MakePrimitiveTest(DateTime.MaxValue); } [Fact] public void SerializeIPAddress() { var comparator = new Func((left, right) => NetUtils.Compare(left, right) == 0); MakePrimitiveTest(null, comparator); MakePrimitiveTest(IPAddress.Any, comparator); MakePrimitiveTest(IPAddress.Broadcast, comparator); MakePrimitiveTest(IPAddress.IPv6Any, comparator); MakePrimitiveTest(IPAddress.IPv6Loopback, comparator); MakePrimitiveTest(IPAddress.IPv6None, comparator); MakePrimitiveTest(IPAddress.Loopback, comparator); MakePrimitiveTest(IPAddress.None, comparator); MakePrimitiveTest(IPAddress.Parse("93.111.16.58"), comparator); } [Fact] public void SerializeIPEndPoint() { var comparator = new Func((left, right) => NetUtils.Compare(left, right) == 0); MakePrimitiveTest(null, comparator); MakePrimitiveTest(new IPEndPoint(IPAddress.Any, 1), comparator); MakePrimitiveTest(new IPEndPoint(IPAddress.Broadcast, 600), comparator); MakePrimitiveTest(new IPEndPoint(IPAddress.IPv6Any, IPEndPoint.MaxPort), comparator); MakePrimitiveTest(new IPEndPoint(IPAddress.IPv6Loopback, 8080), comparator); MakePrimitiveTest(new IPEndPoint(IPAddress.IPv6None, 80), comparator); MakePrimitiveTest(new IPEndPoint(IPAddress.Loopback, 9000), comparator); MakePrimitiveTest(new IPEndPoint(IPAddress.None, 0), comparator); MakePrimitiveTest(new IPEndPoint(IPAddress.Parse("93.111.16.58"), IPEndPoint.MinPort), comparator); } [Fact] public void SerializeGuid() { MakePrimitiveTest(Guid.Empty); MakePrimitiveTest(Guid.NewGuid()); } [Fact] public void SerializeTimeSpan() { MakePrimitiveTest(TimeSpan.MaxValue); MakePrimitiveTest(TimeSpan.MinValue); MakePrimitiveTest(TimeSpan.Zero); MakePrimitiveTest(TimeSpan.FromDays(1024)); MakePrimitiveTest(TimeSpan.FromMilliseconds(1)); MakePrimitiveTest(TimeSpan.FromTicks(1)); MakePrimitiveTest(TimeSpan.FromTicks(0)); } [Fact] public void SerializeString() { var comparator = new Func((left, right) => (left == null && right == null) || (left == null && right != null && right.Length == 0) || (left != null && left.Length == 0 && right == null) || string.Compare(left, right, StringComparison.InvariantCulture) == 0); MakePrimitiveTest("", comparator); MakePrimitiveTest(String.Empty, comparator); MakePrimitiveTest(null, comparator); MakePrimitiveTest("HELLO!", comparator); MakePrimitiveTest("𐌼𐌰𐌲 𐌲𐌻𐌴𐍃 𐌹̈𐍄𐌰𐌽, 𐌽𐌹 𐌼𐌹𐍃 𐍅𐌿 𐌽𐌳𐌰𐌽 𐌱𐍂𐌹𐌲𐌲𐌹𐌸", comparator); } [Fact] public void SerizlizeCharText() { // Arrange var line = "abcxyzABCZА-Яа-яёЁйЙ123"; // Act var bytes = line.Select(ch => MessageSerializer.SerializeCompatible(ch)); // Assert var testLine = new string(bytes.Select(ba => MessageSerializer.DeserializeCompatible(ba)).ToArray()); Assert.Equal(line, testLine); } [Fact] public void SerializeInt32() { MakePrimitiveTest(-0); MakePrimitiveTest(0); MakePrimitiveTest(-10); MakePrimitiveTest(10); MakePrimitiveTest(Int32.MinValue); MakePrimitiveTest(Int32.MaxValue); } [Fact] public void SerializeUInt32() { MakePrimitiveTest(-0); MakePrimitiveTest(0); MakePrimitiveTest(10); MakePrimitiveTest(UInt32.MinValue); MakePrimitiveTest(UInt32.MaxValue); } [Fact] public void SerializeShort() { MakePrimitiveTest(-0); MakePrimitiveTest(0); MakePrimitiveTest(-10); MakePrimitiveTest(10); MakePrimitiveTest(short.MinValue); MakePrimitiveTest(short.MaxValue); } [Fact] public void SerializeUShort() { MakePrimitiveTest(-0); MakePrimitiveTest(0); MakePrimitiveTest(10); MakePrimitiveTest(ushort.MinValue); MakePrimitiveTest(ushort.MaxValue); } [Fact] public void SerializeInt64() { MakePrimitiveTest(-0); MakePrimitiveTest(0); MakePrimitiveTest(-10); MakePrimitiveTest(10); MakePrimitiveTest(Int64.MinValue); MakePrimitiveTest(Int64.MaxValue); MakePrimitiveTest(Int64.MinValue / 2); MakePrimitiveTest(Int64.MaxValue / 2); } [Fact] public void SerializeUInt64() { MakePrimitiveTest(-0); MakePrimitiveTest(0); MakePrimitiveTest(10); MakePrimitiveTest(UInt64.MinValue); MakePrimitiveTest(UInt64.MaxValue); MakePrimitiveTest(UInt64.MinValue / 2); MakePrimitiveTest(UInt64.MaxValue / 2); } [Fact] public void SerializeDecimal() { MakePrimitiveTest(-0); MakePrimitiveTest(0); MakePrimitiveTest(-10); MakePrimitiveTest(10); MakePrimitiveTest(Decimal.MinValue); MakePrimitiveTest(Decimal.MaxValue); MakePrimitiveTest(Decimal.MinValue / 2); MakePrimitiveTest(Decimal.MaxValue / 2); } [Fact] public void SerializeFloat() { MakePrimitiveTest(-0); MakePrimitiveTest(0); MakePrimitiveTest(-10); MakePrimitiveTest(10); MakePrimitiveTest(float.MinValue); MakePrimitiveTest(float.MaxValue); MakePrimitiveTest(float.MinValue / 2); MakePrimitiveTest(float.MaxValue / 2); } [Fact] public void SerializeDouble() { MakePrimitiveTest(-0); MakePrimitiveTest(0); MakePrimitiveTest(-10); MakePrimitiveTest(10); MakePrimitiveTest(Double.MinValue); MakePrimitiveTest(Double.MaxValue); MakePrimitiveTest(Double.MinValue / 2); MakePrimitiveTest(Double.MaxValue / 2); } [Fact] public void SerializeBoolean() { MakePrimitiveTest(true); MakePrimitiveTest(false); } [Fact] public void SerializeByte() { MakePrimitiveTest(0); MakePrimitiveTest(-0); MakePrimitiveTest(1); MakePrimitiveTest(10); MakePrimitiveTest(128); MakePrimitiveTest(255); } [Fact] public void SerializeBytes() { var comparator = new Func((left, right) => (left == null && (right == null || right.Length == 0)) || ArrayExtensions.UnsafeEquals(left, right)); MakePrimitiveTest(null, comparator); MakePrimitiveTest(new byte[] { }, comparator); MakePrimitiveTest(new byte[] { 1 }, comparator); MakePrimitiveTest(new byte[] { 0, 1, 10, 100, 128, 255 }, comparator); } /* COLLECTIONS */ [Fact] public void SerializeCollectionDateTime() { MakeCollectionTest(null); MakeCollectionTest(new DateTime?[] { }); MakeCollectionTest(new DateTime?[] { DateTime.Now, DateTime.UtcNow, DateTime.Today, DateTime.Now.AddYears(2000), null, DateTime.MinValue, DateTime.MaxValue }); } [Fact] public void SerializeCollectionIPAddress() { var comparator = new Func((left, right) => NetUtils.Compare(left, right) == 0); MakeCollectionTest(null); MakeCollectionTest(new IPAddress[] { IPAddress.Any, IPAddress.Broadcast, IPAddress.IPv6Any, IPAddress.IPv6Loopback, IPAddress.IPv6None, IPAddress.Loopback, IPAddress.None, IPAddress.Parse("93.111.16.58") }, comparator); } [Fact] public void SerializeCollectionIPEndPoint() { var comparator = new Func((left, right) => NetUtils.Compare(left, right) == 0); MakeCollectionTest(null); MakeCollectionTest(new IPEndPoint[] { }); MakeCollectionTest(new IPEndPoint[] { new IPEndPoint(IPAddress.Any, 1), new IPEndPoint(IPAddress.Broadcast, 600), new IPEndPoint(IPAddress.IPv6Any, IPEndPoint.MaxPort), new IPEndPoint(IPAddress.IPv6Loopback, 8080), new IPEndPoint(IPAddress.IPv6None, 80), new IPEndPoint(IPAddress.Loopback, 9000), new IPEndPoint(IPAddress.None, 0), new IPEndPoint(IPAddress.Parse("93.111.16.58"), IPEndPoint.MinPort) }, comparator); } [Fact] public void SerializeCollectionGuid() { MakeCollectionTest(null); MakeCollectionTest(new Guid[] { }); MakeCollectionTest(new Guid[] { Guid.Empty, Guid.NewGuid() }); } [Fact] public void SerializeCollectionTimeSpan() { MakeCollectionTest(new TimeSpan[] { TimeSpan.MaxValue, TimeSpan.MinValue, TimeSpan.Zero, TimeSpan.FromDays(1024), TimeSpan.FromMilliseconds(1), TimeSpan.FromTicks(1), TimeSpan.FromTicks(0) }); } [Fact] public void SerializeCollectionString() { var comparator = new Func((left, right) => (left == null && right == null) || (left == null && right != null && right.Length == 0) || (left != null && left.Length == 0 && right == null) || string.Compare(left, right, StringComparison.InvariantCulture) == 0); MakeCollectionTest(new string[] { "", String.Empty, null, "HELLO!", "𐌼𐌰𐌲 𐌲𐌻𐌴𐍃 𐌹̈𐍄𐌰𐌽, 𐌽𐌹 𐌼𐌹𐍃 𐍅𐌿 𐌽𐌳𐌰𐌽 𐌱𐍂𐌹𐌲𐌲𐌹𐌸" }, comparator); } [Fact] public void SerizlizeCollectionChar() { // Arrange var line = "abcxyzABCZА-Яа-яёЁйЙ123"; // Act var bytes_string = MessageSerializer.SerializeCompatible(line); var bytes_charenum = MessageSerializer.SerializeCompatible>(line); // Assert var test_line1 = MessageSerializer.DeserializeCompatible(bytes_string); var test_line2 = new string(MessageSerializer.DeserializeCompatible>(bytes_charenum).ToArray()); Assert.Equal(line, test_line1); Assert.Equal(line, test_line2); Assert.NotEqual(bytes_string, bytes_charenum); } [Fact] public void EOSTest() { var data = new Dictionary { { 0, "asd"}, { 1, "sdf"}, { 2, "dfg"}, { 3, "fgh"}, { 4, "ghj"} }; var num_data = long.MaxValue >> 1; var date_data = DateTime.UtcNow; byte[] serialized; using (var writer = new MemoryStreamWriter()) { writer.WriteDateTime(date_data); foreach (var key in data.Keys.OrderBy(k => k)) { writer.WriteLong(key); writer.WriteString(data[key]); } writer.WriteLong(num_data); serialized = writer.Complete(); } using (var reader = new MemoryStreamReader(serialized)) { Assert.False(reader.EOS); var date = reader.ReadDateTime(); Assert.Equal(date, date_data); Assert.False(reader.EOS); for (long i = 0; i < 5; i++) { Assert.Equal(i, reader.ReadLong()); Assert.False(reader.EOS); Assert.Equal(data[i], reader.ReadString()); Assert.False(reader.EOS); } var num = reader.ReadLong(); Assert.Equal(num, num_data); Assert.True(reader.EOS); } } [Fact] public void SerializeCollectionInt32() { MakeCollectionTest(new int[] { -0, 0, -10, 10, Int32.MinValue, Int32.MaxValue }); } [Fact] public void SerializeCollectionInt64() { MakeCollectionTest(new long[] { -0, 0, -10, 10, Int64.MinValue, Int64.MaxValue, Int64.MinValue / 2, Int64.MaxValue / 2 }); } [Fact] public void SerializeCollectionDecimal() { MakeCollectionTest(new Decimal[] { -0, 0, -10, 10, Decimal.MinValue, Decimal.MaxValue, Decimal.MinValue / 2, Decimal.MaxValue / 2 }); } [Fact] public void SerializeCollectionFloat() { MakeCollectionTest(new float[] { -0, 0, -10, 10, float.MinValue, float.MaxValue, float.MinValue / 2, float.MaxValue / 2 }); } [Fact] public void SerializeCollectionDouble() { MakeCollectionTest(new Double[] { -0, 0, -10, 10, Double.MinValue, Double.MaxValue, Double.MinValue / 2, Double.MaxValue / 2 }); } [Fact] public void SerializeCollectionBoolean() { MakeCollectionTest(new Boolean[] { true, false, true }); } [Fact] public void SerializeCollectionByte() { MakeCollectionTest(new byte[] { 0, 3, -0, 1, 10, 128, 255 }); } [Fact] public void SerializeCollectionBytes() { var comparator = new Func((left, right) => (left == null && (right == null || right.Length == 0)) || ArrayExtensions.UnsafeEquals(left, right)); MakeCollectionTest(new Byte[][] { null, new byte[] { }, new byte[] { 1 }, new byte[] { 0, 1, 10, 100, 128, 255 } }, comparator); } [Fact] public void SerializeCompositeObject() { var comparator = new Func((left, right) => { var l_bin = MessageSerializer.Serialize(left); var r_bin = MessageSerializer.Serialize(right); return ArrayExtensions.UnsafeEquals(l_bin, r_bin); }); MakePrimitiveTest(CompositeInstanceFactory.MakeDocument(), comparator); } [Fact] public void SerializeCompositeOnjectCollection() { var comparator = new Func((left, right) => { var l_bin = MessageSerializer.Serialize(left); var r_bin = MessageSerializer.Serialize(right); return ArrayExtensions.UnsafeEquals(l_bin, r_bin); }); var collection = new Document[] { CompositeInstanceFactory.MakeDocument(), CompositeInstanceFactory.MakeDocument(), CompositeInstanceFactory.MakeDocument() }; var data = MessageSerializer.Serialize(collection); var restored = MessageSerializer.DeserializeCollection(data); var restored_lazy = MessageSerializer.DeserializeCollectionLazy(data); // Assert Assert.True(CollectionComparsionExtensions.OrderingEquals(collection, restored, comparator)); Assert.True(CollectionComparsionExtensions.OrderingEquals(collection, restored_lazy, comparator)); } [Fact] public void ReverseByteOrderTest() { var data = new byte[4] { 0, 0, 8, 1 }; using (var reader = new MemoryStreamReader(data)) { Assert.Equal(17301504, reader.ReadInt32()); } using (var reader = new MemoryStreamReader(data)) { reader.ReverseByteOrder(true); Assert.Equal(2049, reader.ReadInt32()); } } [Fact] public void SerializeDictionaryTest() { var dict = new Dictionary { {0, "Dear" }, {1, "Chaisy" }, {2, "Lain" } }; MakeDictionaryTest(dict); } [Fact] public void SerializeDictionaryWithComposedObjectTest() { var dict = new Dictionary { {0, CompositeInstanceFactory.MakeDocument() }, {1, CompositeInstanceFactory.MakeDocument() }, {2, CompositeInstanceFactory.MakeDocument() }, {3, CompositeInstanceFactory.MakeDocument() } }; var comparator = new Func((left, right) => { var l_bin = MessageSerializer.Serialize(left); var r_bin = MessageSerializer.Serialize(right); return ArrayExtensions.UnsafeEquals(l_bin, r_bin); }); MakeDictionaryTest(dict, valueComparator: comparator); } } }