rd-net/Test.RdFramework/Reflection/ScalarBuiltInSerializerTests.cs (273 lines of code) (raw):

using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using JetBrains.Collections.Viewable; using JetBrains.Core; using JetBrains.Rd; using JetBrains.Rd.Impl; using JetBrains.Rd.Reflection; using JetBrains.Serialization; using NUnit.Framework; using static JetBrains.Rd.Reflection.BuiltInSerializers.BuiltInType; namespace Test.RdFramework.Reflection { [TestFixture] public class ScalarBuiltInSerializerTests : RdReflectionTestBase { [Test] public void TestAllMarkedBuiltInTypes() { var additionalTypes = new Dictionary<Type, BuiltInSerializers.BuiltInType> { { typeof(RdMap<int, int>), ProtocolCollectionLike2 }, { typeof(RdList<int>), ProtocolCollectionLike1 } }; foreach (var type in typeof(ScalarBuiltInSerializerTests).Assembly.GetTypes().Concat(additionalTypes.Keys)) { var expectedType = type.GetCustomAttribute<AssertBuiltInTypeAttribute>()?.BuiltInType; if (additionalTypes.TryGetValue(type, out var knowType)) expectedType = knowType; if (expectedType.HasValue) { var builtInType = BuiltInSerializers.GetBuiltInType(type.GetTypeInfo()); if (builtInType != expectedType) { Assert.AreEqual(expectedType, builtInType, "Unexpected built-in serializer type detected for type {0}", type); } } } } [Test] public void TestReadWriteMethods() { WithExts<Ext1>((c, s) => { c.Simple.Value = new NoRedBuiltIn1(1,1,1); Assert.AreEqual(0, s.Simple.Value.Red); Assert.AreEqual(1, s.Simple.Value.Green); Assert.AreEqual(1, s.Simple.Value.Blue); }); } [Test] public void TestReadWriteFields() { WithExts<Ext2>((c, s) => { c.Simple.Value = new NoRedBuiltIn2(1,1,1); Assert.AreEqual(0, s.Simple.Value.Red); Assert.AreEqual(1, s.Simple.Value.Green); Assert.AreEqual(1, s.Simple.Value.Blue); }); } [Test] public void TestRdScalarAttribute() { WithExts<Ext3>((c, s) => { c.Simple.Value = new NoRedBuiltIn3(1,1,1); Assert.AreEqual(0, s.Simple.Value.Red); Assert.AreEqual(1, s.Simple.Value.Green); Assert.AreEqual(1, s.Simple.Value.Blue); }); } [Test] public void TestRdSimpleMethods() { WithExts<Ext4>((c, s) => { c.Simple.Value = new NoRedBuiltIn4<int, int>(1,1,1); Assert.AreEqual(0, s.Simple.Value.Red); Assert.AreEqual(1, s.Simple.Value.Green); Assert.AreEqual(1, s.Simple.Value.Blue); }); } [Test] public void TestRdSimpleMethodsStaticWrite() { WithExts<Ext5>((c, s) => { c.Simple.Value = new OuterClass<Unit>.NoRedBuiltIn5(1,1,1); Assert.AreEqual(0, s.Simple.Value.Red); Assert.AreEqual(1, s.Simple.Value.Green); Assert.AreEqual(1, s.Simple.Value.Blue); }); } [Test] public void TestExternalSerialization() { void Reg(ReflectionSerializers cache) { cache.Register( (ctx, reader) => new ScalarTests.ColorFields(0, reader.ReadByte(), reader.ReadByte()), (ctx, writer, value) => { writer.WriteByte((byte) value.Green); writer.WriteByte((byte) value.Blue); }); } Reg(CFacade.Serializers); Reg(SFacade.Serializers); WithExts<RegularExt>((c, s) => { c.Simple.Value = new ScalarTests.ColorFields(1,1,1); Assert.AreEqual(0, s.Simple.Value.Red); Assert.AreEqual(1, s.Simple.Value.Green); Assert.AreEqual(1, s.Simple.Value.Blue); }); } [RdExt] public class Ext1 : RdExtReflectionBindableBase { public IViewableProperty<NoRedBuiltIn1> Simple { get; } } [RdExt] public class Ext2 : RdExtReflectionBindableBase { public IViewableProperty<NoRedBuiltIn2> Simple { get; } } [RdExt] public class Ext3 : RdExtReflectionBindableBase { public IViewableProperty<NoRedBuiltIn3> Simple { get; } } [RdExt] public class Ext4 : RdExtReflectionBindableBase { public IViewableProperty<NoRedBuiltIn4<int, int>> Simple { get; } } [RdExt] public class Ext5 : RdExtReflectionBindableBase { public IViewableProperty<OuterClass<Unit>.NoRedBuiltIn5> Simple { get; } } [RdExt] public class RegularExt : RdExtReflectionBindableBase { public IViewableProperty<ScalarTests.ColorFields> Simple { get; } } /// <summary> /// Built-in serializers way 1: special fields /// </summary> [RdScalar, AssertBuiltInType(StaticFields)] // not required public class NoRedBuiltIn1 { public int Red { get; } public int Green { get; } public int Blue { get; } public NoRedBuiltIn1(int red, int green, int blue) { Red = red; Green = green; Blue = blue; } public static CtxReadDelegate<NoRedBuiltIn1> Read = (ctx, reader) => new NoRedBuiltIn1(0/*reader.ReadByte()*/, reader.ReadByte(), reader.ReadByte()); public static CtxWriteDelegate<NoRedBuiltIn1> Write = (ctx, writer, value) => { // writer.Write((byte) value.Red); writer.WriteByte((byte) value.Green); writer.WriteByte((byte) value.Blue); }; } /// <summary> /// Built-in serializers way 2: magic static methods /// </summary> [RdScalar, AssertBuiltInType(StaticProtocolMethods)] // not required public class NoRedBuiltIn2 { public int Red { get; } public int Green { get; } public int Blue { get; } public NoRedBuiltIn2(int red, int green, int blue) { Red = red; Green = green; Blue = blue; } public static NoRedBuiltIn2 Read(SerializationCtx ctx, UnsafeReader reader) { return new NoRedBuiltIn2(0 /*reader.ReadByte()*/, reader.ReadByte(), reader.ReadByte()); } public static void Write(SerializationCtx ctx, UnsafeWriter writer, NoRedBuiltIn2 value) { // writer.Write((byte) value.Red); writer.WriteByte((byte) value.Green); writer.WriteByte((byte) value.Blue); } } /// <summary> /// Built-in serializers way 3: marshallers /// </summary> [RdScalar(typeof(Marshaller)), AssertBuiltInType(MarshallerAttribute)] public class NoRedBuiltIn3 { public int Red { get; } public int Green { get; } public int Blue { get; } public NoRedBuiltIn3(int red, int green, int blue) { Red = red; Green = green; Blue = blue; } } /// <summary> /// Built-in serializers way 4: implemented directly in type via Non-protocol methods with unsafe writers /// </summary> [AssertBuiltInType(Methods)] public class NoRedBuiltIn4<T1/*optional*/, T2/*optional*/> { public int Red { get; } public int Green { get; } public int Blue { get; } public NoRedBuiltIn4(int red, int green, int blue) { Red = red; Green = green; Blue = blue; } public static NoRedBuiltIn4<T1, T2> Read(UnsafeReader reader) { return new NoRedBuiltIn4<T1, T2>(0 /*reader.ReadByte()*/, reader.ReadByte(), reader.ReadByte()); } public void Write(UnsafeWriter writer) { // writer.Write((byte) value.Red); writer.WriteByte((byte) Green); writer.WriteByte((byte) Blue); } // Overloads with same name are allowed public void Write(Stream stream) { } public static NoRedBuiltIn4<T1, T2> Read(Stream stream) => default; } public class OuterClass<T> { /// <summary> /// Built-in serializers way 5: implemented directly in type via Non-protocol methods with unsafe writers, but write method can be static /// </summary> [AssertBuiltInType(StaticMethods)] public record NoRedBuiltIn5(int Red, int Green, int Blue) { public static NoRedBuiltIn5 Read(UnsafeReader reader) { return new NoRedBuiltIn5(0 /*reader.ReadByte()*/, reader.ReadByte(), reader.ReadByte()); } public static void Write(UnsafeWriter writer, NoRedBuiltIn5 value) { // writer.Write((byte) value.Red); writer.WriteByte((byte)value.Green); writer.WriteByte((byte)value.Blue); } public virtual bool Equals(NoRedBuiltIn5 other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Red == other.Red && Green == other.Green && Blue == other.Blue; } public override int GetHashCode() { unchecked { var hashCode = Red; hashCode = (hashCode * 397) ^ Green; hashCode = (hashCode * 397) ^ Blue; return hashCode; } } } } public class Marshaller : IBuiltInMarshaller<NoRedBuiltIn3> { public NoRedBuiltIn3 Read(SerializationCtx ctx, UnsafeReader reader) { return new NoRedBuiltIn3(0 /*reader.ReadByte()*/, reader.ReadByte(), reader.ReadByte()); } public void Write(SerializationCtx ctx, UnsafeWriter writer, NoRedBuiltIn3 value) { // writer.Write((byte) value.Red); writer.WriteByte((byte) value.Green); writer.WriteByte((byte) value.Blue); } } } }