1 /* _________________________________________________________________________
2 *
3 * UTILIB: A utility library for developing portable C++ codes.
4 * Copyright (c) 2008 Sandia Corporation.
5 * This software is distributed under the BSD License.
6 * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7 * the U.S. Government retains certain rights in this software.
8 * For more information, see the README file in the top UTILIB directory.
9 * _________________________________________________________________________
10 */
11
12 #include <utilib/Serialize.h>
13
14 #include <utilib/BasicArray.h>
15 #include <utilib/NumArray.h>
16 #include <utilib/MixedIntVars.h>
17 #include <utilib/OStreamTee.h>
18
19 #include "CommonTestUtils.h"
20
21
22 // NB: we use #defines so that if a test fails, the reported line number
23 // is from the original TEST code, and not from the utility function
24 // code (the latter being very difficult to diagnose for large tests
25 // like test_pod_serializers).
26
27 #define TEST_POD_serial_transform(TYPE, VALUE, LEN) \
28 if ( true ) { \
29 SerialObject::elementList_t so_list; \
30 TYPE init = VALUE; \
31 \
32 /* serialize */ \
33 TS_ASSERT_EQUALS(serial_transform(so_list, init, true), 0); \
34 TS_ASSERT_EQUALS(so_list.size(), size_t(1)); \
35 \
36 /* verify serial POD */ \
37 SerialObject &so = so_list.front(); \
38 TS_ASSERT_EQUALS(Serializer().get_typeinfo(so.type), &typeid(TYPE)); \
39 TS_ASSERT(so.data.is_type(typeid(SerialPOD))); \
40 if ( ! POD_text_mode ) \
41 TS_ASSERT_EQUALS(so.data.expose<SerialPOD>().size(), LEN); \
42 \
43 /* deserialize */ \
44 TYPE final; \
45 TYPE test = VALUE; \
46 TS_ASSERT_EQUALS(serial_transform(so_list, final, false), 0); \
47 TS_ASSERT_EQUALS(final, test); \
48 } else static_cast<void>(0)
49
50 #define TEST_POD_serialize(TYPE, VALUE, LEN) \
51 if ( true ) { \
52 /* serialize */ \
53 TYPE init = VALUE; \
54 SerialObject so = Serialize(init, POD_text_mode); \
55 \
56 /* verify serial POD */ \
57 TS_ASSERT_EQUALS(Serializer().get_typeinfo(so.type), &typeid(TYPE)); \
58 TS_ASSERT(so.data.is_type(typeid(SerialPOD))); \
59 if ( ! POD_text_mode ) \
60 TS_ASSERT_EQUALS(so.data.expose<SerialPOD>().size(), LEN); \
61 \
62 /* deserialize */ \
63 TYPE final = Deserialize(so).expose<TYPE >(); \
64 TYPE test = VALUE; \
65 TS_ASSERT_EQUALS(final, test); \
66 } else static_cast<void>(0)
67
68
69 /// Composite test given type, value, and the expected serialized length
70 #define TEST_POD_LEN(TYPE, VALUE, LEN) \
71 if ( true ) { \
72 TEST_POD_serial_transform(TYPE, VALUE, LEN); \
73 TEST_POD_serialize(TYPE, VALUE, LEN); \
74 } else static_cast<void>(0)
75
76 #define TEST_POD(TYPE, VALUE) TEST_POD_LEN(TYPE, VALUE, sizeof(TYPE))
77
78
79 #define TEST_STL_serial_transform(TYPE, VALUE, ADAPTOR, CMP) \
80 if ( true ){ \
81 SerialObject::elementList_t so_list; \
82 TYPE init = VALUE; \
83 \
84 /* serialize */ \
85 TS_ASSERT_EQUALS(serial_transform(so_list, init, true), 0); \
86 TS_ASSERT_EQUALS(so_list.size(), size_t(1)); \
87 \
88 /* verify serialized STL */ \
89 SerialObject &so = so_list.front(); \
90 TS_ASSERT_EQUALS(Serializer().get_typeinfo(so.type), &typeid(TYPE)); \
91 TS_ASSERT(so.data.is_type(typeid(SerialObject::elementList_t))); \
92 const SerialObject::elementList_t &el = \
93 so.data.expose<SerialObject::elementList_t>(); \
94 if ( ADAPTOR ) \
95 { \
96 TS_ASSERT_EQUALS(el.size(), size_t(1)); \
97 TS_ASSERT( el.front().data.is_type \
98 (typeid(SerialObject::elementList_t)) ); \
99 TS_ASSERT_EQUALS( el.front().data.expose \
100 <SerialObject::elementList_t>().size(), \
101 VALUE.size() ); \
102 } \
103 else \
104 TS_ASSERT_EQUALS( el.size(), VALUE.size() ); \
105 \
106 /* deserialize */ \
107 TYPE final; \
108 TS_ASSERT_EQUALS(serial_transform(so_list, final, false), 0); \
109 CMP(final, VALUE); \
110 } else static_cast<void>(0)
111
112 #define TEST_STL_serialize(TYPE, VALUE, ADAPTOR, CMP) \
113 if ( true ) { \
114 /* serialize */ \
115 TYPE init = VALUE; \
116 SerialObject so = Serialize(init); \
117 \
118 /* verify serial POD */ \
119 TS_ASSERT_EQUALS(Serializer().get_typeinfo(so.type), &typeid(TYPE)); \
120 TS_ASSERT(so.data.is_type(typeid(SerialObject::elementList_t))); \
121 const SerialObject::elementList_t &el = \
122 so.data.expose<SerialObject::elementList_t>(); \
123 if ( ADAPTOR ) \
124 { \
125 TS_ASSERT_EQUALS(el.size(), size_t(1)); \
126 TS_ASSERT( el.front().data.is_type \
127 (typeid(SerialObject::elementList_t)) ); \
128 TS_ASSERT_EQUALS( el.front().data.expose \
129 <SerialObject::elementList_t>().size(), \
130 VALUE.size() ); \
131 } \
132 else \
133 TS_ASSERT_EQUALS( el.size(), VALUE.size() ); \
134 \
135 /* deserialize */ \
136 CMP(Deserialize(so).expose<TYPE >(), VALUE); \
137 } else static_cast<void>(0)
138
139
140 /// Composite test given type, value
141 #define TEST_STL(TYPE, VALUE, ADAPTOR, CMP) \
142 if ( true ) { \
143 TEST_STL_serial_transform(TYPE, VALUE, ADAPTOR, CMP); \
144 TEST_STL_serialize(TYPE, VALUE, ADAPTOR, CMP); \
145 } else static_cast<void>(0)
146
147 #define TEST_STL_driver_1(TYPE, A, B, C) \
148 if ( true ) { \
149 TYPE val; \
150 TEST_STL(TYPE, val, false, TS_ASSERT_EQUALS); \
151 \
152 val.insert(val.end(), A); \
153 val.insert(val.end(), B); \
154 val.insert(val.end(), C); \
155 TEST_STL(TYPE, val, false, TS_ASSERT_EQUALS); \
156 } else static_cast<void>(0)
157
158 #define TEST_STL_driver_2(TYPE, A, B, C, FCN, ADAPTOR) \
159 if ( true ) { \
160 TYPE val; \
161 TEST_STL(TYPE, val, ADAPTOR, TS_ASSERT_EQUALS); \
162 \
163 val.FCN(A); \
164 val.FCN(B); \
165 val.FCN(C); \
166 TEST_STL(TYPE, val, ADAPTOR, TS_ASSERT_EQUALS); \
167 } else static_cast<void>(0)
168
169
170
171 #define TEST_OBJ_serial_transform(TYPE, VALUE, CMP) \
172 if ( true ){ \
173 SerialObject::elementList_t so_list; \
174 TYPE init = VALUE; \
175 \
176 /* serialize */ \
177 TS_ASSERT_EQUALS(serial_transform(so_list, init, true), 0); \
178 TS_ASSERT_EQUALS(so_list.size(), size_t(1)); \
179 \
180 /* verify serialized OBJ */ \
181 SerialObject &so = so_list.front(); \
182 TS_ASSERT_EQUALS(Serializer().get_typeinfo(so.type), &typeid(TYPE)); \
183 TS_ASSERT(so.data.is_type(typeid(SerialObject::elementList_t))); \
184 \
185 /* deserialize */ \
186 TYPE final; \
187 TS_ASSERT_EQUALS(serial_transform(so_list, final, false), 0); \
188 CMP(final, VALUE); \
189 } else static_cast<void>(0)
190
191 #define TEST_OBJ_serialize(TYPE, VALUE, CMP) \
192 if ( true ) { \
193 /* serialize */ \
194 TYPE init = VALUE; \
195 SerialObject so = Serialize(init); \
196 \
197 /* verify serial POD */ \
198 TS_ASSERT_EQUALS(Serializer().get_typeinfo(so.type), &typeid(TYPE)); \
199 TS_ASSERT(so.data.is_type(typeid(SerialObject::elementList_t))); \
200 \
201 /* deserialize */ \
202 CMP(Deserialize(so).expose<TYPE >(), VALUE); \
203 } else static_cast<void>(0)
204
205
206 /// Composite test given type, value
207 #define TEST_OBJ(TYPE, VALUE) \
208 if ( true ) { \
209 TEST_OBJ_serial_transform(TYPE, VALUE, TS_ASSERT_EQUALS); \
210 TEST_OBJ_serialize(TYPE, VALUE, TS_ASSERT_EQUALS); \
211 } else static_cast<void>(0)
212
213
214 namespace {
215
216 template<typename T>
PQueue_Equals(std::priority_queue<T> a,std::priority_queue<T> b)217 void PQueue_Equals(std::priority_queue<T> a, std::priority_queue<T> b)
218 {
219 while ( ! a.empty() && ! b.empty() )
220 {
221 TS_ASSERT_EQUALS(a.top(), b.top());
222 a.pop();
223 b.pop();
224 }
225 TS_ASSERT(a.empty());
226 TS_ASSERT(b.empty());
227 }
228
NullInitializer(utilib::Any & data)229 void NullInitializer(utilib::Any& data)
230 { data.clear(); }
231
232 class UnknownClass {};
233
234 class AnotherClass {};
235
236 } // namespace (local)
237
238
239
240 namespace utilib {
241 namespace unittest { class Test_Serialize; }
242
243 class utilib::unittest::Test_Serialize : public CxxTest::TestSuite
244 {
245 public:
246
setUp()247 void setUp()
248 {
249 // As this TestSuite serializes and then deserializes data, it is
250 // important that a serialization failure terminates the test.
251 CxxTest::setAbortTestOnFail(true);
252 }
253
test_empty_any()254 void test_empty_any()
255 {
256 // This should serialize as 'void'
257 utilib::Any a;
258
259 /* test 1: serial_transform */
260 {
261 SerialObject::elementList_t so_list;
262 TS_ASSERT_EQUALS(serial_transform(so_list, a, true), 0);
263 TS_ASSERT_EQUALS(so_list.size(), size_t(1));
264
265 SerialObject &so = so_list.front();
266 TS_ASSERT_EQUALS(so.type, size_t(0));
267 TS_ASSERT(so.data.empty());
268
269 /* deserialize */
270 utilib::Any b = 1;
271 TS_ASSERT_EQUALS(serial_transform(so_list, b, false), 0);
272 TS_ASSERT(b.empty());
273 }
274
275 /* test 2: Serialize/Deserialize */
276 {
277 SerialObject so = Serialize(a);
278
279 // void is the only type that is strictly guaranteed a specific
280 // type number
281 TS_ASSERT_EQUALS(so.type, size_t(0));
282 TS_ASSERT(so.data.empty());
283
284 TS_ASSERT(Deserialize(so).empty());
285 }
286 }
287
288
289 /// Test all POD serializers [with both serial_transform() and
290 /// Serialize() / Deserialize() interfaces]
test_pod_serializers_1()291 void test_pod_serializers_1()
292 {
293 bool POD_text_mode = false;
294
295 TEST_POD(short, 0);
296 TEST_POD(short, 42);
297 TEST_POD(short, -21);
298
299 TEST_POD(signed short, 0);
300 TEST_POD(signed short, 42);
301 TEST_POD(signed short, -21);
302
303 TEST_POD(unsigned short, 0);
304 TEST_POD(unsigned short, 42);
305
306 TEST_POD(int, 0);
307 TEST_POD(int, 42);
308 TEST_POD(int, -21);
309 TEST_POD(int, INT_MAX);
310 TEST_POD(int, INT_MIN);
311
312 TEST_POD(signed int, 0);
313 TEST_POD(signed int, 42);
314 TEST_POD(signed int, -21);
315
316 TEST_POD(unsigned int, 0);
317 TEST_POD(unsigned int, 42);
318
319 TEST_POD(long, 0);
320 TEST_POD(long, 42);
321 TEST_POD(long, -21);
322 TEST_POD(long, LONG_MAX);
323 TEST_POD(long, LONG_MIN);
324
325 TEST_POD(signed long, 0);
326 TEST_POD(signed long, 42);
327 TEST_POD(signed long, -21);
328
329 TEST_POD(unsigned long, 0);
330 TEST_POD(unsigned long, 42);
331 }
332
test_pod_serializers_2()333 void test_pod_serializers_2()
334 {
335 bool POD_text_mode = false;
336
337 TEST_POD(float, 0);
338 TEST_POD(float, 3.1415f);
339
340 TEST_POD(double, 0);
341 TEST_POD(double, 3.1415);
342
343 TEST_POD(long double, 0);
344 TEST_POD(long double, 3.1415l);
345
346 TEST_POD(bool, true);
347 TEST_POD(bool, false);
348
349 TEST_POD(char, 'A');
350 TEST_POD(char, '\n');
351 TEST_POD(char, 127);
352
353 TEST_POD(signed char, 0);
354 TEST_POD(signed char, 42);
355 TEST_POD(signed char, -21);
356
357 TEST_POD(unsigned char, 0);
358 TEST_POD(unsigned char, 42);
359
360 TEST_POD(wchar_t, 'A');
361 TEST_POD(wchar_t, '\n');
362
363 TEST_POD_LEN(std::string, "", size_t(0));
364 TEST_POD_LEN(std::string, "hello, world", size_t(12));
365 }
366
367
368 /// Test all POD text serializers [with both serial_transform() and
369 /// Serialize() / Deserialize() interfaces]
test_pod_text_serializers_1()370 void test_pod_text_serializers_1()
371 {
372 bool POD_text_mode = true;
373
374 TEST_POD(short, 0);
375 TEST_POD(short, 42);
376 TEST_POD(short, -21);
377
378 TEST_POD(signed short, 0);
379 TEST_POD(signed short, 42);
380 TEST_POD(signed short, -21);
381
382 TEST_POD(unsigned short, 0);
383 TEST_POD(unsigned short, 42);
384
385 TEST_POD(int, 0);
386 TEST_POD(int, 42);
387 TEST_POD(int, -21);
388 TEST_POD(int, INT_MAX);
389 TEST_POD(int, INT_MIN);
390
391 TEST_POD(signed int, 0);
392 TEST_POD(signed int, 42);
393 TEST_POD(signed int, -21);
394
395 TEST_POD(unsigned int, 0);
396 TEST_POD(unsigned int, 42);
397
398 TEST_POD(long, 0);
399 TEST_POD(long, 42);
400 TEST_POD(long, -21);
401 TEST_POD(long, LONG_MAX);
402 TEST_POD(long, LONG_MIN);
403
404 TEST_POD(signed long, 0);
405 TEST_POD(signed long, 42);
406 TEST_POD(signed long, -21);
407
408 TEST_POD(unsigned long, 0);
409 TEST_POD(unsigned long, 42);
410 }
411
test_pod_text_serializers_2()412 void test_pod_text_serializers_2()
413 {
414 bool POD_text_mode = true;
415
416 TEST_POD(float, 0);
417 TEST_POD(float, 3.1415f);
418
419 TEST_POD(double, 0);
420 TEST_POD(double, 3.1415);
421
422 TEST_POD(long double, 0);
423 TEST_POD(long double, 3.1415l);
424
425 TEST_POD(bool, true);
426 TEST_POD(bool, false);
427
428 TEST_POD(char, 'A');
429 TEST_POD(char, '\n');
430 TEST_POD(char, 31);
431 TEST_POD(char, 32);
432 TEST_POD(char, 126);
433 TEST_POD(char, 127);
434
435 TEST_POD(signed char, 0);
436 TEST_POD(signed char, 42);
437 TEST_POD(signed char, -21);
438
439 TEST_POD(unsigned char, 0);
440 TEST_POD(unsigned char, 42);
441
442 TEST_POD(wchar_t, 'A');
443 TEST_POD(wchar_t, '\n');
444
445 TEST_POD(std::string, "");
446 TEST_POD(std::string, "hello, world");
447 }
448
449 /// Test all STL container serializers [with both serial_transform()
450 /// and Serialize() / Deserialize() interfaces]
test_stl_serializers_1()451 void test_stl_serializers_1()
452 {
453 // basic containers
454 TEST_STL_driver_1(std::vector<int>, 0, 42, 21);
455 TEST_STL_driver_1(std::list<int>, 0, 42, 21);
456
457 // associative containers
458 TEST_STL_driver_1(std::set<int>, 0, 42, 21);
459 TEST_STL_driver_1(std::multiset<int>, 0, 42, 21);
460 TEST_STL_driver_1(std::multiset<int>, 0, 42, 0);
461
462 typedef std::map<int, int> map_t;
463 typedef std::multimap<int, int> multimap_t;
464 typedef std::pair<const int, int> p_t;
465 TEST_STL_driver_1( map_t, p_t(0,1), p_t(42, 43), p_t(21,20) );
466 TEST_STL_driver_1( multimap_t, p_t(0,1), p_t(42, 43), p_t(21,20) );
467 TEST_STL_driver_1( multimap_t, p_t(0,1), p_t(0, 43), p_t(0,20) );
468 }
469
test_stl_serializers_3()470 void test_stl_serializers_3()
471 {
472 // special sequence containers
473 TEST_STL_driver_2(std::deque<int>, 0, 42, 21, push_back, false);
474 TEST_STL_driver_2(std::queue<int>, 0, 42, 21, push, true);
475 TEST_STL_driver_2(std::stack<int>, 0, 42, 21, push, true);
476
477 // priority_queue doesn't support operator==, so we have to do
478 // this by hand
479 {
480 std::priority_queue<int> val;
481 TEST_STL(std::priority_queue<int>, val, true, PQueue_Equals);
482
483 val.push(0);
484 val.push(42);
485 val.push(21);
486 TEST_STL(std::priority_queue<int>, val, true, PQueue_Equals);
487 }
488
489 // test a complex container
490 {
491 typedef std::map<std::pair<int, double>, std::vector<double> >
492 complex_t;
493 complex_t val;
494 TEST_STL(complex_t, val, false, TS_ASSERT_EQUALS);
495 val[std::make_pair(0, 2)];
496 val[std::make_pair(0, 3)].push_back(1);
497 val[std::make_pair(0, 3)].push_back(10);
498 val[std::make_pair(0, 3)].push_back(5);
499 TEST_STL(complex_t, val, false, TS_ASSERT_EQUALS);
500 }
501 }
502
test_utilib_adt()503 void test_utilib_adt()
504 {
505 utilib::Ereal<float> er = 5;
506 TEST_OBJ(utilib::Ereal<float>, er);
507 er = utilib::Ereal<float>::positive_infinity;
508 TEST_OBJ(utilib::Ereal<float>, er);
509
510 utilib::BasicArray<double> ba;
511 TEST_OBJ(utilib::BasicArray<double>, ba);
512 ba.push_back(1.1);
513 ba.push_back(2.2);
514 ba.push_back(3.3);
515 TEST_OBJ(utilib::BasicArray<double>, ba);
516
517 utilib::NumArray<int> na;
518 TEST_OBJ(utilib::NumArray<int>, na);
519 na.push_back(3);
520 na.push_back(5);
521 na.push_back(7);
522 TEST_OBJ(utilib::NumArray<int>, na);
523
524 utilib::MixedIntVars miv;
525 TEST_OBJ(utilib::MixedIntVars, miv);
526 miv.Binary().resize(3);
527 miv.Binary().set(1);
528 miv.Integer().push_back(3);
529 miv.Integer().push_back(5);
530 miv.Integer().push_back(7);
531 miv.Real().push_back(3.1415);
532 miv.Real().push_back(42);
533 TEST_OBJ(utilib::MixedIntVars, miv);
534 }
535
536
test_print()537 void test_print()
538 {
539 std::stringstream ss;
540
541 /*
542 * A simple POD
543 */
544 int i = 5;
545 Serialize(i, false).print(ss);
546 if ( utilib::Serialization_Manager::Endian == 0xE4 )
547 {
548 TS_ASSERT_EQUALS(ss.str(), "type = int\n POD: 4: 5 0 0 0\n");
549 }
550 else if ( utilib::Serialization_Manager::Endian == 0x1B )
551 {
552 TS_ASSERT_EQUALS(ss.str(), "type = int\n POD: 4: 0 0 0 5\n");
553 }
554 else
555 TS_FAIL("Unrecognized endianness");
556
557 ss.str("");
558 Serialize(i, true).print(ss);
559 TS_ASSERT_EQUALS(ss.str(), "type = int: 5\n");
560
561 /*
562 * A simple STL container
563 */
564
565 std::list<int> l;
566 ss.str("");
567 Serialize(l, false).print(ss);
568 TS_ASSERT_EQUALS(ss.str(), "type = std::list<int,*>\n");
569
570 ss.str("");
571 Serialize(l, true).print(ss);
572 TS_ASSERT_EQUALS(ss.str(), "type = std::list<int,*>\n");
573
574 l.push_back(5);
575 l.push_back(10);
576
577 ss.str("");
578 Serialize(l, false).print(ss);
579 if ( utilib::Serialization_Manager::Endian == 0xE4 )
580 {
581 TS_ASSERT_EQUALS(ss.str(), "type = std::list<int,*>\n"
582 " type = int\n POD: 4: 5 0 0 0\n"
583 " type = int\n POD: 4: 10 0 0 0\n");
584 }
585 else if ( utilib::Serialization_Manager::Endian == 0x1B )
586 {
587 TS_ASSERT_EQUALS(ss.str(), "type = std::list<int,*>\n"
588 " type = int\n POD: 4: 0 0 0 5\n"
589 " type = int\n POD: 4: 0 0 0 10\n");
590 }
591 else
592 TS_FAIL("Unrecognized endianness");
593
594 ss.str("");
595 Serialize(l, true).print(ss);
596 TS_ASSERT_EQUALS( ss.str(), "type = std::list<int,*>\n"
597 " type = int: 5\n type = int: 10\n" );
598
599 /*
600 * A complex STL container
601 */
602
603 std::map<std::pair<int,double>, std::string> cdt;
604 ss.str("");
605 Serialize(cdt, false).print(ss);
606 TS_ASSERT_EQUALS(ss.str(), "type = std::map<std::pair<int,double>,"
607 "std::string,*,*>\n");
608
609 ss.str("");
610 Serialize(cdt, true).print(ss);
611 TS_ASSERT_EQUALS(ss.str(), "type = std::map<std::pair<int,double>,"
612 "std::string,*,*>\n");
613
614 cdt[std::make_pair(1, 5)] = "";
615 cdt[std::make_pair(3, 3.14)] = "hello";
616
617 ss.str("");
618 Serialize(cdt, true).print(ss);
619 TS_ASSERT_EQUALS
620 (ss.str(),
621 "type = std::map<std::pair<int,double>,std::string,*,*>\n"
622 " type = std::pair<std::pair<int,double>,std::string>\n"
623 " type = std::pair<int,double>\n"
624 " type = int: 1\n"
625 " type = double: 5\n"
626 " type = std::string: \"\"\n"
627 " type = std::pair<std::pair<int,double>,std::string>\n"
628 " type = std::pair<int,double>\n"
629 " type = int: 3\n"
630 " type = double: 3.1400000000000001\n"
631 " type = std::string: \"hello\"\n");
632
633 /*
634 * A character
635 */
636 char c = 'A';
637 ss.str("");
638 Serialize(c, false).print(ss);
639 TS_ASSERT_EQUALS(ss.str(), "type = char\n POD: 1: 65\n");
640
641 ss.str("");
642 Serialize(c, true).print(ss);
643 TS_ASSERT_EQUALS(ss.str(), "type = char: 'A'\n");
644
645 c = ' ';
646 ss.str("");
647 Serialize(c, false).print(ss);
648 TS_ASSERT_EQUALS(ss.str(), "type = char\n POD: 1: 32\n");
649
650 ss.str("");
651 Serialize(c, true).print(ss);
652 TS_ASSERT_EQUALS(ss.str(), "type = char: ' '\n");
653
654 c = 31;
655 ss.str("");
656 Serialize(c, false).print(ss);
657 TS_ASSERT_EQUALS(ss.str(), "type = char\n POD: 1: 31\n");
658
659 ss.str("");
660 Serialize(c, true).print(ss);
661 TS_ASSERT_EQUALS(ss.str(), "type = char: 31\n");
662
663 c = '~';
664 ss.str("");
665 Serialize(c, false).print(ss);
666 TS_ASSERT_EQUALS(ss.str(), "type = char\n POD: 1: 126\n");
667
668 ss.str("");
669 Serialize(c, true).print(ss);
670 TS_ASSERT_EQUALS(ss.str(), "type = char: '~'\n");
671
672 c = 127;
673 ss.str("");
674 Serialize(c, false).print(ss);
675 TS_ASSERT_EQUALS(ss.str(), "type = char\n POD: 1: 127\n");
676
677 ss.str("");
678 Serialize(c, true).print(ss);
679 TS_ASSERT_EQUALS(ss.str(), "type = char: 127\n");
680
681 ss.str("");
682 SerialObject so = Serialize(int(1));
683 so.data = utilib::Any();
684 so.print(ss);
685 std::string ref = "type = int\n UNKNOWN DATA! ("
686 + utilib::demangledName(typeid(void)) + ")\n";
687 TS_ASSERT_EQUALS(ss.str(), ref);
688 }
689
690
test_typeRegistry()691 void test_typeRegistry()
692 {
693 // check for simple int
694 size_t int_key = Serializer().get_keyid("int");
695 TS_ASSERT_EQUALS(int_key, Serializer().get_keyid(typeid(int)));
696 TS_ASSERT_EQUALS("int", Serializer().get_username(int_key));
697 TS_ASSERT(Serializer().is_pod(int_key));
698 TS_ASSERT_EQUALS(Serializer().get_pod_length(int_key), (int)sizeof(int));
699 TS_ASSERT_EQUALS(Serializer().get_typeinfo(int_key), &typeid(int));
700
701 // check for complex type
702 typedef std::map<int,double> cdt_t;
703 // declare & use the variable so it gets registered...
704 cdt_t foo;
705 Serialize(foo);
706
707 std::string cdt_name = "std::map<int,double,*,*>";
708 size_t cdt_key = Serializer().get_keyid(typeid(cdt_t));
709 TS_ASSERT_EQUALS( cdt_name, Serializer().get_username(cdt_key) );
710 TS_ASSERT_EQUALS(cdt_key, Serializer().get_keyid(cdt_name));
711 TS_ASSERT(! Serializer().is_pod(cdt_key));
712 TS_ASSERT_EQUALS(Serializer().get_pod_length(cdt_key), -1);
713 TS_ASSERT_EQUALS(Serializer().get_typeinfo(cdt_key), &typeid(cdt_t));
714
715 // check for unknown type
716 typedef UnknownClass u_t;
717 std::string u_name = "UnknownClass";
718 size_t u_key = 1000000;
719 TS_ASSERT_THROWS_ASSERT
720 ( Serializer().get_keyid(typeid(u_t)),
721 utilib::serializer_unknown_type &e,
722 TEST_WHAT(e, "Serialization_Manager::get_keyid(): "
723 "unknown type_info name, \"") );
724 TS_ASSERT_EQUALS(Serializer().get_username(u_key), "");
725 TS_ASSERT_THROWS_ASSERT
726 ( Serializer().get_keyid(u_name),
727 utilib::serializer_unknown_type &e,
728 TEST_WHAT(e, "Serialization_Manager::get_keyid(): "
729 "unknown user-defined type name, \"UnknownClass\"") );
730 TS_ASSERT(! Serializer().is_pod(u_key));
731 TS_ASSERT_EQUALS(Serializer().get_pod_length(u_key), -1);
732 TS_ASSERT( ! Serializer().get_typeinfo(u_key) );
733 }
734
735
test_listSerializers()736 void test_listSerializers()
737 {
738 utilib::Serialization_Manager sm;
739 std::stringstream ss;
740 sm.list_serializers(ss);
741
742 // we need to strip out all the mangled names, as those can change
743 // across compilers/platforms.
744 std::string list = ss.str();
745 size_t start;
746 while ( (start = list.find("[ ")) != std::string::npos )
747 list.erase(start+1, list.find(" ]") - start);
748
749 TS_ASSERT_EQUALS(list, std::string("Known serializers:\n"
750 " bool []\n"
751 " char []\n"
752 " double []\n"
753 " float []\n"
754 " int []\n"
755 " long []\n"
756 " long double []\n"
757 " short []\n"
758 " signed char []\n"
759 " std::string []\n"
760 " unsigned char []\n"
761 " unsigned int []\n"
762 " unsigned long []\n"
763 " unsigned short []\n"
764 " void []\n"
765 " wchar_t []\n"));
766 }
767
768
test_POD_serializer_errors()769 void test_POD_serializer_errors()
770 {
771 SerialObject::elementList_t so_list;
772 char c = 0;
773 utilib::Any a;
774
775 /*
776 * int
777 */
778 SerialObject so = Serialize(5);
779
780 // make sure that the text serializer correctly handles whitespace
781 so.data.expose<SerialPOD>().set(std::string(" 2 "));
782 TS_ASSERT_EQUALS(Deserialize(so).expose<int>(), 2);
783
784 // change the size of the int
785 so.data.expose<SerialPOD>().set(&c, sizeof(char));
786 TS_ASSERT_THROWS_ASSERT
787 ( Deserialize(so), utilib::serializer_bad_pod_size &e,
788 TEST_WHAT(e, "POD_serializer(): "
789 "SerialPOD data size does not match destination type") );
790
791 // change the int to text mode with an invalid string
792 so.data.expose<SerialPOD>().set(std::string("a"));
793 so_list.push_back(so);
794 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
795 utilib::error::Serialization::BadPODTextConversion);
796 TS_ASSERT_THROWS_ASSERT
797 ( Deserialize(so), utilib::serialization_error &e,
798 TEST_WHAT(e, "Serialization_Manager::Deserialize()"
799 ": Deserialization failed for '") );
800
801 so.data.expose<SerialPOD>().set(std::string("1.5"));
802 so_list.push_back(so);
803 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
804 utilib::error::Serialization::UnconvertedPODText);
805 a.clear();
806 TS_ASSERT_THROWS_ASSERT
807 ( Deserialize(so), utilib::serialization_error &e,
808 TEST_WHAT(e, "Serialization_Manager::Deserialize()"
809 ": Deserialization failed for '") );
810
811 /*
812 * float
813 */
814
815 so = Serialize(3.14f);
816
817 so.data.expose<SerialPOD>().set(std::string(" 2.718 "));
818 TS_ASSERT_EQUALS(Deserialize(so).expose<float>(), 2.718f);
819
820 so.data.expose<SerialPOD>().set(std::string("a"));
821 so_list.push_back(so);
822 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
823 utilib::error::Serialization::BadPODTextConversion);
824 TS_ASSERT_THROWS_ASSERT
825 ( Deserialize(so), utilib::serialization_error &e,
826 TEST_WHAT(e, "Serialization_Manager::Deserialize()"
827 ": Deserialization failed for '") );
828
829 so.data.expose<SerialPOD>().set(std::string("1.5b"));
830 so_list.push_back(so);
831 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
832 utilib::error::Serialization::UnconvertedPODText);
833 a.clear();
834 TS_ASSERT_THROWS_ASSERT
835 ( Deserialize(so), utilib::serialization_error &e,
836 TEST_WHAT(e, "Serialization_Manager::Deserialize()"
837 ": Deserialization failed for '") );
838
839 /*
840 * double
841 */
842
843 so = Serialize(3.14);
844
845 so.data.expose<SerialPOD>().set(std::string(" 2.718 "));
846 TS_ASSERT_EQUALS(Deserialize(so).expose<double>(), 2.718);
847
848 so.data.expose<SerialPOD>().set(std::string("a"));
849 so_list.push_back(so);
850 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
851 utilib::error::Serialization::BadPODTextConversion);
852 TS_ASSERT_THROWS_ASSERT
853 ( Deserialize(so), utilib::serialization_error &e,
854 TEST_WHAT(e, "Serialization_Manager::Deserialize()"
855 ": Deserialization failed for '") );
856
857 so.data.expose<SerialPOD>().set(std::string("1.5b"));
858 so_list.push_back(so);
859 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
860 utilib::error::Serialization::UnconvertedPODText);
861 a.clear();
862 TS_ASSERT_THROWS_ASSERT
863 ( Deserialize(so), utilib::serialization_error &e,
864 TEST_WHAT(e, "Serialization_Manager::Deserialize()"
865 ": Deserialization failed for '") );
866
867 /*
868 * long double
869 */
870
871 so = Serialize(3.14l);
872
873 so.data.expose<SerialPOD>().set(std::string(" 2.718 "));
874 TS_ASSERT_EQUALS(Deserialize(so).expose<long double>(), 2.718l);
875
876 so.data.expose<SerialPOD>().set(std::string("a"));
877 so_list.push_back(so);
878 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
879 utilib::error::Serialization::BadPODTextConversion);
880 TS_ASSERT_THROWS_ASSERT
881 ( Deserialize(so), utilib::serialization_error &e,
882 TEST_WHAT(e, "Serialization_Manager::Deserialize()"
883 ": Deserialization failed for '") );
884
885 so.data.expose<SerialPOD>().set(std::string("1.5b"));
886 so_list.push_back(so);
887 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
888 utilib::error::Serialization::UnconvertedPODText);
889 a.clear();
890 TS_ASSERT_THROWS_ASSERT
891 ( Deserialize(so), utilib::serialization_error &e,
892 TEST_WHAT(e, "Serialization_Manager::Deserialize()"
893 ": Deserialization failed for '") );
894
895
896 /*
897 * std::string
898 */
899 so = Serialize(std::string(""));
900
901 so.data.expose<SerialPOD>().set(std::string());
902 so_list.push_back(so);
903 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
904 utilib::error::Serialization::MissingStringQuote);
905 a.clear();
906
907 so.data.expose<SerialPOD>().set(std::string("A"));
908 so_list.push_back(so);
909 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
910 utilib::error::Serialization::MissingStringQuote);
911 a.clear();
912
913 so.data.expose<SerialPOD>().set(std::string("\""));
914 so_list.push_back(so);
915 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
916 utilib::error::Serialization::MissingStringQuote);
917 a.clear();
918
919 so.data.expose<SerialPOD>().set(std::string("\"a"));
920 so_list.push_back(so);
921 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
922 utilib::error::Serialization::MissingStringQuote);
923 a.clear();
924
925 /*
926 * char
927 */
928
929 so = Serialize('a');
930
931 so.data.expose<SerialPOD>().set(std::string());
932 so_list.push_back(so);
933 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
934 utilib::error::Serialization::BadPODData);
935 a.clear();
936
937 so.data.expose<SerialPOD>().set(std::string("'A"));
938 so_list.push_back(so);
939 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
940 utilib::error::Serialization::BadPODData);
941 a.clear();
942
943 so.data.expose<SerialPOD>().set(std::string("'Ab"));
944 so_list.push_back(so);
945 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
946 utilib::error::Serialization::BadPODData);
947 a.clear();
948
949 so.data.expose<SerialPOD>().set(std::string("257"));
950 so_list.push_back(so);
951 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
952 utilib::error::Serialization::BadPODTextConversion);
953 a.clear();
954
955 so.data.expose<SerialPOD>().set(std::string("\"a\""));
956 so_list.push_back(so);
957 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
958 utilib::error::Serialization::BadPODTextConversion);
959 a.clear();
960
961 so.data.expose<SerialPOD>().set(std::string("32a"));
962 so_list.push_back(so);
963 TS_ASSERT_EQUALS(serial_transform(so_list, a, false),
964 utilib::error::Serialization::UnconvertedPODText);
965 a.clear();
966 }
967
test_serialization_errors()968 void test_serialization_errors()
969 {
970 // This is going to work with a non-global serializer, so we will
971 // bypass the normal Serialize(), Deserialize(), and
972 // serial_transform functions...
973
974 utilib::Serialization_Manager sm;
975 SerialObject::elementList_t so_list;
976
977 // Attempt to serialize an unregistered class
978 UnknownClass uc;
979 utilib::AnyFixedRef data = uc;
980 TS_ASSERT_THROWS_ASSERT
981 ( sm.transform_impl(data.type(), so_list, data, true),
982 utilib::serializer_unknown_type &e,
983 TEST_WHAT(e, "Serialization_Manager::transform_impl(): "
984 "cannot serialize unknown type '") );
985
986 // Attempt to deserialize an empty list
987 TS_ASSERT_THROWS_ASSERT
988 ( sm.transform_impl(data.type(), so_list, data, false),
989 utilib::serialization_error &e,
990 TEST_WHAT(e, "Serialization_Manager::transform_impl(): "
991 "SerialObject missing required element.") );
992
993
994 // Register a completely bogus serialization
995 sm.register_serializer<UnknownClass>( "MyClass", NULL, NULL, -1, NULL );
996
997 // Still cannot serialize
998 TS_ASSERT_THROWS_ASSERT
999 ( sm.transform_impl(data.type(), so_list, data, true),
1000 utilib::serialization_error &e,
1001 TEST_WHAT(e, "Serialization_Manager::transform_impl(): "
1002 "NULL serialization function for type ") );
1003 // ...nor deserialize
1004 TS_ASSERT_THROWS_ASSERT
1005 ( sm.transform_impl(data.type(), so_list, data, false),
1006 utilib::serialization_error &e,
1007 TEST_WHAT(e, "Serialization_Manager::transform_impl(): "
1008 "NULL initialization function for id ") );
1009
1010 // try to re-register with a valid initializer...
1011 utilib::OStreamTee tee(std::cerr);
1012 std::stringstream ref;
1013 ref << "WARNING: Serialization_Manager::register_serializer(): "
1014 "discarding duplicate registration for '" <<
1015 utilib::mangledName(typeid(UnknownClass)) << "'" << std::endl;
1016 TS_ASSERT_EQUALS( sm.register_serializer<UnknownClass>
1017 ( "MyClass", NULL, &NullInitializer ),
1018 utilib::error::Serialization::DuplicateRegistration );
1019 TS_ASSERT_EQUALS(tee.out.str(), ref.str())
1020
1021 // OK, how about an invalid initializer?
1022 sm = utilib::Serialization_Manager();
1023 sm.register_serializer<UnknownClass>
1024 ( "MyClass", NULL, &NullInitializer );
1025
1026 // ...still can't deserialize
1027 tee.out.str("");
1028 ref.str("");
1029 ref << "WARNING: Serialization_Manager::transform_impl(): initialization function for " <<
1030 utilib::mangledName(typeid(UnknownClass)) << " resulted in an empty Any." << std::endl << " This will likely cause random segmentation faults." << std::endl;
1031 TS_ASSERT_THROWS_ASSERT
1032 ( sm.transform_impl(data.type(), so_list, data, false),
1033 utilib::serialization_error &e,
1034 TEST_WHAT(e, "Serialization_Manager::transform_impl(): "
1035 "NULL deserialization function for id ") );
1036 TS_ASSERT_EQUALS(tee.out.str(), ref.str())
1037
1038 // OK, how about a reasonable initializer?
1039 sm = utilib::Serialization_Manager();
1040 sm.register_serializer<UnknownClass>
1041 ( "MyClass", NULL,
1042 &utilib::Serialization_Manager::DefaultInitializer<UnknownClass> );
1043
1044 // ...still can't deserialize
1045 TS_ASSERT_THROWS_ASSERT
1046 ( sm.transform_impl(data.type(), so_list, data, false),
1047 utilib::serialization_error &e,
1048 TEST_WHAT(e, "Serialization_Manager::transform_impl(): "
1049 "NULL deserialization function for id ") );
1050
1051 // what about conflicting usernames?
1052 sm.register_serializer<AnotherClass>
1053 ( "MyClass", NULL,
1054 &utilib::Serialization_Manager::DefaultInitializer<UnknownClass> );
1055
1056 tee.out.str("");
1057 ref.str("");
1058 ref << "WARNING: Serialization_Manager::resolve_user_name(): "
1059 << std::endl << " Multiple mangled type names map to the same "
1060 "user-defined name. It is" << std::endl << " likely that you "
1061 "forgot to register a name or a serialization function" << std::endl
1062 << " for a template argument. If you attempt to serialize "
1063 "either type," << std::endl << " you will get an exception."
1064 << std::endl << " User name: MyClass" << std::endl << " Mangled: "
1065 << utilib::mangledName(typeid(UnknownClass)) << std::endl <<
1066 " "
1067 << utilib::mangledName(typeid(AnotherClass)) << std::endl;
1068
1069 TS_ASSERT_THROWS_ASSERT
1070 ( sm.get_keyid("MyClass"), utilib::serializer_unknown_type &e,
1071 TEST_WHAT(e, "Serialization_Manager::get_keyid(): "
1072 "user-defined type name, \"MyClass\" "
1073 "maps to multiple types") );
1074 TS_ASSERT_EQUALS(tee.out.str(), ref.str())
1075
1076 TS_ASSERT_THROWS_ASSERT
1077 ( sm.transform_impl(data.type(), so_list, data, true),
1078 utilib::serialization_error &e,
1079 TEST_WHAT(e, "Serialization_Manager::transform_impl(): attempt "
1080 "to serialize an object with a nonunique username."));
1081
1082 TS_ASSERT_THROWS_ASSERT
1083 ( sm.transform_impl(data.type(), so_list, data, false),
1084 utilib::serialization_error &e,
1085 TEST_WHAT(e, "Serialization_Manager::transform_impl(): attempt "
1086 "to deserialize an object with a nonunique username."));
1087
1088 // create an invalid type id
1089 so_list.front().type+=2;
1090 TS_ASSERT_THROWS_ASSERT
1091 ( sm.transform_impl(data.type(), so_list, data, false),
1092 utilib::serialization_error &e,
1093 TEST_WHAT(e, "Serialization_Manager::transform_impl(): "
1094 "SerialObject contains unknown type id.") );
1095 }
1096 };
1097
1098 } // namespace utilib
1099