1
2
3
4
5
6
7
8
9
10
11
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
31enum 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
47typedef 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
67typedef 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
87
88typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
89
90static 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
99static 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
144static 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
190static 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
199static 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
208static void struct_cleanup(TestStruct *ts)
209{
210 g_free(ts->string);
211 g_free(ts);
212}
213
214static void visit_struct(Visitor *v, void **native, Error **errp)
215{
216 visit_type_TestStruct(v, NULL, (TestStruct **)native, errp);
217}
218
219static 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
239static 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
260static void nested_struct_cleanup(UserDefTwo *udnp)
261{
262 qapi_free_UserDefTwo(udnp);
263}
264
265static void visit_nested_struct(Visitor *v, void **native, Error **errp)
266{
267 visit_type_UserDefTwo(v, NULL, (UserDefTwo **)native, errp);
268}
269
270static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
271{
272 visit_type_UserDefTwoList(v, NULL, (UserDefTwoList **)native, errp);
273}
274
275
276
277typedef enum VisitorCapabilities {
278 VCAP_PRIMITIVES = 1,
279 VCAP_STRUCTURES = 2,
280 VCAP_LISTS = 4,
281 VCAP_PRIMITIVE_LISTS = 8,
282} VisitorCapabilities;
283
284typedef 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
294typedef struct TestArgs {
295 const SerializeOps *ops;
296 void *test_data;
297} TestArgs;
298
299static 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
320
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
339static 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
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
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
624
625
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
659static 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
680static 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
701static 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
737static PrimitiveType pt_values[] = {
738
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
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
796
797
798
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
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
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
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
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
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
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
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
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
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
1013
1014typedef struct QmpSerializeData {
1015 QmpOutputVisitor *qov;
1016 QmpInputVisitor *qiv;
1017} QmpSerializeData;
1018
1019static 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
1029static 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, true);
1042 qobject_decref(obj_orig);
1043 qobject_decref(obj);
1044 visit(qmp_input_get_visitor(d->qiv), native_out, errp);
1045}
1046
1047static 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
1056typedef struct StringSerializeData {
1057 char *string;
1058 StringOutputVisitor *sov;
1059 StringInputVisitor *siv;
1060} StringSerializeData;
1061
1062static 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
1072static 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
1082static 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
1093
1094
1095
1096
1097
1098static 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
1117static 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
1174int 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}
1189