using System; using System.Collections.Generic; using System.Linq; using JetBrains.Collections.Viewable; using JetBrains.Rd.Impl; using JetBrains.Rd.Reflection; using JetBrains.Serialization; using NUnit.Framework; namespace Test.RdFramework.Reflection { [TestFixture] public class ScalarTests : RdReflectionTestBase { [Test] public void TestColor1() { WithExts((c, s) => { c.Map.Add(new ColorFields(100, 100, 100), long.MaxValue); Assert.AreEqual(s.Map[new ColorFields(100, 100, 100)], c.Map.Values.First()); }); } [Test] public void TestColor2() { WithExts((c, s) => { c.List.Add(new ColorStruct() {Blue = 1, Green = 2, Red = 3}); c.List.Add(new ColorStruct()); CollectionAssert.AreEqual(s.List, c.List); }); } [Test] public void TestColor3() { WithExts((c, s) => { c.List.Add(new ColorStruct() {Blue = 1, Green = 2, Red = 3}); c.List.Add(new ColorStruct()); CollectionAssert.AreEqual(s.List, c.List); }); } [Test] public void TestValueTuple() { WithExts((c, s) => { var val = ("test", "test2"); c.SimpleTuple.Value = val; Assert.AreEqual(val, s.SimpleTuple.Value); }); } [Test] public void TestValueTupleNested() { WithExts((c, s) => { var val = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1); s.NestedTuple.Value = val; Assert.AreEqual(val, c.NestedTuple.Value); }); } [Test] public void TestArrays() { WithExts((c, s) => { s.IntArray.Value = new[] {1, 2, 3}; CollectionAssert.AreEqual(s.IntArray.Value, c.IntArray.Value); }); } [Test] public void TestArrays2() { WithExts((c, s) => { s.ComplexArray.Value = new[] {new[] {new[] {1, 2, 3}}}; CollectionAssert.AreEqual(s.ComplexArray.Value[0][0], c.ComplexArray.Value[0][0]); }); } [Test] public void TestArrays3() { WithExts((c, s) => { s.ValueTupleArray.Value = new[] {("key", "value"), ("key", "value")}; CollectionAssert.AreEqual(s.ValueTupleArray.Value, c.ValueTupleArray.Value); }); } [Test] public void TestArraysClass() { WithExts((c, s) => { s.Property.Value = new ColorFields(1, 1, 1); s.PropertyArray.Value = new[] {new ColorFields(2, 2, 2)}; Assert.AreEqual(s.Property.Value, c.Property.Value); CollectionAssert.AreEqual(s.PropertyArray.Value, c.PropertyArray.Value); }); } [Test] public void TestList2() { AddType(typeof(ColorFields)); WithExts((c, s) => { s.Objects.Value = new ListOwner() { Ints = new List() {1, 2, 3}, Polymorphic = new List() { new ColorFields(1, 2, 3) }, PolymorphicArray = new List() { new ColorFields[30] } }; CollectionAssert.AreEqual(s.Objects.Value.Ints, c.Objects.Value.Ints); Assert.AreEqual(s.Objects.Value.Polymorphic[0].Blue, s.Objects.Value.Polymorphic[0].Blue); Assert.AreEqual(s.Objects.Value.PolymorphicArray[0].Length, s.Objects.Value.PolymorphicArray[0].Length); }); } [Test] public void TestListInterface() { WithExts((c, s) => { c.Objects.Value = new ListInterfacesExt.ListOwner1() { InterfaceListOfInts = new List() {1, 2, 3}, ListOfInts = new List() {1, 2, 3}, CollectionOfInts = new List() {1, 2, 3}, ReadonlyListInts = new List() {1, 2, 3}, EnumerableInts = new List() {1, 2, 3}, }; CollectionAssert.AreEqual(c.Objects.Value.InterfaceListOfInts , s.Objects.Value.InterfaceListOfInts ); CollectionAssert.AreEqual(c.Objects.Value.ListOfInts , s.Objects.Value.ListOfInts ); CollectionAssert.AreEqual(c.Objects.Value.CollectionOfInts , s.Objects.Value.CollectionOfInts ); CollectionAssert.AreEqual(c.Objects.Value.ReadonlyListInts , s.Objects.Value.ReadonlyListInts ); CollectionAssert.AreEqual(c.Objects.Value.EnumerableInts , s.Objects.Value.EnumerableInts ); }); } [RdExt] public class ListInterfacesExt : RdExtReflectionBindableBase { public IViewableProperty Objects { get; } public class ListOwner1 { public IList InterfaceListOfInts; public List ListOfInts; public IList CollectionOfInts; public IReadOnlyList ReadonlyListInts; public IEnumerable EnumerableInts; } } [Test] public void TestEventArgs() { WithExts((c, s) => { c.Objects.Value = new MyEventArgs() { Value = 42 }; Assert.AreEqual(42, s.Objects.Value.Value); }); } [Test] public void TestGenericStruct() { WithExts((c, s) => { c.EnumStruct.Value = new TextControlOverridableValue(MyEnum.First, MyEnum.Second); c.IntStruct.Value = new TextControlOverridableValue(1,2); Assert.AreEqual(MyEnum.First, s.EnumStruct.Value.Original); Assert.AreEqual(MyEnum.Second, s.EnumStruct.Value.Override); Assert.AreEqual(1, s.IntStruct.Value.Original); Assert.AreEqual(2, s.IntStruct.Value.Override); }); } [Test] public void TestDictionary() { RunScalarTest(new Dictionary() { {"a", "b"}}, CollectionAssert.AreEqual); } [Test] public void TestIDictionary() { RunScalarTest(new Dictionary() { {"a", "b"}} as IDictionary, CollectionAssert.AreEqual); } [Test] public void TestReadOnlyDictionary() { RunScalarTest(new Dictionary() { {"a", "b"}} as IReadOnlyDictionary, CollectionAssert.AreEqual); } [Test] public void TestBoxing() { RunScalarTest(true, (a, b) => Assert.AreEqual((bool)a, (bool)b)); RunScalarTest(MyEnum.First, (a, b) => Assert.AreEqual((MyEnum)a, (MyEnum)b)); } [Test] public void TestCyclic() { RunScalarTest(new RedBlackList {Start = new RedBlackList.BlackNode() {Next = new RedBlackList.RedNode()}}, (a, b) => { Assert.NotNull(b.Start.Next); Assert.Null(b.Start.Next.Next); }); } [Test] public void TestInvalidPointers() { Assert.Throws(() => { RunScalarTest(new NonScalarPtr(), (a, b) => { }); }); } public class NonScalarPtr { public Action X; } public sealed class RedBlackList { public BlackNode Start; public sealed class BlackNode { public RedNode Next; } public sealed class RedNode { public BlackNode Next; } } public void RunScalarTest(T instance, Action checkEqual) { var scalar = new ReflectionSerializers(CFacade.TypesCatalog); var serializerPair = scalar.GetOrRegisterSerializerPair(typeof(T), true); var reader = serializerPair.GetReader(); var writer = serializerPair.GetWriter(); using (var cookie = UnsafeWriter.NewThreadLocalWriter()) { unsafe { writer(default, cookie.Writer, instance); var unsafeReader = UnsafeReader.CreateReader(cookie.Data, cookie.Count); var restored = reader(default, unsafeReader); checkEqual(instance, restored); } } } [RdExt] public class GenericStructExt : RdExtReflectionBindableBase { public IViewableProperty> IntStruct { get; } public IViewableProperty> EnumStruct { get; } } [RdScalar] public struct TextControlOverridableValue { public TextControlOverridableValue(T original, T @override) { Original = original; Override = @override; } public T Original; public T Override; } [RdExt] public class EventArgsExt : RdExtReflectionBindableBase { public IViewableProperty> Objects { get; } } [RdScalar] public class MyEventArgs : EventArgs { public T Value; } [RdExt] public class ListObjectsExt : RdExtReflectionBindableBase { public IViewableProperty Objects { get; } } [RdScalar] // not required public class ListOwner { public List Polymorphic; public List PolymorphicArray; public List Ints; } [RdExt] public class ArraysExt : RdExtReflectionBindableBase { public IViewableProperty IntArray { get; } public IViewableProperty ComplexArray { get; } public IViewableProperty<(string, string)[]> ValueTupleArray { get; } } [RdExt] public class ArraysExt2 : RdExtReflectionBindableBase { public IViewableProperty Property { get; } public IViewableProperty PropertyArray { get; } } [RdExt] public class ValueTuplesExt : RdExtReflectionBindableBase { public IViewableProperty<(string, string)> SimpleTuple { get; } public IViewableProperty<(int, int, int, int, int, int, int, int, int, int, int, int, int)> NestedTuple { get; } } [RdExt] public class ColorsExt : RdExtReflectionBindableBase { public RdProperty Property { get; } public IViewableMap Map { get; } public IViewableList List { get; } } [RdScalar] // not required public struct ColorClass { public int Red { get; set; } public int Green { get; set; } public int Blue { get; set; } } [RdScalar] // not required public struct ColorStruct { public int Red { get; set; } public int Green { get; set; } public int Blue { get; set; } } [RdScalar] // not required public sealed class ColorFields { public int Red { get; } public int Green { get; } public int Blue { get; } public ColorFields(int red, int green, int blue) { Red = red; Green = green; Blue = blue; } public ColorFields() { } private bool Equals(ColorFields other) { return Red == other.Red; } 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((ColorFields) obj); } public override int GetHashCode() { return Red; } } public class Scalar1 { public string Name; public Scalar2 Value; } public class Scalar2 { public Scalar2(long value, int only) { Value = value; SetOnly = only; } public long Value { get; set; } public int SetOnly { get; } } } }