1 module mutils.serializer.tests;
2 
3 import std.meta;
4 
5 import mutils.container.vector : Vector;
6 import mutils.serializer.binary;
7 import mutils.serializer.binary_maped;
8 import mutils.serializer.json;
9 
10 // Minimum requirements for all serializers:
11 // - fields serialized in order must work
12 // - @("noserialize") support
13 // - has to have default serializer instance (Serializer.instance)
14 // - supports customSerialize
15 
16 import MSC;
17 
18 auto getContainer(Serializer)() {
19     static if (is(Serializer.SliceElementType == ubyte)) {
20         return CON_UB();
21     } else static if (is(Serializer.SliceElementType == char)) {
22         return CON_C();
23     } else {
24         return Vector!(Serializer.SliceElementType)();
25     }
26 }
27 
28 void testSerializerInOut(Serializer, VariableIn, VariableOut)(
29         ref Serializer serializer, VariableIn varIn, VariableOut varOut) {
30     auto container = getContainer!Serializer;
31     serializer.serialize!(Load.no)(varIn, container);
32     assert(container.length > 0);
33 
34     VariableOut outVarTest;
35     serializer.serialize!(Load.yes)(outVarTest, container[]);
36     assert(outVarTest == varOut);
37 }
38 
39 void testSerializerBeginEnd(Serializer)(ref Serializer serializer) {
40     int numA = 1;
41     long numB = 2;
42     int numC = 3;
43 
44     auto container = getContainer!Serializer;
45 
46     auto begin = serializer.beginObject!(Load.no)(container);
47     serializer.serialize!(Load.no)(numA, container);
48     serializer.serialize!(Load.no)(numB, container);
49     serializer.serialize!(Load.no)(numC, container);
50     serializer.endObject!(Load.no)(container, begin);
51 
52     numA = 0;
53     numB = 0;
54     numC = 0;
55     import std.stdio;
56 
57     auto slice = container[];
58 
59     begin = serializer.beginObject!(Load.yes)(slice);
60     serializer.serialize!(Load.yes)(numA, slice);
61     serializer.serialize!(Load.yes)(numB, slice);
62     serializer.serialize!(Load.yes)(numC, slice);
63     serializer.endObject!(Load.yes)(slice, begin);
64 
65     assert(numA == 1);
66     assert(numB == 2);
67     assert(numC == 3);
68 }
69 
70 struct TestA {
71     int a;
72     int b;
73 }
74 
75 struct TestB {
76     int a;
77     int b;
78     TestA c;
79 }
80 
81 struct TestC {
82     int a;
83     int b;
84     TestA c;
85 
86     void customSerialize(Load load, Serializer, COS)(Serializer serializer, ref COS con) {
87         auto begin = serializer.beginObject!(load)(con);
88         scope (exit)
89             serializer.endObject!(load)(con, begin);
90 
91         serializer.serializeWithName!(load, "varA")(a, con);
92         serializer.serializeWithName!(load, "varB")(b, con);
93         serializer.serializeWithName!(load, "varC")(c, con);
94 
95     }
96 }
97 
98 // Test common serialzier properties
99 unittest {
100     alias SerializersToTest = AliasSeq!(BinarySerializer,
101             BinarySerializerMaped, JSONSerializerToken);
102 
103     enum TestA[3] arrA = [TestA(1, 2), TestA(3, 4), TestA(5, 6)];
104 
105     foreach (Serializer; SerializersToTest) {
106         testSerializerInOut(Serializer.instance, 4, 4);
107         testSerializerInOut(Serializer.instance, TestA(1, 2), TestA(1, 2));
108         testSerializerInOut(Serializer.instance, TestB(3, 4, TestA(1, 2)),
109                 TestB(3, 4, TestA(1, 2)));
110         testSerializerInOut(Serializer.instance, TestC(3, 4, TestA(1, 2)),
111                 TestC(3, 4, TestA(1, 2)));
112 
113         testSerializerInOut(Serializer.instance, Vector!TestA(arrA), Vector!TestA(arrA));
114 
115         testSerializerBeginEnd(Serializer.instance);
116     }
117 }
118 
119 struct TestA_Diff {
120     int xxx;
121     byte a;
122 }
123 
124 struct TestB_Diff {
125     long b;
126     TestA_Diff c;
127     ushort a;
128 }
129 
130 struct TestB_Diff2 {
131 }
132 
133 // Test out of order loading,loading without present members, loading with different types
134 unittest {
135     alias SerializersToTest = AliasSeq!(BinarySerializerMaped, JSONSerializerToken);
136 
137     enum TestA[3] arrA = [TestA(1, 2), TestA(3, 4), TestA(5, 6)];
138 
139     foreach (Serializer; SerializersToTest) {
140         testSerializerInOut(Serializer.instance, TestA(1, 2), TestA_Diff(0, 1));
141         testSerializerInOut(Serializer.instance, TestB(3, 4, TestA(1, 2)),
142                 TestB_Diff(4, TestA_Diff(0, 1), 3));
143         testSerializerInOut(Serializer.instance, TestB(3, 4, TestA(1, 2)), TestB_Diff2());
144 
145         testSerializerInOut(Serializer.instance, Vector!TestA(arrA), Vector!TestA(arrA));
146 
147         testSerializerBeginEnd(Serializer.instance);
148     }
149 }