27
|
1
|
|
2 /**
|
|
3 * Copyright: Copyright (c) 2010 Jacob Carlborg. All rights reserved.
|
|
4 * Authors: Jacob Carlborg
|
|
5 * Version: Initial created: Nov 5, 2010
|
|
6 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
|
|
7 */
|
|
8 module tests.Serializer;
|
|
9
|
|
10 private:
|
|
11
|
|
12 import orange.serialization.Serializer;
|
|
13 import orange.serialization.archives.XMLArchive;
|
|
14 import orange.core.io;
|
|
15 import orange.core.string;
|
|
16
|
|
17 bool containsDefaultXmlContent (string source)
|
|
18 {
|
|
19 return source.containsXmlHeader() &&
|
|
20 source.containsArchive() &&
|
|
21 source.containsXmlTag("data");
|
|
22 }
|
|
23
|
|
24 bool containsXmlHeader (string source)
|
|
25 {
|
|
26 return source.contains(`<?xml version="1.0" encoding="UTF-8"?>`);
|
|
27 }
|
|
28
|
|
29 bool containsArchive (string source)
|
|
30 {
|
|
31 return source.containsArchiveHeader() && source.contains("</archive>");
|
|
32 }
|
|
33
|
|
34 bool containsArchiveHeader (string source)
|
|
35 {
|
|
36 return source.contains(`<archive type="org.dsource.orange.xml" version="1.0.0">`);
|
|
37 }
|
|
38
|
|
39 bool containsXmlTag (string source, string tag, bool simple = false)
|
|
40 {
|
|
41 return source.containsXmlTag(tag, null, null, simple);
|
|
42 }
|
|
43
|
|
44 bool containsXmlTag (string source, string tag, string attributes, bool simple = false)
|
|
45 {
|
|
46 return source.containsXmlTag(tag, attributes, null, simple);
|
|
47 }
|
|
48
|
|
49 bool containsXmlTag (string source, string tag, string attributes, string content, bool simple = false)
|
|
50 {
|
|
51 string pattern = '<' ~ tag;
|
|
52
|
|
53 if (attributes.length > 0)
|
|
54 pattern ~= ' ' ~ attributes;
|
|
55
|
|
56 if (simple)
|
|
57 return source.contains(pattern ~ "/>");
|
|
58
|
|
59 if (content.length > 0)
|
|
60 return source.contains(pattern ~ '>' ~ content ~ "</" ~ tag ~ '>');
|
|
61
|
|
62 return source.contains(pattern ~ '>') && source.contains("</" ~ tag ~ '>');
|
|
63 }
|
|
64
|
|
65 enum Foo { a, b, c }
|
|
66 typedef int Int;
|
|
67
|
|
68 class A
|
|
69 {
|
|
70 equals_t opEquals (Object other)
|
|
71 {
|
|
72 if (auto o = cast(A) other)
|
|
73 return true;
|
|
74
|
|
75 return false;
|
|
76 }
|
|
77 }
|
|
78
|
|
79 struct B
|
|
80 {
|
|
81 equals_t opEquals (B b)
|
|
82 {
|
|
83 return true;
|
|
84 }
|
|
85 }
|
|
86
|
|
87 class C { string str; }
|
|
88 class D { int[] arr; }
|
|
89 class E { int[int] aa; }
|
|
90 class F { int value; int* ptr; }
|
|
91 class G { Foo foo; }
|
|
92
|
|
93 class H
|
|
94 {
|
|
95 bool bool_;
|
|
96 byte byte_;
|
|
97 //cdouble cdouble_; // currently not suppported by to!()
|
|
98 //cent cent_; // currently not implemented but a reserved keyword
|
|
99 //cfloat cfloat_; // currently not suppported by to!()
|
|
100 char char_;
|
|
101 //creal creal_; // currently not suppported by to!()
|
|
102 dchar dchar_;
|
|
103 double double_;
|
|
104 float float_;
|
|
105 //idouble idouble_; // currently not suppported by to!()
|
|
106 //ifloat ifloat_; // currently not suppported by to!()
|
|
107 int int_;
|
|
108 //ireal ireal_; // currently not suppported by to!()
|
|
109 long long_;
|
|
110 real real_;
|
|
111 short short_;
|
|
112 ubyte ubyte_;
|
|
113 //ucent ucent_; // currently not implemented but a reserved keyword
|
|
114 uint uint_;
|
|
115 ulong ulong_;
|
|
116 ushort ushort_;
|
|
117 wchar wchar_;
|
|
118
|
|
119 equals_t opEquals (Object other)
|
|
120 {
|
|
121 if (auto o = cast(H) other)
|
|
122 {
|
|
123 return bool_ == o.bool_ &&
|
|
124 byte_ == o.byte_ &&
|
|
125 //cdouble_ == o.cdouble_ && // currently not suppported by to!()
|
|
126 //cent_ == o.cent_ && // currently not implemented but a reserved keyword
|
|
127 //cfloat_ == o.cfloat_ && // currently not suppported by to!()
|
|
128 char_ == o.char_ &&
|
|
129 //creal_ == o.creal_ && // currently not suppported by to!()
|
|
130 dchar_ == o.dchar_ &&
|
|
131 double_ == o.double_ &&
|
|
132 float_ == o.float_ &&
|
|
133 //idouble_ == o.idouble_ && // currently not suppported by to!()
|
|
134 //ifloat_ == o.ifloat_ && // currently not suppported by to!()
|
|
135 int_ == o.int_ &&
|
|
136 //ireal_ == o.ireal_ && // currently not suppported by to!()
|
|
137 long_ == o.long_ &&
|
|
138 real_ == o.real_ &&
|
|
139 short_ == o.short_ &&
|
|
140 ubyte_ == o.ubyte_ &&
|
|
141 //ucent_ == o.ucent_ && // currently not implemented but a reserved keyword
|
|
142 uint_ == o.uint_ &&
|
|
143 ulong_ == o.ulong_ &&
|
|
144 ushort_ == o.ushort_ &&
|
|
145 wchar_ == o.wchar_;
|
|
146 }
|
|
147
|
|
148 return false;
|
|
149 }
|
|
150 }
|
|
151
|
|
152 class I
|
|
153 {
|
|
154 Int a;
|
|
155 }
|
|
156
|
|
157 class J
|
|
158 {
|
|
159 string firstSource;
|
|
160 string firstSlice;
|
|
161
|
|
162 string secondSlice;
|
|
163 string secondSource;
|
|
164 }
|
|
165
|
|
166 class K
|
|
167 {
|
|
168 int[int] a;
|
|
169 int[int] b;
|
|
170 }
|
|
171
|
|
172 import orange.test.UnitTester;
|
|
173 Serializer serializer;
|
|
174 XMLArchive!(char) archive;
|
|
175
|
|
176 A a;
|
|
177 B b;
|
|
178 C c;
|
|
179 D d;
|
|
180 E e;
|
|
181 F f;
|
|
182 G g;
|
|
183 H h;
|
|
184 I i;
|
|
185 J j;
|
|
186 J jDeserialized;
|
|
187 K k;
|
|
188
|
|
189 string data;
|
|
190
|
|
191 unittest
|
|
192 {
|
|
193 archive = new XMLArchive!(char);
|
|
194 serializer = new Serializer(archive);
|
|
195
|
|
196 a = new A;
|
|
197
|
|
198 c = new C;
|
|
199 c.str = "foo";
|
|
200
|
|
201 d = new D;
|
|
202 d.arr = [27, 382, 283, 3820, 32, 832].dup;
|
|
203
|
|
204 e = new E;
|
|
205 e.aa = [3 : 4, 1 : 2, 39 : 472, 6 : 7];
|
|
206
|
|
207 f = new F;
|
|
208 f.value = 9;
|
|
209 f.ptr = &f.value;
|
|
210
|
|
211 g = new G;
|
|
212 g.foo = Foo.b;
|
|
213
|
|
214 h = new H;
|
|
215 h.bool_ = true;
|
|
216 h.byte_ = 1;
|
|
217 h.char_ = 'a';
|
|
218 //h.cdouble_ = 0.0 + 0.0 * 1.0i; // currently not supported by to!()
|
|
219 //h.cfloat_ = 0.0f + 0.0f * 1.0i; // currently not supported by to!()
|
|
220 //h.creal_ = 0.0 + 0.0 * 1.0i; // currently not supported by to!()
|
|
221 h.dchar_ = 'b';
|
|
222 h.double_ = 0.0;
|
|
223 h.float_ = 0.0f;
|
|
224 //h.idouble_ = 0.0 * 1.0i; // currently not supported by to!()
|
|
225 //h.ifloat_ = 0.0f * 1.0i; // currently not supported by to!()
|
|
226 h.int_ = 1;
|
|
227 //h.ireal_ = 0.0 * 1.0i; // currently not supported by to!()
|
|
228 h.long_ = 1L;
|
|
229 h.real_ = 0.0;
|
|
230 h.short_ = 1;
|
|
231 h.ubyte_ = 1U;
|
|
232 h.uint_ = 1U;
|
|
233 h.ulong_ = 1LU;
|
|
234 h.ushort_ = 1U;
|
|
235 h.wchar_ = 'c';
|
|
236
|
|
237 i = new I;
|
|
238 i.a = 1;
|
|
239
|
|
240 j = new J;
|
|
241 j.firstSource = "0123456789";
|
|
242 j.firstSlice = j.firstSource[3 .. 7];
|
|
243 j.secondSource = "abcdefg";
|
|
244 j.secondSlice = j.secondSource[1 .. 4];
|
|
245
|
|
246 k = new K;
|
|
247 k.a = [3 : 4, 1 : 2, 39 : 472, 6 : 7];
|
|
248 k.b = k.a;
|
|
249
|
|
250 describe("Serializer") in {
|
|
251 describe("serialize object") in {
|
|
252 it("should return a serialized object") in {
|
|
253 serializer.reset;
|
|
254 serializer.serialize(a);
|
|
255
|
|
256 assert(archive.data().containsDefaultXmlContent());
|
|
257 assert(archive.data().contains(`<object runtimeType="tests.Serializer.A" type="A" key="0" id="0"/>`));
|
|
258 };
|
|
259 };
|
|
260
|
|
261 describe("deserialize object") in {
|
|
262 it("should return a deserialized object equal to the original object") in {
|
|
263 auto aDeserialized = serializer.deserialize!(A)(archive.data);
|
|
264 assert(a == aDeserialized);
|
|
265 };
|
|
266 };
|
|
267
|
|
268 describe("serialize struct") in {
|
|
269 it("should return a serialized struct") in {
|
|
270 serializer.reset;
|
|
271 serializer.serialize(B());
|
|
272
|
|
273 assert(archive.data().containsDefaultXmlContent());
|
|
274 assert(archive.data().contains(`<struct type="B" key="0"/>`));
|
|
275 };
|
|
276 };
|
|
277
|
|
278 describe("deserialize struct") in {
|
|
279 it("should return a deserialized struct equal to the original struct") in {
|
|
280 auto bDeserialized = serializer.deserialize!(B)(archive.data);
|
|
281 assert(b == bDeserialized);
|
|
282 };
|
|
283 };
|
|
284
|
|
285 describe("serialize string") in {
|
|
286 it("should return a serialized string") in {
|
|
287 serializer.reset;
|
|
288
|
|
289 serializer.serialize(c);
|
|
290 assert(archive.data().containsDefaultXmlContent());
|
|
291 assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.C" type="C" key="0" id="0"`));
|
|
292 assert(archive.data().containsXmlTag("string", `type="char" length="3" key="str" id="1"`, "foo"));
|
|
293 };
|
|
294 };
|
|
295
|
|
296 describe("deserialize string") in {
|
|
297 it("should return a deserialized string equal to the original string") in {
|
|
298 auto cDeserialized = serializer.deserialize!(C)(archive.data);
|
|
299 assert(c.str == cDeserialized.str);
|
|
300 };
|
|
301 };
|
|
302
|
|
303 describe("serialize array") in {
|
|
304 it("should return a serialized array") in {
|
|
305 serializer.reset;
|
|
306 serializer.serialize(d);
|
|
307
|
|
308 assert(archive.data().containsDefaultXmlContent());
|
|
309 assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.D" type="D" key="0" id="0"`));
|
|
310 assert(archive.data().containsXmlTag("int", `key="0"`, "27"));
|
|
311 assert(archive.data().containsXmlTag("int", `key="1"`, "382"));
|
|
312 assert(archive.data().containsXmlTag("int", `key="2"`, "283"));
|
|
313 assert(archive.data().containsXmlTag("int", `key="3"`, "3820"));
|
|
314 assert(archive.data().containsXmlTag("int", `key="4"`, "32"));
|
|
315 assert(archive.data().containsXmlTag("int", `key="5"`, "832"));
|
|
316 };
|
|
317 };
|
|
318
|
|
319 describe("deserialize array") in {
|
|
320 it("should return a deserialize array equal to the original array") in {
|
|
321 auto dDeserialized = serializer.deserialize!(D)(archive.data);
|
|
322 assert(d.arr == dDeserialized.arr);
|
|
323 };
|
|
324 };
|
|
325
|
|
326 describe("serialize associative array") in {
|
|
327 it("should return a serialized associative array") in {
|
|
328 serializer.reset();
|
|
329 serializer.serialize(e);
|
|
330
|
|
331 assert(archive.data().containsDefaultXmlContent());
|
|
332 assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.E" type="E" key="0" id="0"`));
|
|
333 assert(archive.data().containsXmlTag("associativeArray", `keyType="int" valueType="int" length="4" key="aa"`));
|
|
334
|
|
335 assert(archive.data().containsXmlTag("key", `key="0"`));
|
|
336 assert(archive.data().containsXmlTag("int", `key="0"`, "1"));
|
|
337 assert(archive.data().containsXmlTag("value", `key="0"`));
|
|
338 assert(archive.data().containsXmlTag("int", `key="0"`, "2"));
|
|
339
|
|
340 assert(archive.data().containsXmlTag("key", `key="1"`));
|
|
341 assert(archive.data().containsXmlTag("int", `key="1"`, "3"));
|
|
342 assert(archive.data().containsXmlTag("value", `key="1"`));
|
|
343 assert(archive.data().containsXmlTag("int", `key="1"`, "4"));
|
|
344
|
|
345 assert(archive.data().containsXmlTag("key", `key="2"`));
|
|
346 assert(archive.data().containsXmlTag("int", `key="2"`, "6"));
|
|
347 assert(archive.data().containsXmlTag("value", `key="2"`));
|
|
348 assert(archive.data().containsXmlTag("int", `key="2"`, "7"));
|
|
349
|
|
350 assert(archive.data().containsXmlTag("key", `key="3"`));
|
|
351 assert(archive.data().containsXmlTag("int", `key="3"`, "39"));
|
|
352 assert(archive.data().containsXmlTag("value", `key="3"`));
|
|
353 assert(archive.data().containsXmlTag("int", `key="3"`, "472"));
|
|
354 };
|
|
355 };
|
|
356
|
|
357 describe("deserialize associative array") in {
|
|
358 it("should return an associative array equal to the original associative array") in {
|
|
359 auto eDeserialized = serializer.deserialize!(E)(archive.data);
|
|
360
|
|
361 foreach (k, v ; eDeserialized.aa)
|
|
362 assert(e.aa[k] == v);
|
|
363
|
|
364 //assert(e.aa == eDeserialized.aa); // cannot compare associative array
|
|
365 };
|
|
366 };
|
|
367
|
|
368 describe("serialize pointer") in {
|
|
369 it("should return a serialized pointer") in {
|
|
370 serializer.reset();
|
|
371
|
|
372 serializer.serialize(f);
|
|
373 assert(archive.data().containsDefaultXmlContent());
|
|
374 assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.F" type="F" key="0" id="0"`));
|
|
375 assert(archive.data().containsXmlTag("pointer", `key="ptr" id="2"`));
|
|
376 assert(archive.data().containsXmlTag("int", `key="1"`, "9"));
|
|
377 assert(archive.data().containsXmlTag("int", `key="value"`, "9"));
|
|
378 };
|
|
379 };
|
|
380
|
|
381 describe("deserialize pointer") in {
|
|
382 it("should return a deserialized pointer equal to the original pointer") in {
|
|
383 auto fDeserialized = serializer.deserialize!(F)(archive.data);
|
|
384 assert(*f.ptr == *fDeserialized.ptr);
|
|
385 };
|
|
386 };
|
|
387
|
|
388 describe("serialize enum") in {
|
|
389 it("should return a serialized enum") in {
|
|
390 serializer.reset();
|
|
391 serializer.serialize(g);
|
|
392 assert(archive.data().containsDefaultXmlContent());
|
|
393 assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.G" type="G" key="0" id="0"`));
|
|
394 assert(archive.data().containsXmlTag("enum", `type="Foo" baseType="int" key="foo"`, "1"));
|
|
395 };
|
|
396 };
|
|
397
|
|
398
|
|
399 describe("deserialize enum") in {
|
|
400 it("should return an enum equal to the original enum") in {
|
|
401 auto gDeserialized = serializer.deserialize!(G)(archive.data);
|
|
402 assert(g.foo == gDeserialized.foo);
|
|
403 };
|
|
404 };
|
|
405
|
|
406 describe("serialize primitives") in {
|
|
407 it("should return serialized primitives") in {
|
|
408 serializer.reset;
|
|
409
|
|
410 serializer.serialize(h);
|
|
411 assert(archive.data().containsDefaultXmlContent());
|
|
412 assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.H" type="H" key="0" id="0"`));
|
|
413 assert(archive.data().containsXmlTag("byte", `key="byte_"`, "1"));
|
|
414 assert(archive.data().containsXmlTag("char", `key="char_"`, "a"));
|
|
415 assert(archive.data().containsXmlTag("dchar", `key="dchar_"`, "b"));
|
|
416 assert(archive.data().containsXmlTag("double", `key="double_"`, "0"));
|
|
417 assert(archive.data().containsXmlTag("float", `key="float_"`, "0"));
|
|
418 assert(archive.data().containsXmlTag("int", `key="int_"`, "1"));
|
|
419 assert(archive.data().containsXmlTag("long", `key="long_"`, "1"));
|
|
420 assert(archive.data().containsXmlTag("real", `key="real_"`, "0"));
|
|
421 assert(archive.data().containsXmlTag("short", `key="short_"`, "1"));
|
|
422 assert(archive.data().containsXmlTag("ubyte", `key="ubyte_"`, "1"));
|
|
423 assert(archive.data().containsXmlTag("uint", `key="uint_"`, "1"));
|
|
424 assert(archive.data().containsXmlTag("ulong", `key="ulong_"`, "1"));
|
|
425 assert(archive.data().containsXmlTag("ushort", `key="ushort_"`, "1"));
|
|
426 assert(archive.data().containsXmlTag("wchar", `key="wchar_"`, "c"));
|
|
427 assert(archive.data().containsXmlTag("bool", `key="bool_"`, "true"));
|
|
428 };
|
|
429 };
|
|
430
|
|
431 describe("deserialize primitives") in {
|
|
432 it("should return deserialized primitives equal to the original primitives") in {
|
|
433 auto hDeserialized = serializer.deserialize!(H)(archive.data);
|
|
434 assert(h == hDeserialized);
|
|
435 };
|
|
436 };
|
|
437
|
|
438 describe("serialize typedef") in {
|
|
439 it("should return a serialized typedef") in {
|
|
440 serializer.reset();
|
|
441 serializer.serialize(i);
|
|
442 assert(archive.data().containsDefaultXmlContent());
|
|
443 assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.I" type="I" key="0" id="0"`));
|
|
444 assert(archive.data().containsXmlTag("typedef", `type="Int" key="a"`));
|
|
445 assert(archive.data().containsXmlTag("int", `key="1"`, "1"));
|
|
446 };
|
|
447 };
|
|
448
|
|
449 describe("deserialize typedef") in {
|
|
450 it("should return a deserialized typedef equal to the original typedef") in {
|
|
451 auto iDeserialized = serializer.deserialize!(I)(archive.data);
|
|
452 assert(i.a == iDeserialized.a);
|
|
453 };
|
|
454 };
|
|
455
|
|
456 describe("serialize slices") in {
|
|
457 it("should return serialized slices") in {
|
|
458 serializer.reset();
|
|
459 serializer.serialize(j);
|
|
460
|
|
461 assert(archive.data().containsDefaultXmlContent());
|
|
462 assert(archive.data().containsXmlTag("object", `runtimeType="tests.Serializer.J" type="J" key="0" id="0"`));
|
|
463 assert(archive.data().containsXmlTag("string", `type="char" length="10" key="firstSource" id="1"`, "0123456789"));
|
|
464 assert(archive.data().containsXmlTag("slice", `key="firstSlice" offset="3" length="4"`, "1"));
|
|
465 assert(archive.data().containsXmlTag("slice", `key="secondSlice" offset="1" length="3"`, "4"));
|
|
466 assert(archive.data().containsXmlTag("string", `type="char" length="7" key="secondSource" id="4"`, "abcdefg"));
|
|
467 };
|
|
468 };
|
|
469
|
|
470 describe("deserialize slices") in {
|
|
471 jDeserialized = serializer.deserialize!(J)(archive.data);
|
|
472
|
|
473 it("should return deserialized strings equal to the original strings") in {
|
|
474 assert(j.firstSource == jDeserialized.firstSource);
|
|
475 assert(j.secondSource == jDeserialized.secondSource);
|
|
476 };
|
|
477
|
|
478 it("should return deserialized slices equal to the original slices") in {
|
|
479 assert(j.firstSlice == jDeserialized.firstSlice);
|
|
480 assert(j.secondSlice == jDeserialized.secondSlice);
|
|
481 };
|
|
482
|
|
483 it("the slices should be equal to a slice of the original sources") in {
|
|
484 assert(jDeserialized.firstSource[3 .. 7] == jDeserialized.firstSlice);
|
|
485 assert(jDeserialized.secondSource[1 .. 4] == jDeserialized.secondSlice);
|
|
486
|
|
487 assert(j.firstSource[3 .. 7] == jDeserialized.firstSlice);
|
|
488 assert(j.secondSource[1 .. 4] == jDeserialized.secondSlice);
|
|
489 };
|
|
490
|
|
491 it("the slices should be able to modify the sources") in {
|
|
492 jDeserialized.firstSlice[0] = 'a';
|
|
493 jDeserialized.secondSlice[0] = '0';
|
|
494
|
|
495 assert(jDeserialized.firstSource == "012a456789");
|
|
496 assert(jDeserialized.secondSource == "a0cdefg");
|
|
497 };
|
|
498 };
|
|
499
|
|
500 describe("associative array references") in {
|
|
501 it("should return ") in {
|
|
502 serializer.reset();
|
|
503 serializer.serialize(k);
|
|
504 println(archive.data);
|
|
505 };
|
|
506 };
|
|
507 };
|
|
508 } |