aspeed/i2c: Add ast1030 controller models
[qemu.git] / tests / unit / test-visitor-serialization.c
blob907263d0307c798d4cb5ab800429e0343c6481b5
1 /*
2 * Unit-tests for visitor-based serialization
4 * Copyright (C) 2014-2015 Red Hat, Inc.
5 * Copyright IBM, Corp. 2012
7 * Authors:
8 * Michael Roth <mdroth@linux.vnet.ibm.com>
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.
14 #include "qemu/osdep.h"
15 #include <float.h>
17 #include "test-qapi-visit.h"
18 #include "qapi/error.h"
19 #include "qapi/qmp/qjson.h"
20 #include "qapi/qmp/qstring.h"
21 #include "qapi/qobject-input-visitor.h"
22 #include "qapi/qobject-output-visitor.h"
23 #include "qapi/string-input-visitor.h"
24 #include "qapi/string-output-visitor.h"
25 #include "qapi/dealloc-visitor.h"
27 enum PrimitiveTypeKind {
28 PTYPE_STRING = 0,
29 PTYPE_BOOLEAN,
30 PTYPE_NUMBER,
31 PTYPE_INTEGER,
32 PTYPE_U8,
33 PTYPE_U16,
34 PTYPE_U32,
35 PTYPE_U64,
36 PTYPE_S8,
37 PTYPE_S16,
38 PTYPE_S32,
39 PTYPE_S64,
40 PTYPE_EOL,
43 typedef struct PrimitiveType {
44 union {
45 const char *string;
46 bool boolean;
47 double number;
48 int64_t integer;
49 uint8_t u8;
50 uint16_t u16;
51 uint32_t u32;
52 uint64_t u64;
53 int8_t s8;
54 int16_t s16;
55 int32_t s32;
56 int64_t s64;
57 } value;
58 enum PrimitiveTypeKind type;
59 const char *description;
60 } PrimitiveType;
62 typedef struct PrimitiveList {
63 union {
64 strList *strings;
65 boolList *booleans;
66 numberList *numbers;
67 intList *integers;
68 int8List *s8_integers;
69 int16List *s16_integers;
70 int32List *s32_integers;
71 int64List *s64_integers;
72 uint8List *u8_integers;
73 uint16List *u16_integers;
74 uint32List *u32_integers;
75 uint64List *u64_integers;
76 } value;
77 enum PrimitiveTypeKind type;
78 const char *description;
79 } PrimitiveList;
81 /* test helpers */
83 typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
85 static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp)
87 Visitor *v = qapi_dealloc_visitor_new();
89 visit(v, &native_in, errp);
91 visit_free(v);
94 static void visit_primitive_type(Visitor *v, void **native, Error **errp)
96 PrimitiveType *pt = *native;
97 switch(pt->type) {
98 case PTYPE_STRING:
99 visit_type_str(v, NULL, (char **)&pt->value.string, errp);
100 break;
101 case PTYPE_BOOLEAN:
102 visit_type_bool(v, NULL, &pt->value.boolean, errp);
103 break;
104 case PTYPE_NUMBER:
105 visit_type_number(v, NULL, &pt->value.number, errp);
106 break;
107 case PTYPE_INTEGER:
108 visit_type_int(v, NULL, &pt->value.integer, errp);
109 break;
110 case PTYPE_U8:
111 visit_type_uint8(v, NULL, &pt->value.u8, errp);
112 break;
113 case PTYPE_U16:
114 visit_type_uint16(v, NULL, &pt->value.u16, errp);
115 break;
116 case PTYPE_U32:
117 visit_type_uint32(v, NULL, &pt->value.u32, errp);
118 break;
119 case PTYPE_U64:
120 visit_type_uint64(v, NULL, &pt->value.u64, errp);
121 break;
122 case PTYPE_S8:
123 visit_type_int8(v, NULL, &pt->value.s8, errp);
124 break;
125 case PTYPE_S16:
126 visit_type_int16(v, NULL, &pt->value.s16, errp);
127 break;
128 case PTYPE_S32:
129 visit_type_int32(v, NULL, &pt->value.s32, errp);
130 break;
131 case PTYPE_S64:
132 visit_type_int64(v, NULL, &pt->value.s64, errp);
133 break;
134 case PTYPE_EOL:
135 g_assert_not_reached();
139 static void visit_primitive_list(Visitor *v, void **native, Error **errp)
141 PrimitiveList *pl = *native;
142 switch (pl->type) {
143 case PTYPE_STRING:
144 visit_type_strList(v, NULL, &pl->value.strings, errp);
145 break;
146 case PTYPE_BOOLEAN:
147 visit_type_boolList(v, NULL, &pl->value.booleans, errp);
148 break;
149 case PTYPE_NUMBER:
150 visit_type_numberList(v, NULL, &pl->value.numbers, errp);
151 break;
152 case PTYPE_INTEGER:
153 visit_type_intList(v, NULL, &pl->value.integers, errp);
154 break;
155 case PTYPE_S8:
156 visit_type_int8List(v, NULL, &pl->value.s8_integers, errp);
157 break;
158 case PTYPE_S16:
159 visit_type_int16List(v, NULL, &pl->value.s16_integers, errp);
160 break;
161 case PTYPE_S32:
162 visit_type_int32List(v, NULL, &pl->value.s32_integers, errp);
163 break;
164 case PTYPE_S64:
165 visit_type_int64List(v, NULL, &pl->value.s64_integers, errp);
166 break;
167 case PTYPE_U8:
168 visit_type_uint8List(v, NULL, &pl->value.u8_integers, errp);
169 break;
170 case PTYPE_U16:
171 visit_type_uint16List(v, NULL, &pl->value.u16_integers, errp);
172 break;
173 case PTYPE_U32:
174 visit_type_uint32List(v, NULL, &pl->value.u32_integers, errp);
175 break;
176 case PTYPE_U64:
177 visit_type_uint64List(v, NULL, &pl->value.u64_integers, errp);
178 break;
179 default:
180 g_assert_not_reached();
185 static TestStruct *struct_create(void)
187 TestStruct *ts = g_malloc0(sizeof(*ts));
188 ts->integer = -42;
189 ts->boolean = true;
190 ts->string = strdup("test string");
191 return ts;
194 static void struct_compare(TestStruct *ts1, TestStruct *ts2)
196 g_assert(ts1);
197 g_assert(ts2);
198 g_assert_cmpint(ts1->integer, ==, ts2->integer);
199 g_assert(ts1->boolean == ts2->boolean);
200 g_assert_cmpstr(ts1->string, ==, ts2->string);
203 static void struct_cleanup(TestStruct *ts)
205 g_free(ts->string);
206 g_free(ts);
209 static void visit_struct(Visitor *v, void **native, Error **errp)
211 visit_type_TestStruct(v, NULL, (TestStruct **)native, errp);
214 static UserDefTwo *nested_struct_create(void)
216 UserDefTwo *udnp = g_malloc0(sizeof(*udnp));
217 udnp->string0 = strdup("test_string0");
218 udnp->dict1 = g_malloc0(sizeof(*udnp->dict1));
219 udnp->dict1->string1 = strdup("test_string1");
220 udnp->dict1->dict2 = g_malloc0(sizeof(*udnp->dict1->dict2));
221 udnp->dict1->dict2->userdef = g_new0(UserDefOne, 1);
222 udnp->dict1->dict2->userdef->integer = 42;
223 udnp->dict1->dict2->userdef->string = strdup("test_string");
224 udnp->dict1->dict2->string = strdup("test_string2");
225 udnp->dict1->dict3 = g_malloc0(sizeof(*udnp->dict1->dict3));
226 udnp->dict1->has_dict3 = true;
227 udnp->dict1->dict3->userdef = g_new0(UserDefOne, 1);
228 udnp->dict1->dict3->userdef->integer = 43;
229 udnp->dict1->dict3->userdef->string = strdup("test_string");
230 udnp->dict1->dict3->string = strdup("test_string3");
231 return udnp;
234 static void nested_struct_compare(UserDefTwo *udnp1, UserDefTwo *udnp2)
236 g_assert(udnp1);
237 g_assert(udnp2);
238 g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
239 g_assert_cmpstr(udnp1->dict1->string1, ==, udnp2->dict1->string1);
240 g_assert_cmpint(udnp1->dict1->dict2->userdef->integer, ==,
241 udnp2->dict1->dict2->userdef->integer);
242 g_assert_cmpstr(udnp1->dict1->dict2->userdef->string, ==,
243 udnp2->dict1->dict2->userdef->string);
244 g_assert_cmpstr(udnp1->dict1->dict2->string, ==,
245 udnp2->dict1->dict2->string);
246 g_assert(udnp1->dict1->has_dict3 == udnp2->dict1->has_dict3);
247 g_assert_cmpint(udnp1->dict1->dict3->userdef->integer, ==,
248 udnp2->dict1->dict3->userdef->integer);
249 g_assert_cmpstr(udnp1->dict1->dict3->userdef->string, ==,
250 udnp2->dict1->dict3->userdef->string);
251 g_assert_cmpstr(udnp1->dict1->dict3->string, ==,
252 udnp2->dict1->dict3->string);
255 static void nested_struct_cleanup(UserDefTwo *udnp)
257 qapi_free_UserDefTwo(udnp);
260 static void visit_nested_struct(Visitor *v, void **native, Error **errp)
262 visit_type_UserDefTwo(v, NULL, (UserDefTwo **)native, errp);
265 static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
267 visit_type_UserDefTwoList(v, NULL, (UserDefTwoList **)native, errp);
270 /* test cases */
272 typedef enum VisitorCapabilities {
273 VCAP_PRIMITIVES = 1,
274 VCAP_STRUCTURES = 2,
275 VCAP_LISTS = 4,
276 VCAP_PRIMITIVE_LISTS = 8,
277 } VisitorCapabilities;
279 typedef struct SerializeOps {
280 void (*serialize)(void *native_in, void **datap,
281 VisitorFunc visit, Error **errp);
282 void (*deserialize)(void **native_out, void *datap,
283 VisitorFunc visit, Error **errp);
284 void (*cleanup)(void *datap);
285 const char *type;
286 VisitorCapabilities caps;
287 } SerializeOps;
289 typedef struct TestArgs {
290 const SerializeOps *ops;
291 void *test_data;
292 } TestArgs;
294 static void test_primitives(gconstpointer opaque)
296 TestArgs *args = (TestArgs *) opaque;
297 const SerializeOps *ops = args->ops;
298 PrimitiveType *pt = args->test_data;
299 PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
300 void *serialize_data;
302 pt_copy->type = pt->type;
303 ops->serialize(pt, &serialize_data, visit_primitive_type, &error_abort);
304 ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type,
305 &error_abort);
307 g_assert(pt_copy != NULL);
308 switch (pt->type) {
309 case PTYPE_STRING:
310 g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
311 g_free((char *)pt_copy->value.string);
312 break;
313 case PTYPE_BOOLEAN:
314 g_assert_cmpint(pt->value.boolean, ==, pt->value.boolean);
315 break;
316 case PTYPE_NUMBER:
317 g_assert_cmpfloat(pt->value.number, ==, pt_copy->value.number);
318 break;
319 case PTYPE_INTEGER:
320 g_assert_cmpint(pt->value.integer, ==, pt_copy->value.integer);
321 break;
322 case PTYPE_U8:
323 g_assert_cmpuint(pt->value.u8, ==, pt_copy->value.u8);
324 break;
325 case PTYPE_U16:
326 g_assert_cmpuint(pt->value.u16, ==, pt_copy->value.u16);
327 break;
328 case PTYPE_U32:
329 g_assert_cmpuint(pt->value.u32, ==, pt_copy->value.u32);
330 break;
331 case PTYPE_U64:
332 g_assert_cmpuint(pt->value.u64, ==, pt_copy->value.u64);
333 break;
334 case PTYPE_S8:
335 g_assert_cmpint(pt->value.s8, ==, pt_copy->value.s8);
336 break;
337 case PTYPE_S16:
338 g_assert_cmpint(pt->value.s16, ==, pt_copy->value.s16);
339 break;
340 case PTYPE_S32:
341 g_assert_cmpint(pt->value.s32, ==, pt_copy->value.s32);
342 break;
343 case PTYPE_S64:
344 g_assert_cmpint(pt->value.s64, ==, pt_copy->value.s64);
345 break;
346 case PTYPE_EOL:
347 g_assert_not_reached();
350 ops->cleanup(serialize_data);
351 g_free(args);
352 g_free(pt_copy);
355 static void test_primitive_lists(gconstpointer opaque)
357 TestArgs *args = (TestArgs *) opaque;
358 const SerializeOps *ops = args->ops;
359 PrimitiveType *pt = args->test_data;
360 PrimitiveList pl = { .value = { NULL } };
361 PrimitiveList pl_copy = { .value = { NULL } };
362 PrimitiveList *pl_copy_ptr = &pl_copy;
363 void *serialize_data;
364 void *cur_head = NULL;
365 int i;
367 pl.type = pl_copy.type = pt->type;
369 /* build up our list of primitive types */
370 for (i = 0; i < 32; i++) {
371 switch (pl.type) {
372 case PTYPE_STRING: {
373 QAPI_LIST_PREPEND(pl.value.strings, g_strdup(pt->value.string));
374 break;
376 case PTYPE_INTEGER: {
377 QAPI_LIST_PREPEND(pl.value.integers, pt->value.integer);
378 break;
380 case PTYPE_S8: {
381 QAPI_LIST_PREPEND(pl.value.s8_integers, pt->value.s8);
382 break;
384 case PTYPE_S16: {
385 QAPI_LIST_PREPEND(pl.value.s16_integers, pt->value.s16);
386 break;
388 case PTYPE_S32: {
389 QAPI_LIST_PREPEND(pl.value.s32_integers, pt->value.s32);
390 break;
392 case PTYPE_S64: {
393 QAPI_LIST_PREPEND(pl.value.s64_integers, pt->value.s64);
394 break;
396 case PTYPE_U8: {
397 QAPI_LIST_PREPEND(pl.value.u8_integers, pt->value.u8);
398 break;
400 case PTYPE_U16: {
401 QAPI_LIST_PREPEND(pl.value.u16_integers, pt->value.u16);
402 break;
404 case PTYPE_U32: {
405 QAPI_LIST_PREPEND(pl.value.u32_integers, pt->value.u32);
406 break;
408 case PTYPE_U64: {
409 QAPI_LIST_PREPEND(pl.value.u64_integers, pt->value.u64);
410 break;
412 case PTYPE_NUMBER: {
413 QAPI_LIST_PREPEND(pl.value.numbers, pt->value.number);
414 break;
416 case PTYPE_BOOLEAN: {
417 QAPI_LIST_PREPEND(pl.value.booleans, pt->value.boolean);
418 break;
420 default:
421 g_assert_not_reached();
425 ops->serialize((void **)&pl, &serialize_data, visit_primitive_list,
426 &error_abort);
427 ops->deserialize((void **)&pl_copy_ptr, serialize_data,
428 visit_primitive_list, &error_abort);
430 i = 0;
432 /* compare our deserialized list of primitives to the original */
433 do {
434 switch (pl_copy.type) {
435 case PTYPE_STRING: {
436 strList *ptr;
437 if (cur_head) {
438 ptr = cur_head;
439 cur_head = ptr->next;
440 } else {
441 cur_head = ptr = pl_copy.value.strings;
443 g_assert_cmpstr(pt->value.string, ==, ptr->value);
444 break;
446 case PTYPE_INTEGER: {
447 intList *ptr;
448 if (cur_head) {
449 ptr = cur_head;
450 cur_head = ptr->next;
451 } else {
452 cur_head = ptr = pl_copy.value.integers;
454 g_assert_cmpint(pt->value.integer, ==, ptr->value);
455 break;
457 case PTYPE_S8: {
458 int8List *ptr;
459 if (cur_head) {
460 ptr = cur_head;
461 cur_head = ptr->next;
462 } else {
463 cur_head = ptr = pl_copy.value.s8_integers;
465 g_assert_cmpint(pt->value.s8, ==, ptr->value);
466 break;
468 case PTYPE_S16: {
469 int16List *ptr;
470 if (cur_head) {
471 ptr = cur_head;
472 cur_head = ptr->next;
473 } else {
474 cur_head = ptr = pl_copy.value.s16_integers;
476 g_assert_cmpint(pt->value.s16, ==, ptr->value);
477 break;
479 case PTYPE_S32: {
480 int32List *ptr;
481 if (cur_head) {
482 ptr = cur_head;
483 cur_head = ptr->next;
484 } else {
485 cur_head = ptr = pl_copy.value.s32_integers;
487 g_assert_cmpint(pt->value.s32, ==, ptr->value);
488 break;
490 case PTYPE_S64: {
491 int64List *ptr;
492 if (cur_head) {
493 ptr = cur_head;
494 cur_head = ptr->next;
495 } else {
496 cur_head = ptr = pl_copy.value.s64_integers;
498 g_assert_cmpint(pt->value.s64, ==, ptr->value);
499 break;
501 case PTYPE_U8: {
502 uint8List *ptr;
503 if (cur_head) {
504 ptr = cur_head;
505 cur_head = ptr->next;
506 } else {
507 cur_head = ptr = pl_copy.value.u8_integers;
509 g_assert_cmpint(pt->value.u8, ==, ptr->value);
510 break;
512 case PTYPE_U16: {
513 uint16List *ptr;
514 if (cur_head) {
515 ptr = cur_head;
516 cur_head = ptr->next;
517 } else {
518 cur_head = ptr = pl_copy.value.u16_integers;
520 g_assert_cmpint(pt->value.u16, ==, ptr->value);
521 break;
523 case PTYPE_U32: {
524 uint32List *ptr;
525 if (cur_head) {
526 ptr = cur_head;
527 cur_head = ptr->next;
528 } else {
529 cur_head = ptr = pl_copy.value.u32_integers;
531 g_assert_cmpint(pt->value.u32, ==, ptr->value);
532 break;
534 case PTYPE_U64: {
535 uint64List *ptr;
536 if (cur_head) {
537 ptr = cur_head;
538 cur_head = ptr->next;
539 } else {
540 cur_head = ptr = pl_copy.value.u64_integers;
542 g_assert_cmpint(pt->value.u64, ==, ptr->value);
543 break;
545 case PTYPE_NUMBER: {
546 numberList *ptr;
547 GString *double_expected = g_string_new("");
548 GString *double_actual = g_string_new("");
549 if (cur_head) {
550 ptr = cur_head;
551 cur_head = ptr->next;
552 } else {
553 cur_head = ptr = pl_copy.value.numbers;
555 /* we serialize with %f for our reference visitors, so rather than
556 * fuzzy floating math to test "equality", just compare the
557 * formatted values
559 g_string_printf(double_expected, "%.6f", pt->value.number);
560 g_string_printf(double_actual, "%.6f", ptr->value);
561 g_assert_cmpstr(double_actual->str, ==, double_expected->str);
562 g_string_free(double_expected, true);
563 g_string_free(double_actual, true);
564 break;
566 case PTYPE_BOOLEAN: {
567 boolList *ptr;
568 if (cur_head) {
569 ptr = cur_head;
570 cur_head = ptr->next;
571 } else {
572 cur_head = ptr = pl_copy.value.booleans;
574 g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value);
575 break;
577 default:
578 g_assert_not_reached();
580 i++;
581 } while (cur_head);
583 g_assert_cmpint(i, ==, 33);
585 ops->cleanup(serialize_data);
586 dealloc_helper(&pl, visit_primitive_list, &error_abort);
587 dealloc_helper(&pl_copy, visit_primitive_list, &error_abort);
588 g_free(args);
591 static void test_struct(gconstpointer opaque)
593 TestArgs *args = (TestArgs *) opaque;
594 const SerializeOps *ops = args->ops;
595 TestStruct *ts = struct_create();
596 TestStruct *ts_copy = NULL;
597 void *serialize_data;
599 ops->serialize(ts, &serialize_data, visit_struct, &error_abort);
600 ops->deserialize((void **)&ts_copy, serialize_data, visit_struct,
601 &error_abort);
603 struct_compare(ts, ts_copy);
605 struct_cleanup(ts);
606 struct_cleanup(ts_copy);
608 ops->cleanup(serialize_data);
609 g_free(args);
612 static void test_nested_struct(gconstpointer opaque)
614 TestArgs *args = (TestArgs *) opaque;
615 const SerializeOps *ops = args->ops;
616 UserDefTwo *udnp = nested_struct_create();
617 UserDefTwo *udnp_copy = NULL;
618 void *serialize_data;
620 ops->serialize(udnp, &serialize_data, visit_nested_struct, &error_abort);
621 ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct,
622 &error_abort);
624 nested_struct_compare(udnp, udnp_copy);
626 nested_struct_cleanup(udnp);
627 nested_struct_cleanup(udnp_copy);
629 ops->cleanup(serialize_data);
630 g_free(args);
633 static void test_nested_struct_list(gconstpointer opaque)
635 TestArgs *args = (TestArgs *) opaque;
636 const SerializeOps *ops = args->ops;
637 UserDefTwoList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
638 void *serialize_data;
639 int i = 0;
641 for (i = 0; i < 8; i++) {
642 QAPI_LIST_PREPEND(listp, nested_struct_create());
645 ops->serialize(listp, &serialize_data, visit_nested_struct_list,
646 &error_abort);
647 ops->deserialize((void **)&listp_copy, serialize_data,
648 visit_nested_struct_list, &error_abort);
650 tmp = listp;
651 tmp_copy = listp_copy;
652 while (listp_copy) {
653 g_assert(listp);
654 nested_struct_compare(listp->value, listp_copy->value);
655 listp = listp->next;
656 listp_copy = listp_copy->next;
659 qapi_free_UserDefTwoList(tmp);
660 qapi_free_UserDefTwoList(tmp_copy);
662 ops->cleanup(serialize_data);
663 g_free(args);
666 static PrimitiveType pt_values[] = {
667 /* string tests */
669 .description = "string_empty",
670 .type = PTYPE_STRING,
671 .value.string = "",
674 .description = "string_whitespace",
675 .type = PTYPE_STRING,
676 .value.string = "a b c\td",
679 .description = "string_newlines",
680 .type = PTYPE_STRING,
681 .value.string = "a\nb\n",
684 .description = "string_commas",
685 .type = PTYPE_STRING,
686 .value.string = "a,b, c,d",
689 .description = "string_single_quoted",
690 .type = PTYPE_STRING,
691 .value.string = "'a b',cd",
694 .description = "string_double_quoted",
695 .type = PTYPE_STRING,
696 .value.string = "\"a b\",cd",
698 /* boolean tests */
700 .description = "boolean_true1",
701 .type = PTYPE_BOOLEAN,
702 .value.boolean = true,
705 .description = "boolean_true2",
706 .type = PTYPE_BOOLEAN,
707 .value.boolean = 8,
710 .description = "boolean_true3",
711 .type = PTYPE_BOOLEAN,
712 .value.boolean = -1,
715 .description = "boolean_false1",
716 .type = PTYPE_BOOLEAN,
717 .value.boolean = false,
720 .description = "boolean_false2",
721 .type = PTYPE_BOOLEAN,
722 .value.boolean = 0,
724 /* number tests (double) */
726 .description = "number_sanity1",
727 .type = PTYPE_NUMBER,
728 .value.number = -1,
731 .description = "number_sanity2",
732 .type = PTYPE_NUMBER,
733 .value.number = 3.141593,
736 .description = "number_min",
737 .type = PTYPE_NUMBER,
738 .value.number = DBL_MIN,
741 .description = "number_max",
742 .type = PTYPE_NUMBER,
743 .value.number = DBL_MAX,
745 /* integer tests (int64) */
747 .description = "integer_sanity1",
748 .type = PTYPE_INTEGER,
749 .value.integer = -1,
752 .description = "integer_sanity2",
753 .type = PTYPE_INTEGER,
754 .value.integer = INT64_MAX / 2 + 1,
757 .description = "integer_min",
758 .type = PTYPE_INTEGER,
759 .value.integer = INT64_MIN,
762 .description = "integer_max",
763 .type = PTYPE_INTEGER,
764 .value.integer = INT64_MAX,
766 /* uint8 tests */
768 .description = "uint8_sanity1",
769 .type = PTYPE_U8,
770 .value.u8 = 1,
773 .description = "uint8_sanity2",
774 .type = PTYPE_U8,
775 .value.u8 = UINT8_MAX / 2 + 1,
778 .description = "uint8_min",
779 .type = PTYPE_U8,
780 .value.u8 = 0,
783 .description = "uint8_max",
784 .type = PTYPE_U8,
785 .value.u8 = UINT8_MAX,
787 /* uint16 tests */
789 .description = "uint16_sanity1",
790 .type = PTYPE_U16,
791 .value.u16 = 1,
794 .description = "uint16_sanity2",
795 .type = PTYPE_U16,
796 .value.u16 = UINT16_MAX / 2 + 1,
799 .description = "uint16_min",
800 .type = PTYPE_U16,
801 .value.u16 = 0,
804 .description = "uint16_max",
805 .type = PTYPE_U16,
806 .value.u16 = UINT16_MAX,
808 /* uint32 tests */
810 .description = "uint32_sanity1",
811 .type = PTYPE_U32,
812 .value.u32 = 1,
815 .description = "uint32_sanity2",
816 .type = PTYPE_U32,
817 .value.u32 = UINT32_MAX / 2 + 1,
820 .description = "uint32_min",
821 .type = PTYPE_U32,
822 .value.u32 = 0,
825 .description = "uint32_max",
826 .type = PTYPE_U32,
827 .value.u32 = UINT32_MAX,
829 /* uint64 tests */
831 .description = "uint64_sanity1",
832 .type = PTYPE_U64,
833 .value.u64 = 1,
836 .description = "uint64_sanity2",
837 .type = PTYPE_U64,
838 .value.u64 = UINT64_MAX / 2 + 1,
841 .description = "uint64_min",
842 .type = PTYPE_U64,
843 .value.u64 = 0,
846 .description = "uint64_max",
847 .type = PTYPE_U64,
848 .value.u64 = UINT64_MAX,
850 /* int8 tests */
852 .description = "int8_sanity1",
853 .type = PTYPE_S8,
854 .value.s8 = -1,
857 .description = "int8_sanity2",
858 .type = PTYPE_S8,
859 .value.s8 = INT8_MAX / 2 + 1,
862 .description = "int8_min",
863 .type = PTYPE_S8,
864 .value.s8 = INT8_MIN,
867 .description = "int8_max",
868 .type = PTYPE_S8,
869 .value.s8 = INT8_MAX,
871 /* int16 tests */
873 .description = "int16_sanity1",
874 .type = PTYPE_S16,
875 .value.s16 = -1,
878 .description = "int16_sanity2",
879 .type = PTYPE_S16,
880 .value.s16 = INT16_MAX / 2 + 1,
883 .description = "int16_min",
884 .type = PTYPE_S16,
885 .value.s16 = INT16_MIN,
888 .description = "int16_max",
889 .type = PTYPE_S16,
890 .value.s16 = INT16_MAX,
892 /* int32 tests */
894 .description = "int32_sanity1",
895 .type = PTYPE_S32,
896 .value.s32 = -1,
899 .description = "int32_sanity2",
900 .type = PTYPE_S32,
901 .value.s32 = INT32_MAX / 2 + 1,
904 .description = "int32_min",
905 .type = PTYPE_S32,
906 .value.s32 = INT32_MIN,
909 .description = "int32_max",
910 .type = PTYPE_S32,
911 .value.s32 = INT32_MAX,
913 /* int64 tests */
915 .description = "int64_sanity1",
916 .type = PTYPE_S64,
917 .value.s64 = -1,
920 .description = "int64_sanity2",
921 .type = PTYPE_S64,
922 .value.s64 = INT64_MAX / 2 + 1,
925 .description = "int64_min",
926 .type = PTYPE_S64,
927 .value.s64 = INT64_MIN,
930 .description = "int64_max",
931 .type = PTYPE_S64,
932 .value.s64 = INT64_MAX,
934 { .type = PTYPE_EOL }
937 /* visitor-specific op implementations */
939 typedef struct QmpSerializeData {
940 Visitor *qov;
941 QObject *obj;
942 Visitor *qiv;
943 } QmpSerializeData;
945 static void qmp_serialize(void *native_in, void **datap,
946 VisitorFunc visit, Error **errp)
948 QmpSerializeData *d = g_malloc0(sizeof(*d));
950 d->qov = qobject_output_visitor_new(&d->obj);
951 visit(d->qov, &native_in, errp);
952 *datap = d;
955 static void qmp_deserialize(void **native_out, void *datap,
956 VisitorFunc visit, Error **errp)
958 QmpSerializeData *d = datap;
959 GString *output_json;
960 QObject *obj_orig, *obj;
962 visit_complete(d->qov, &d->obj);
963 obj_orig = d->obj;
964 output_json = qobject_to_json(obj_orig);
965 obj = qobject_from_json(output_json->str, &error_abort);
967 g_string_free(output_json, true);
968 d->qiv = qobject_input_visitor_new(obj);
969 qobject_unref(obj_orig);
970 qobject_unref(obj);
971 visit(d->qiv, native_out, errp);
974 static void qmp_cleanup(void *datap)
976 QmpSerializeData *d = datap;
977 visit_free(d->qov);
978 visit_free(d->qiv);
980 g_free(d);
983 typedef struct StringSerializeData {
984 char *string;
985 Visitor *sov;
986 Visitor *siv;
987 } StringSerializeData;
989 static void string_serialize(void *native_in, void **datap,
990 VisitorFunc visit, Error **errp)
992 StringSerializeData *d = g_malloc0(sizeof(*d));
994 d->sov = string_output_visitor_new(false, &d->string);
995 visit(d->sov, &native_in, errp);
996 *datap = d;
999 static void string_deserialize(void **native_out, void *datap,
1000 VisitorFunc visit, Error **errp)
1002 StringSerializeData *d = datap;
1004 visit_complete(d->sov, &d->string);
1005 d->siv = string_input_visitor_new(d->string);
1006 visit(d->siv, native_out, errp);
1009 static void string_cleanup(void *datap)
1011 StringSerializeData *d = datap;
1013 visit_free(d->sov);
1014 visit_free(d->siv);
1015 g_free(d->string);
1016 g_free(d);
1019 /* visitor registration, test harness */
1021 /* note: to function interchangeably as a serialization mechanism your
1022 * visitor test implementation should pass the test cases for all visitor
1023 * capabilities: primitives, structures, and lists
1025 static const SerializeOps visitors[] = {
1027 .type = "QMP",
1028 .serialize = qmp_serialize,
1029 .deserialize = qmp_deserialize,
1030 .cleanup = qmp_cleanup,
1031 .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS |
1032 VCAP_PRIMITIVE_LISTS
1035 .type = "String",
1036 .serialize = string_serialize,
1037 .deserialize = string_deserialize,
1038 .cleanup = string_cleanup,
1039 .caps = VCAP_PRIMITIVES
1041 { NULL }
1044 static void add_visitor_type(const SerializeOps *ops)
1046 char testname_prefix[32];
1047 char testname[128];
1048 TestArgs *args;
1049 int i = 0;
1051 sprintf(testname_prefix, "/visitor/serialization/%s", ops->type);
1053 if (ops->caps & VCAP_PRIMITIVES) {
1054 while (pt_values[i].type != PTYPE_EOL) {
1055 sprintf(testname, "%s/primitives/%s", testname_prefix,
1056 pt_values[i].description);
1057 args = g_malloc0(sizeof(*args));
1058 args->ops = ops;
1059 args->test_data = &pt_values[i];
1060 g_test_add_data_func(testname, args, test_primitives);
1061 i++;
1065 if (ops->caps & VCAP_STRUCTURES) {
1066 sprintf(testname, "%s/struct", testname_prefix);
1067 args = g_malloc0(sizeof(*args));
1068 args->ops = ops;
1069 args->test_data = NULL;
1070 g_test_add_data_func(testname, args, test_struct);
1072 sprintf(testname, "%s/nested_struct", testname_prefix);
1073 args = g_malloc0(sizeof(*args));
1074 args->ops = ops;
1075 args->test_data = NULL;
1076 g_test_add_data_func(testname, args, test_nested_struct);
1079 if (ops->caps & VCAP_LISTS) {
1080 sprintf(testname, "%s/nested_struct_list", testname_prefix);
1081 args = g_malloc0(sizeof(*args));
1082 args->ops = ops;
1083 args->test_data = NULL;
1084 g_test_add_data_func(testname, args, test_nested_struct_list);
1087 if (ops->caps & VCAP_PRIMITIVE_LISTS) {
1088 i = 0;
1089 while (pt_values[i].type != PTYPE_EOL) {
1090 sprintf(testname, "%s/primitive_list/%s", testname_prefix,
1091 pt_values[i].description);
1092 args = g_malloc0(sizeof(*args));
1093 args->ops = ops;
1094 args->test_data = &pt_values[i];
1095 g_test_add_data_func(testname, args, test_primitive_lists);
1096 i++;
1101 int main(int argc, char **argv)
1103 int i = 0;
1105 g_test_init(&argc, &argv, NULL);
1107 while (visitors[i].type != NULL) {
1108 add_visitor_type(&visitors[i]);
1109 i++;
1112 g_test_run();
1114 return 0;