These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / tests / test-visitor-serialization.c
1 /*
2  * Unit-tests for visitor-based serialization
3  *
4  * Copyright (C) 2014-2015 Red Hat, Inc.
5  * Copyright IBM, Corp. 2012
6  *
7  * Authors:
8  *  Michael Roth <mdroth@linux.vnet.ibm.com>
9  *
10  * This work is licensed under the terms of the GNU GPL, version 2 or later.
11  * See the COPYING file in the top-level directory.
12  */
13
14 #include "qemu/osdep.h"
15 #include <glib.h>
16 #include <float.h>
17
18 #include "qemu-common.h"
19 #include "test-qapi-types.h"
20 #include "test-qapi-visit.h"
21 #include "qapi/error.h"
22 #include "qapi/qmp/types.h"
23 #include "qapi/qmp-input-visitor.h"
24 #include "qapi/qmp-output-visitor.h"
25 #include "qapi/string-input-visitor.h"
26 #include "qapi/string-output-visitor.h"
27 #include "qapi-types.h"
28 #include "qapi-visit.h"
29 #include "qapi/dealloc-visitor.h"
30
31 enum PrimitiveTypeKind {
32     PTYPE_STRING = 0,
33     PTYPE_BOOLEAN,
34     PTYPE_NUMBER,
35     PTYPE_INTEGER,
36     PTYPE_U8,
37     PTYPE_U16,
38     PTYPE_U32,
39     PTYPE_U64,
40     PTYPE_S8,
41     PTYPE_S16,
42     PTYPE_S32,
43     PTYPE_S64,
44     PTYPE_EOL,
45 };
46
47 typedef struct PrimitiveType {
48     union {
49         const char *string;
50         bool boolean;
51         double number;
52         int64_t integer;
53         uint8_t u8;
54         uint16_t u16;
55         uint32_t u32;
56         uint64_t u64;
57         int8_t s8;
58         int16_t s16;
59         int32_t s32;
60         int64_t s64;
61         intmax_t max;
62     } value;
63     enum PrimitiveTypeKind type;
64     const char *description;
65 } PrimitiveType;
66
67 typedef struct PrimitiveList {
68     union {
69         strList *strings;
70         boolList *booleans;
71         numberList *numbers;
72         intList *integers;
73         int8List *s8_integers;
74         int16List *s16_integers;
75         int32List *s32_integers;
76         int64List *s64_integers;
77         uint8List *u8_integers;
78         uint16List *u16_integers;
79         uint32List *u32_integers;
80         uint64List *u64_integers;
81     } value;
82     enum PrimitiveTypeKind type;
83     const char *description;
84 } PrimitiveList;
85
86 /* test helpers */
87
88 typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
89
90 static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp)
91 {
92     QapiDeallocVisitor *qdv = qapi_dealloc_visitor_new();
93
94     visit(qapi_dealloc_get_visitor(qdv), &native_in, errp);
95
96     qapi_dealloc_visitor_cleanup(qdv);
97 }
98
99 static void visit_primitive_type(Visitor *v, void **native, Error **errp)
100 {
101     PrimitiveType *pt = *native;
102     switch(pt->type) {
103     case PTYPE_STRING:
104         visit_type_str(v, NULL, (char **)&pt->value.string, errp);
105         break;
106     case PTYPE_BOOLEAN:
107         visit_type_bool(v, NULL, &pt->value.boolean, errp);
108         break;
109     case PTYPE_NUMBER:
110         visit_type_number(v, NULL, &pt->value.number, errp);
111         break;
112     case PTYPE_INTEGER:
113         visit_type_int(v, NULL, &pt->value.integer, errp);
114         break;
115     case PTYPE_U8:
116         visit_type_uint8(v, NULL, &pt->value.u8, errp);
117         break;
118     case PTYPE_U16:
119         visit_type_uint16(v, NULL, &pt->value.u16, errp);
120         break;
121     case PTYPE_U32:
122         visit_type_uint32(v, NULL, &pt->value.u32, errp);
123         break;
124     case PTYPE_U64:
125         visit_type_uint64(v, NULL, &pt->value.u64, errp);
126         break;
127     case PTYPE_S8:
128         visit_type_int8(v, NULL, &pt->value.s8, errp);
129         break;
130     case PTYPE_S16:
131         visit_type_int16(v, NULL, &pt->value.s16, errp);
132         break;
133     case PTYPE_S32:
134         visit_type_int32(v, NULL, &pt->value.s32, errp);
135         break;
136     case PTYPE_S64:
137         visit_type_int64(v, NULL, &pt->value.s64, errp);
138         break;
139     case PTYPE_EOL:
140         g_assert_not_reached();
141     }
142 }
143
144 static void visit_primitive_list(Visitor *v, void **native, Error **errp)
145 {
146     PrimitiveList *pl = *native;
147     switch (pl->type) {
148     case PTYPE_STRING:
149         visit_type_strList(v, NULL, &pl->value.strings, errp);
150         break;
151     case PTYPE_BOOLEAN:
152         visit_type_boolList(v, NULL, &pl->value.booleans, errp);
153         break;
154     case PTYPE_NUMBER:
155         visit_type_numberList(v, NULL, &pl->value.numbers, errp);
156         break;
157     case PTYPE_INTEGER:
158         visit_type_intList(v, NULL, &pl->value.integers, errp);
159         break;
160     case PTYPE_S8:
161         visit_type_int8List(v, NULL, &pl->value.s8_integers, errp);
162         break;
163     case PTYPE_S16:
164         visit_type_int16List(v, NULL, &pl->value.s16_integers, errp);
165         break;
166     case PTYPE_S32:
167         visit_type_int32List(v, NULL, &pl->value.s32_integers, errp);
168         break;
169     case PTYPE_S64:
170         visit_type_int64List(v, NULL, &pl->value.s64_integers, errp);
171         break;
172     case PTYPE_U8:
173         visit_type_uint8List(v, NULL, &pl->value.u8_integers, errp);
174         break;
175     case PTYPE_U16:
176         visit_type_uint16List(v, NULL, &pl->value.u16_integers, errp);
177         break;
178     case PTYPE_U32:
179         visit_type_uint32List(v, NULL, &pl->value.u32_integers, errp);
180         break;
181     case PTYPE_U64:
182         visit_type_uint64List(v, NULL, &pl->value.u64_integers, errp);
183         break;
184     default:
185         g_assert_not_reached();
186     }
187 }
188
189
190 static TestStruct *struct_create(void)
191 {
192     TestStruct *ts = g_malloc0(sizeof(*ts));
193     ts->integer = -42;
194     ts->boolean = true;
195     ts->string = strdup("test string");
196     return ts;
197 }
198
199 static void struct_compare(TestStruct *ts1, TestStruct *ts2)
200 {
201     g_assert(ts1);
202     g_assert(ts2);
203     g_assert_cmpint(ts1->integer, ==, ts2->integer);
204     g_assert(ts1->boolean == ts2->boolean);
205     g_assert_cmpstr(ts1->string, ==, ts2->string);
206 }
207
208 static void struct_cleanup(TestStruct *ts)
209 {
210     g_free(ts->string);
211     g_free(ts);
212 }
213
214 static void visit_struct(Visitor *v, void **native, Error **errp)
215 {
216     visit_type_TestStruct(v, NULL, (TestStruct **)native, errp);
217 }
218
219 static UserDefTwo *nested_struct_create(void)
220 {
221     UserDefTwo *udnp = g_malloc0(sizeof(*udnp));
222     udnp->string0 = strdup("test_string0");
223     udnp->dict1 = g_malloc0(sizeof(*udnp->dict1));
224     udnp->dict1->string1 = strdup("test_string1");
225     udnp->dict1->dict2 = g_malloc0(sizeof(*udnp->dict1->dict2));
226     udnp->dict1->dict2->userdef = g_new0(UserDefOne, 1);
227     udnp->dict1->dict2->userdef->integer = 42;
228     udnp->dict1->dict2->userdef->string = strdup("test_string");
229     udnp->dict1->dict2->string = strdup("test_string2");
230     udnp->dict1->dict3 = g_malloc0(sizeof(*udnp->dict1->dict3));
231     udnp->dict1->has_dict3 = true;
232     udnp->dict1->dict3->userdef = g_new0(UserDefOne, 1);
233     udnp->dict1->dict3->userdef->integer = 43;
234     udnp->dict1->dict3->userdef->string = strdup("test_string");
235     udnp->dict1->dict3->string = strdup("test_string3");
236     return udnp;
237 }
238
239 static void nested_struct_compare(UserDefTwo *udnp1, UserDefTwo *udnp2)
240 {
241     g_assert(udnp1);
242     g_assert(udnp2);
243     g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
244     g_assert_cmpstr(udnp1->dict1->string1, ==, udnp2->dict1->string1);
245     g_assert_cmpint(udnp1->dict1->dict2->userdef->integer, ==,
246                     udnp2->dict1->dict2->userdef->integer);
247     g_assert_cmpstr(udnp1->dict1->dict2->userdef->string, ==,
248                     udnp2->dict1->dict2->userdef->string);
249     g_assert_cmpstr(udnp1->dict1->dict2->string, ==,
250                     udnp2->dict1->dict2->string);
251     g_assert(udnp1->dict1->has_dict3 == udnp2->dict1->has_dict3);
252     g_assert_cmpint(udnp1->dict1->dict3->userdef->integer, ==,
253                     udnp2->dict1->dict3->userdef->integer);
254     g_assert_cmpstr(udnp1->dict1->dict3->userdef->string, ==,
255                     udnp2->dict1->dict3->userdef->string);
256     g_assert_cmpstr(udnp1->dict1->dict3->string, ==,
257                     udnp2->dict1->dict3->string);
258 }
259
260 static void nested_struct_cleanup(UserDefTwo *udnp)
261 {
262     qapi_free_UserDefTwo(udnp);
263 }
264
265 static void visit_nested_struct(Visitor *v, void **native, Error **errp)
266 {
267     visit_type_UserDefTwo(v, NULL, (UserDefTwo **)native, errp);
268 }
269
270 static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
271 {
272     visit_type_UserDefTwoList(v, NULL, (UserDefTwoList **)native, errp);
273 }
274
275 /* test cases */
276
277 typedef enum VisitorCapabilities {
278     VCAP_PRIMITIVES = 1,
279     VCAP_STRUCTURES = 2,
280     VCAP_LISTS = 4,
281     VCAP_PRIMITIVE_LISTS = 8,
282 } VisitorCapabilities;
283
284 typedef struct SerializeOps {
285     void (*serialize)(void *native_in, void **datap,
286                       VisitorFunc visit, Error **errp);
287     void (*deserialize)(void **native_out, void *datap,
288                             VisitorFunc visit, Error **errp);
289     void (*cleanup)(void *datap);
290     const char *type;
291     VisitorCapabilities caps;
292 } SerializeOps;
293
294 typedef struct TestArgs {
295     const SerializeOps *ops;
296     void *test_data;
297 } TestArgs;
298
299 static void test_primitives(gconstpointer opaque)
300 {
301     TestArgs *args = (TestArgs *) opaque;
302     const SerializeOps *ops = args->ops;
303     PrimitiveType *pt = args->test_data;
304     PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
305     void *serialize_data;
306
307     pt_copy->type = pt->type;
308     ops->serialize(pt, &serialize_data, visit_primitive_type, &error_abort);
309     ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type,
310                      &error_abort);
311
312     g_assert(pt_copy != NULL);
313     if (pt->type == PTYPE_STRING) {
314         g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
315         g_free((char *)pt_copy->value.string);
316     } else if (pt->type == PTYPE_NUMBER) {
317         GString *double_expected = g_string_new("");
318         GString *double_actual = g_string_new("");
319         /* we serialize with %f for our reference visitors, so rather than fuzzy
320          * floating math to test "equality", just compare the formatted values
321          */
322         g_string_printf(double_expected, "%.6f", pt->value.number);
323         g_string_printf(double_actual, "%.6f", pt_copy->value.number);
324         g_assert_cmpstr(double_actual->str, ==, double_expected->str);
325
326         g_string_free(double_expected, true);
327         g_string_free(double_actual, true);
328     } else if (pt->type == PTYPE_BOOLEAN) {
329         g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
330     } else {
331         g_assert_cmpint(pt->value.max, ==, pt_copy->value.max);
332     }
333
334     ops->cleanup(serialize_data);
335     g_free(args);
336     g_free(pt_copy);
337 }
338
339 static void test_primitive_lists(gconstpointer opaque)
340 {
341     TestArgs *args = (TestArgs *) opaque;
342     const SerializeOps *ops = args->ops;
343     PrimitiveType *pt = args->test_data;
344     PrimitiveList pl = { .value = { NULL } };
345     PrimitiveList pl_copy = { .value = { NULL } };
346     PrimitiveList *pl_copy_ptr = &pl_copy;
347     void *serialize_data;
348     void *cur_head = NULL;
349     int i;
350
351     pl.type = pl_copy.type = pt->type;
352
353     /* build up our list of primitive types */
354     for (i = 0; i < 32; i++) {
355         switch (pl.type) {
356         case PTYPE_STRING: {
357             strList *tmp = g_new0(strList, 1);
358             tmp->value = g_strdup(pt->value.string);
359             if (pl.value.strings == NULL) {
360                 pl.value.strings = tmp;
361             } else {
362                 tmp->next = pl.value.strings;
363                 pl.value.strings = tmp;
364             }
365             break;
366         }
367         case PTYPE_INTEGER: {
368             intList *tmp = g_new0(intList, 1);
369             tmp->value = pt->value.integer;
370             if (pl.value.integers == NULL) {
371                 pl.value.integers = tmp;
372             } else {
373                 tmp->next = pl.value.integers;
374                 pl.value.integers = tmp;
375             }
376             break;
377         }
378         case PTYPE_S8: {
379             int8List *tmp = g_new0(int8List, 1);
380             tmp->value = pt->value.s8;
381             if (pl.value.s8_integers == NULL) {
382                 pl.value.s8_integers = tmp;
383             } else {
384                 tmp->next = pl.value.s8_integers;
385                 pl.value.s8_integers = tmp;
386             }
387             break;
388         }
389         case PTYPE_S16: {
390             int16List *tmp = g_new0(int16List, 1);
391             tmp->value = pt->value.s16;
392             if (pl.value.s16_integers == NULL) {
393                 pl.value.s16_integers = tmp;
394             } else {
395                 tmp->next = pl.value.s16_integers;
396                 pl.value.s16_integers = tmp;
397             }
398             break;
399         }
400         case PTYPE_S32: {
401             int32List *tmp = g_new0(int32List, 1);
402             tmp->value = pt->value.s32;
403             if (pl.value.s32_integers == NULL) {
404                 pl.value.s32_integers = tmp;
405             } else {
406                 tmp->next = pl.value.s32_integers;
407                 pl.value.s32_integers = tmp;
408             }
409             break;
410         }
411         case PTYPE_S64: {
412             int64List *tmp = g_new0(int64List, 1);
413             tmp->value = pt->value.s64;
414             if (pl.value.s64_integers == NULL) {
415                 pl.value.s64_integers = tmp;
416             } else {
417                 tmp->next = pl.value.s64_integers;
418                 pl.value.s64_integers = tmp;
419             }
420             break;
421         }
422         case PTYPE_U8: {
423             uint8List *tmp = g_new0(uint8List, 1);
424             tmp->value = pt->value.u8;
425             if (pl.value.u8_integers == NULL) {
426                 pl.value.u8_integers = tmp;
427             } else {
428                 tmp->next = pl.value.u8_integers;
429                 pl.value.u8_integers = tmp;
430             }
431             break;
432         }
433         case PTYPE_U16: {
434             uint16List *tmp = g_new0(uint16List, 1);
435             tmp->value = pt->value.u16;
436             if (pl.value.u16_integers == NULL) {
437                 pl.value.u16_integers = tmp;
438             } else {
439                 tmp->next = pl.value.u16_integers;
440                 pl.value.u16_integers = tmp;
441             }
442             break;
443         }
444         case PTYPE_U32: {
445             uint32List *tmp = g_new0(uint32List, 1);
446             tmp->value = pt->value.u32;
447             if (pl.value.u32_integers == NULL) {
448                 pl.value.u32_integers = tmp;
449             } else {
450                 tmp->next = pl.value.u32_integers;
451                 pl.value.u32_integers = tmp;
452             }
453             break;
454         }
455         case PTYPE_U64: {
456             uint64List *tmp = g_new0(uint64List, 1);
457             tmp->value = pt->value.u64;
458             if (pl.value.u64_integers == NULL) {
459                 pl.value.u64_integers = tmp;
460             } else {
461                 tmp->next = pl.value.u64_integers;
462                 pl.value.u64_integers = tmp;
463             }
464             break;
465         }
466         case PTYPE_NUMBER: {
467             numberList *tmp = g_new0(numberList, 1);
468             tmp->value = pt->value.number;
469             if (pl.value.numbers == NULL) {
470                 pl.value.numbers = tmp;
471             } else {
472                 tmp->next = pl.value.numbers;
473                 pl.value.numbers = tmp;
474             }
475             break;
476         }
477         case PTYPE_BOOLEAN: {
478             boolList *tmp = g_new0(boolList, 1);
479             tmp->value = pt->value.boolean;
480             if (pl.value.booleans == NULL) {
481                 pl.value.booleans = tmp;
482             } else {
483                 tmp->next = pl.value.booleans;
484                 pl.value.booleans = tmp;
485             }
486             break;
487         }
488         default:
489             g_assert_not_reached();
490         }
491     }
492
493     ops->serialize((void **)&pl, &serialize_data, visit_primitive_list,
494                    &error_abort);
495     ops->deserialize((void **)&pl_copy_ptr, serialize_data,
496                      visit_primitive_list, &error_abort);
497
498     i = 0;
499
500     /* compare our deserialized list of primitives to the original */
501     do {
502         switch (pl_copy.type) {
503         case PTYPE_STRING: {
504             strList *ptr;
505             if (cur_head) {
506                 ptr = cur_head;
507                 cur_head = ptr->next;
508             } else {
509                 cur_head = ptr = pl_copy.value.strings;
510             }
511             g_assert_cmpstr(pt->value.string, ==, ptr->value);
512             break;
513         }
514         case PTYPE_INTEGER: {
515             intList *ptr;
516             if (cur_head) {
517                 ptr = cur_head;
518                 cur_head = ptr->next;
519             } else {
520                 cur_head = ptr = pl_copy.value.integers;
521             }
522             g_assert_cmpint(pt->value.integer, ==, ptr->value);
523             break;
524         }
525         case PTYPE_S8: {
526             int8List *ptr;
527             if (cur_head) {
528                 ptr = cur_head;
529                 cur_head = ptr->next;
530             } else {
531                 cur_head = ptr = pl_copy.value.s8_integers;
532             }
533             g_assert_cmpint(pt->value.s8, ==, ptr->value);
534             break;
535         }
536         case PTYPE_S16: {
537             int16List *ptr;
538             if (cur_head) {
539                 ptr = cur_head;
540                 cur_head = ptr->next;
541             } else {
542                 cur_head = ptr = pl_copy.value.s16_integers;
543             }
544             g_assert_cmpint(pt->value.s16, ==, ptr->value);
545             break;
546         }
547         case PTYPE_S32: {
548             int32List *ptr;
549             if (cur_head) {
550                 ptr = cur_head;
551                 cur_head = ptr->next;
552             } else {
553                 cur_head = ptr = pl_copy.value.s32_integers;
554             }
555             g_assert_cmpint(pt->value.s32, ==, ptr->value);
556             break;
557         }
558         case PTYPE_S64: {
559             int64List *ptr;
560             if (cur_head) {
561                 ptr = cur_head;
562                 cur_head = ptr->next;
563             } else {
564                 cur_head = ptr = pl_copy.value.s64_integers;
565             }
566             g_assert_cmpint(pt->value.s64, ==, ptr->value);
567             break;
568         }
569         case PTYPE_U8: {
570             uint8List *ptr;
571             if (cur_head) {
572                 ptr = cur_head;
573                 cur_head = ptr->next;
574             } else {
575                 cur_head = ptr = pl_copy.value.u8_integers;
576             }
577             g_assert_cmpint(pt->value.u8, ==, ptr->value);
578             break;
579         }
580         case PTYPE_U16: {
581             uint16List *ptr;
582             if (cur_head) {
583                 ptr = cur_head;
584                 cur_head = ptr->next;
585             } else {
586                 cur_head = ptr = pl_copy.value.u16_integers;
587             }
588             g_assert_cmpint(pt->value.u16, ==, ptr->value);
589             break;
590         }
591         case PTYPE_U32: {
592             uint32List *ptr;
593             if (cur_head) {
594                 ptr = cur_head;
595                 cur_head = ptr->next;
596             } else {
597                 cur_head = ptr = pl_copy.value.u32_integers;
598             }
599             g_assert_cmpint(pt->value.u32, ==, ptr->value);
600             break;
601         }
602         case PTYPE_U64: {
603             uint64List *ptr;
604             if (cur_head) {
605                 ptr = cur_head;
606                 cur_head = ptr->next;
607             } else {
608                 cur_head = ptr = pl_copy.value.u64_integers;
609             }
610             g_assert_cmpint(pt->value.u64, ==, ptr->value);
611             break;
612         }
613         case PTYPE_NUMBER: {
614             numberList *ptr;
615             GString *double_expected = g_string_new("");
616             GString *double_actual = g_string_new("");
617             if (cur_head) {
618                 ptr = cur_head;
619                 cur_head = ptr->next;
620             } else {
621                 cur_head = ptr = pl_copy.value.numbers;
622             }
623             /* we serialize with %f for our reference visitors, so rather than
624              * fuzzy floating math to test "equality", just compare the
625              * formatted values
626              */
627             g_string_printf(double_expected, "%.6f", pt->value.number);
628             g_string_printf(double_actual, "%.6f", ptr->value);
629             g_assert_cmpstr(double_actual->str, ==, double_expected->str);
630             g_string_free(double_expected, true);
631             g_string_free(double_actual, true);
632             break;
633         }
634         case PTYPE_BOOLEAN: {
635             boolList *ptr;
636             if (cur_head) {
637                 ptr = cur_head;
638                 cur_head = ptr->next;
639             } else {
640                 cur_head = ptr = pl_copy.value.booleans;
641             }
642             g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value);
643             break;
644         }
645         default:
646             g_assert_not_reached();
647         }
648         i++;
649     } while (cur_head);
650
651     g_assert_cmpint(i, ==, 33);
652
653     ops->cleanup(serialize_data);
654     dealloc_helper(&pl, visit_primitive_list, &error_abort);
655     dealloc_helper(&pl_copy, visit_primitive_list, &error_abort);
656     g_free(args);
657 }
658
659 static void test_struct(gconstpointer opaque)
660 {
661     TestArgs *args = (TestArgs *) opaque;
662     const SerializeOps *ops = args->ops;
663     TestStruct *ts = struct_create();
664     TestStruct *ts_copy = NULL;
665     void *serialize_data;
666
667     ops->serialize(ts, &serialize_data, visit_struct, &error_abort);
668     ops->deserialize((void **)&ts_copy, serialize_data, visit_struct,
669                      &error_abort);
670
671     struct_compare(ts, ts_copy);
672
673     struct_cleanup(ts);
674     struct_cleanup(ts_copy);
675
676     ops->cleanup(serialize_data);
677     g_free(args);
678 }
679
680 static void test_nested_struct(gconstpointer opaque)
681 {
682     TestArgs *args = (TestArgs *) opaque;
683     const SerializeOps *ops = args->ops;
684     UserDefTwo *udnp = nested_struct_create();
685     UserDefTwo *udnp_copy = NULL;
686     void *serialize_data;
687
688     ops->serialize(udnp, &serialize_data, visit_nested_struct, &error_abort);
689     ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct,
690                      &error_abort);
691
692     nested_struct_compare(udnp, udnp_copy);
693
694     nested_struct_cleanup(udnp);
695     nested_struct_cleanup(udnp_copy);
696
697     ops->cleanup(serialize_data);
698     g_free(args);
699 }
700
701 static void test_nested_struct_list(gconstpointer opaque)
702 {
703     TestArgs *args = (TestArgs *) opaque;
704     const SerializeOps *ops = args->ops;
705     UserDefTwoList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
706     void *serialize_data;
707     int i = 0;
708
709     for (i = 0; i < 8; i++) {
710         tmp = g_new0(UserDefTwoList, 1);
711         tmp->value = nested_struct_create();
712         tmp->next = listp;
713         listp = tmp;
714     }
715
716     ops->serialize(listp, &serialize_data, visit_nested_struct_list,
717                    &error_abort);
718     ops->deserialize((void **)&listp_copy, serialize_data,
719                      visit_nested_struct_list, &error_abort);
720
721     tmp = listp;
722     tmp_copy = listp_copy;
723     while (listp_copy) {
724         g_assert(listp);
725         nested_struct_compare(listp->value, listp_copy->value);
726         listp = listp->next;
727         listp_copy = listp_copy->next;
728     }
729
730     qapi_free_UserDefTwoList(tmp);
731     qapi_free_UserDefTwoList(tmp_copy);
732
733     ops->cleanup(serialize_data);
734     g_free(args);
735 }
736
737 static PrimitiveType pt_values[] = {
738     /* string tests */
739     {
740         .description = "string_empty",
741         .type = PTYPE_STRING,
742         .value.string = "",
743     },
744     {
745         .description = "string_whitespace",
746         .type = PTYPE_STRING,
747         .value.string = "a b  c\td",
748     },
749     {
750         .description = "string_newlines",
751         .type = PTYPE_STRING,
752         .value.string = "a\nb\n",
753     },
754     {
755         .description = "string_commas",
756         .type = PTYPE_STRING,
757         .value.string = "a,b, c,d",
758     },
759     {
760         .description = "string_single_quoted",
761         .type = PTYPE_STRING,
762         .value.string = "'a b',cd",
763     },
764     {
765         .description = "string_double_quoted",
766         .type = PTYPE_STRING,
767         .value.string = "\"a b\",cd",
768     },
769     /* boolean tests */
770     {
771         .description = "boolean_true1",
772         .type = PTYPE_BOOLEAN,
773         .value.boolean = true,
774     },
775     {
776         .description = "boolean_true2",
777         .type = PTYPE_BOOLEAN,
778         .value.boolean = 8,
779     },
780     {
781         .description = "boolean_true3",
782         .type = PTYPE_BOOLEAN,
783         .value.boolean = -1,
784     },
785     {
786         .description = "boolean_false1",
787         .type = PTYPE_BOOLEAN,
788         .value.boolean = false,
789     },
790     {
791         .description = "boolean_false2",
792         .type = PTYPE_BOOLEAN,
793         .value.boolean = 0,
794     },
795     /* number tests (double) */
796     /* note: we format these to %.6f before comparing, since that's how
797      * we serialize them and it doesn't make sense to check precision
798      * beyond that.
799      */
800     {
801         .description = "number_sanity1",
802         .type = PTYPE_NUMBER,
803         .value.number = -1,
804     },
805     {
806         .description = "number_sanity2",
807         .type = PTYPE_NUMBER,
808         .value.number = 3.14159265,
809     },
810     {
811         .description = "number_min",
812         .type = PTYPE_NUMBER,
813         .value.number = DBL_MIN,
814     },
815     {
816         .description = "number_max",
817         .type = PTYPE_NUMBER,
818         .value.number = DBL_MAX,
819     },
820     /* integer tests (int64) */
821     {
822         .description = "integer_sanity1",
823         .type = PTYPE_INTEGER,
824         .value.integer = -1,
825     },
826     {
827         .description = "integer_sanity2",
828         .type = PTYPE_INTEGER,
829         .value.integer = INT64_MAX / 2 + 1,
830     },
831     {
832         .description = "integer_min",
833         .type = PTYPE_INTEGER,
834         .value.integer = INT64_MIN,
835     },
836     {
837         .description = "integer_max",
838         .type = PTYPE_INTEGER,
839         .value.integer = INT64_MAX,
840     },
841     /* uint8 tests */
842     {
843         .description = "uint8_sanity1",
844         .type = PTYPE_U8,
845         .value.u8 = 1,
846     },
847     {
848         .description = "uint8_sanity2",
849         .type = PTYPE_U8,
850         .value.u8 = UINT8_MAX / 2 + 1,
851     },
852     {
853         .description = "uint8_min",
854         .type = PTYPE_U8,
855         .value.u8 = 0,
856     },
857     {
858         .description = "uint8_max",
859         .type = PTYPE_U8,
860         .value.u8 = UINT8_MAX,
861     },
862     /* uint16 tests */
863     {
864         .description = "uint16_sanity1",
865         .type = PTYPE_U16,
866         .value.u16 = 1,
867     },
868     {
869         .description = "uint16_sanity2",
870         .type = PTYPE_U16,
871         .value.u16 = UINT16_MAX / 2 + 1,
872     },
873     {
874         .description = "uint16_min",
875         .type = PTYPE_U16,
876         .value.u16 = 0,
877     },
878     {
879         .description = "uint16_max",
880         .type = PTYPE_U16,
881         .value.u16 = UINT16_MAX,
882     },
883     /* uint32 tests */
884     {
885         .description = "uint32_sanity1",
886         .type = PTYPE_U32,
887         .value.u32 = 1,
888     },
889     {
890         .description = "uint32_sanity2",
891         .type = PTYPE_U32,
892         .value.u32 = UINT32_MAX / 2 + 1,
893     },
894     {
895         .description = "uint32_min",
896         .type = PTYPE_U32,
897         .value.u32 = 0,
898     },
899     {
900         .description = "uint32_max",
901         .type = PTYPE_U32,
902         .value.u32 = UINT32_MAX,
903     },
904     /* uint64 tests */
905     {
906         .description = "uint64_sanity1",
907         .type = PTYPE_U64,
908         .value.u64 = 1,
909     },
910     {
911         .description = "uint64_sanity2",
912         .type = PTYPE_U64,
913         .value.u64 = UINT64_MAX / 2 + 1,
914     },
915     {
916         .description = "uint64_min",
917         .type = PTYPE_U64,
918         .value.u64 = 0,
919     },
920     {
921         .description = "uint64_max",
922         .type = PTYPE_U64,
923         .value.u64 = UINT64_MAX,
924     },
925     /* int8 tests */
926     {
927         .description = "int8_sanity1",
928         .type = PTYPE_S8,
929         .value.s8 = -1,
930     },
931     {
932         .description = "int8_sanity2",
933         .type = PTYPE_S8,
934         .value.s8 = INT8_MAX / 2 + 1,
935     },
936     {
937         .description = "int8_min",
938         .type = PTYPE_S8,
939         .value.s8 = INT8_MIN,
940     },
941     {
942         .description = "int8_max",
943         .type = PTYPE_S8,
944         .value.s8 = INT8_MAX,
945     },
946     /* int16 tests */
947     {
948         .description = "int16_sanity1",
949         .type = PTYPE_S16,
950         .value.s16 = -1,
951     },
952     {
953         .description = "int16_sanity2",
954         .type = PTYPE_S16,
955         .value.s16 = INT16_MAX / 2 + 1,
956     },
957     {
958         .description = "int16_min",
959         .type = PTYPE_S16,
960         .value.s16 = INT16_MIN,
961     },
962     {
963         .description = "int16_max",
964         .type = PTYPE_S16,
965         .value.s16 = INT16_MAX,
966     },
967     /* int32 tests */
968     {
969         .description = "int32_sanity1",
970         .type = PTYPE_S32,
971         .value.s32 = -1,
972     },
973     {
974         .description = "int32_sanity2",
975         .type = PTYPE_S32,
976         .value.s32 = INT32_MAX / 2 + 1,
977     },
978     {
979         .description = "int32_min",
980         .type = PTYPE_S32,
981         .value.s32 = INT32_MIN,
982     },
983     {
984         .description = "int32_max",
985         .type = PTYPE_S32,
986         .value.s32 = INT32_MAX,
987     },
988     /* int64 tests */
989     {
990         .description = "int64_sanity1",
991         .type = PTYPE_S64,
992         .value.s64 = -1,
993     },
994     {
995         .description = "int64_sanity2",
996         .type = PTYPE_S64,
997         .value.s64 = INT64_MAX / 2 + 1,
998     },
999     {
1000         .description = "int64_min",
1001         .type = PTYPE_S64,
1002         .value.s64 = INT64_MIN,
1003     },
1004     {
1005         .description = "int64_max",
1006         .type = PTYPE_S64,
1007         .value.s64 = INT64_MAX,
1008     },
1009     { .type = PTYPE_EOL }
1010 };
1011
1012 /* visitor-specific op implementations */
1013
1014 typedef struct QmpSerializeData {
1015     QmpOutputVisitor *qov;
1016     QmpInputVisitor *qiv;
1017 } QmpSerializeData;
1018
1019 static void qmp_serialize(void *native_in, void **datap,
1020                           VisitorFunc visit, Error **errp)
1021 {
1022     QmpSerializeData *d = g_malloc0(sizeof(*d));
1023
1024     d->qov = qmp_output_visitor_new();
1025     visit(qmp_output_get_visitor(d->qov), &native_in, errp);
1026     *datap = d;
1027 }
1028
1029 static void qmp_deserialize(void **native_out, void *datap,
1030                             VisitorFunc visit, Error **errp)
1031 {
1032     QmpSerializeData *d = datap;
1033     QString *output_json;
1034     QObject *obj_orig, *obj;
1035
1036     obj_orig = qmp_output_get_qobject(d->qov);
1037     output_json = qobject_to_json(obj_orig);
1038     obj = qobject_from_json(qstring_get_str(output_json));
1039
1040     QDECREF(output_json);
1041     d->qiv = qmp_input_visitor_new(obj);
1042     qobject_decref(obj_orig);
1043     qobject_decref(obj);
1044     visit(qmp_input_get_visitor(d->qiv), native_out, errp);
1045 }
1046
1047 static void qmp_cleanup(void *datap)
1048 {
1049     QmpSerializeData *d = datap;
1050     qmp_output_visitor_cleanup(d->qov);
1051     qmp_input_visitor_cleanup(d->qiv);
1052
1053     g_free(d);
1054 }
1055
1056 typedef struct StringSerializeData {
1057     char *string;
1058     StringOutputVisitor *sov;
1059     StringInputVisitor *siv;
1060 } StringSerializeData;
1061
1062 static void string_serialize(void *native_in, void **datap,
1063                              VisitorFunc visit, Error **errp)
1064 {
1065     StringSerializeData *d = g_malloc0(sizeof(*d));
1066
1067     d->sov = string_output_visitor_new(false);
1068     visit(string_output_get_visitor(d->sov), &native_in, errp);
1069     *datap = d;
1070 }
1071
1072 static void string_deserialize(void **native_out, void *datap,
1073                                VisitorFunc visit, Error **errp)
1074 {
1075     StringSerializeData *d = datap;
1076
1077     d->string = string_output_get_string(d->sov);
1078     d->siv = string_input_visitor_new(d->string);
1079     visit(string_input_get_visitor(d->siv), native_out, errp);
1080 }
1081
1082 static void string_cleanup(void *datap)
1083 {
1084     StringSerializeData *d = datap;
1085
1086     string_output_visitor_cleanup(d->sov);
1087     string_input_visitor_cleanup(d->siv);
1088     g_free(d->string);
1089     g_free(d);
1090 }
1091
1092 /* visitor registration, test harness */
1093
1094 /* note: to function interchangeably as a serialization mechanism your
1095  * visitor test implementation should pass the test cases for all visitor
1096  * capabilities: primitives, structures, and lists
1097  */
1098 static const SerializeOps visitors[] = {
1099     {
1100         .type = "QMP",
1101         .serialize = qmp_serialize,
1102         .deserialize = qmp_deserialize,
1103         .cleanup = qmp_cleanup,
1104         .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS |
1105                 VCAP_PRIMITIVE_LISTS
1106     },
1107     {
1108         .type = "String",
1109         .serialize = string_serialize,
1110         .deserialize = string_deserialize,
1111         .cleanup = string_cleanup,
1112         .caps = VCAP_PRIMITIVES
1113     },
1114     { NULL }
1115 };
1116
1117 static void add_visitor_type(const SerializeOps *ops)
1118 {
1119     char testname_prefix[128];
1120     char testname[128];
1121     TestArgs *args;
1122     int i = 0;
1123
1124     sprintf(testname_prefix, "/visitor/serialization/%s", ops->type);
1125
1126     if (ops->caps & VCAP_PRIMITIVES) {
1127         while (pt_values[i].type != PTYPE_EOL) {
1128             sprintf(testname, "%s/primitives/%s", testname_prefix,
1129                     pt_values[i].description);
1130             args = g_malloc0(sizeof(*args));
1131             args->ops = ops;
1132             args->test_data = &pt_values[i];
1133             g_test_add_data_func(testname, args, test_primitives);
1134             i++;
1135         }
1136     }
1137
1138     if (ops->caps & VCAP_STRUCTURES) {
1139         sprintf(testname, "%s/struct", testname_prefix);
1140         args = g_malloc0(sizeof(*args));
1141         args->ops = ops;
1142         args->test_data = NULL;
1143         g_test_add_data_func(testname, args, test_struct);
1144
1145         sprintf(testname, "%s/nested_struct", testname_prefix);
1146         args = g_malloc0(sizeof(*args));
1147         args->ops = ops;
1148         args->test_data = NULL;
1149         g_test_add_data_func(testname, args, test_nested_struct);
1150     }
1151
1152     if (ops->caps & VCAP_LISTS) {
1153         sprintf(testname, "%s/nested_struct_list", testname_prefix);
1154         args = g_malloc0(sizeof(*args));
1155         args->ops = ops;
1156         args->test_data = NULL;
1157         g_test_add_data_func(testname, args, test_nested_struct_list);
1158     }
1159
1160     if (ops->caps & VCAP_PRIMITIVE_LISTS) {
1161         i = 0;
1162         while (pt_values[i].type != PTYPE_EOL) {
1163             sprintf(testname, "%s/primitive_list/%s", testname_prefix,
1164                     pt_values[i].description);
1165             args = g_malloc0(sizeof(*args));
1166             args->ops = ops;
1167             args->test_data = &pt_values[i];
1168             g_test_add_data_func(testname, args, test_primitive_lists);
1169             i++;
1170         }
1171     }
1172 }
1173
1174 int main(int argc, char **argv)
1175 {
1176     int i = 0;
1177
1178     g_test_init(&argc, &argv, NULL);
1179
1180     while (visitors[i].type != NULL) {
1181         add_visitor_type(&visitors[i]);
1182         i++;
1183     }
1184
1185     g_test_run();
1186
1187     return 0;
1188 }