2 * Unit-tests for visitor-based serialization
4 * Copyright (C) 2014-2015 Red Hat, Inc.
5 * Copyright IBM, Corp. 2012
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.
19 #include "qemu-common.h"
20 #include "test-qapi-types.h"
21 #include "test-qapi-visit.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"
31 enum PrimitiveTypeKind
{
47 typedef struct PrimitiveType
{
63 enum PrimitiveTypeKind type
;
64 const char *description
;
67 typedef struct PrimitiveList
{
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
;
82 enum PrimitiveTypeKind type
;
83 const char *description
;
88 typedef void (*VisitorFunc
)(Visitor
*v
, void **native
, Error
**errp
);
90 static void dealloc_helper(void *native_in
, VisitorFunc visit
, Error
**errp
)
92 QapiDeallocVisitor
*qdv
= qapi_dealloc_visitor_new();
94 visit(qapi_dealloc_get_visitor(qdv
), &native_in
, errp
);
96 qapi_dealloc_visitor_cleanup(qdv
);
99 static void visit_primitive_type(Visitor
*v
, void **native
, Error
**errp
)
101 PrimitiveType
*pt
= *native
;
104 visit_type_str(v
, (char **)&pt
->value
.string
, NULL
, errp
);
107 visit_type_bool(v
, &pt
->value
.boolean
, NULL
, errp
);
110 visit_type_number(v
, &pt
->value
.number
, NULL
, errp
);
113 visit_type_int(v
, &pt
->value
.integer
, NULL
, errp
);
116 visit_type_uint8(v
, &pt
->value
.u8
, NULL
, errp
);
119 visit_type_uint16(v
, &pt
->value
.u16
, NULL
, errp
);
122 visit_type_uint32(v
, &pt
->value
.u32
, NULL
, errp
);
125 visit_type_uint64(v
, &pt
->value
.u64
, NULL
, errp
);
128 visit_type_int8(v
, &pt
->value
.s8
, NULL
, errp
);
131 visit_type_int16(v
, &pt
->value
.s16
, NULL
, errp
);
134 visit_type_int32(v
, &pt
->value
.s32
, NULL
, errp
);
137 visit_type_int64(v
, &pt
->value
.s64
, NULL
, errp
);
140 g_assert_not_reached();
144 static void visit_primitive_list(Visitor
*v
, void **native
, Error
**errp
)
146 PrimitiveList
*pl
= *native
;
149 visit_type_strList(v
, &pl
->value
.strings
, NULL
, errp
);
152 visit_type_boolList(v
, &pl
->value
.booleans
, NULL
, errp
);
155 visit_type_numberList(v
, &pl
->value
.numbers
, NULL
, errp
);
158 visit_type_intList(v
, &pl
->value
.integers
, NULL
, errp
);
161 visit_type_int8List(v
, &pl
->value
.s8_integers
, NULL
, errp
);
164 visit_type_int16List(v
, &pl
->value
.s16_integers
, NULL
, errp
);
167 visit_type_int32List(v
, &pl
->value
.s32_integers
, NULL
, errp
);
170 visit_type_int64List(v
, &pl
->value
.s64_integers
, NULL
, errp
);
173 visit_type_uint8List(v
, &pl
->value
.u8_integers
, NULL
, errp
);
176 visit_type_uint16List(v
, &pl
->value
.u16_integers
, NULL
, errp
);
179 visit_type_uint32List(v
, &pl
->value
.u32_integers
, NULL
, errp
);
182 visit_type_uint64List(v
, &pl
->value
.u64_integers
, NULL
, errp
);
185 g_assert_not_reached();
189 typedef struct TestStruct
196 static void visit_type_TestStruct(Visitor
*v
, TestStruct
**obj
,
197 const char *name
, Error
**errp
)
201 visit_start_struct(v
, (void **)obj
, NULL
, name
, sizeof(TestStruct
), &err
);
206 visit_type_int(v
, &(*obj
)->integer
, "integer", &err
);
210 visit_type_bool(v
, &(*obj
)->boolean
, "boolean", &err
);
214 visit_type_str(v
, &(*obj
)->string
, "string", &err
);
217 error_propagate(errp
, err
);
219 visit_end_struct(v
, &err
);
221 error_propagate(errp
, err
);
224 static TestStruct
*struct_create(void)
226 TestStruct
*ts
= g_malloc0(sizeof(*ts
));
229 ts
->string
= strdup("test string");
233 static void struct_compare(TestStruct
*ts1
, TestStruct
*ts2
)
237 g_assert_cmpint(ts1
->integer
, ==, ts2
->integer
);
238 g_assert(ts1
->boolean
== ts2
->boolean
);
239 g_assert_cmpstr(ts1
->string
, ==, ts2
->string
);
242 static void struct_cleanup(TestStruct
*ts
)
248 static void visit_struct(Visitor
*v
, void **native
, Error
**errp
)
250 visit_type_TestStruct(v
, (TestStruct
**)native
, NULL
, errp
);
253 static UserDefTwo
*nested_struct_create(void)
255 UserDefTwo
*udnp
= g_malloc0(sizeof(*udnp
));
256 udnp
->string0
= strdup("test_string0");
257 udnp
->dict1
= g_malloc0(sizeof(*udnp
->dict1
));
258 udnp
->dict1
->string1
= strdup("test_string1");
259 udnp
->dict1
->dict2
= g_malloc0(sizeof(*udnp
->dict1
->dict2
));
260 udnp
->dict1
->dict2
->userdef
= g_new0(UserDefOne
, 1);
261 udnp
->dict1
->dict2
->userdef
->base
= g_new0(UserDefZero
, 1);
262 udnp
->dict1
->dict2
->userdef
->base
->integer
= 42;
263 udnp
->dict1
->dict2
->userdef
->string
= strdup("test_string");
264 udnp
->dict1
->dict2
->string
= strdup("test_string2");
265 udnp
->dict1
->dict3
= g_malloc0(sizeof(*udnp
->dict1
->dict3
));
266 udnp
->dict1
->has_dict3
= true;
267 udnp
->dict1
->dict3
->userdef
= g_new0(UserDefOne
, 1);
268 udnp
->dict1
->dict3
->userdef
->base
= g_new0(UserDefZero
, 1);
269 udnp
->dict1
->dict3
->userdef
->base
->integer
= 43;
270 udnp
->dict1
->dict3
->userdef
->string
= strdup("test_string");
271 udnp
->dict1
->dict3
->string
= strdup("test_string3");
275 static void nested_struct_compare(UserDefTwo
*udnp1
, UserDefTwo
*udnp2
)
279 g_assert_cmpstr(udnp1
->string0
, ==, udnp2
->string0
);
280 g_assert_cmpstr(udnp1
->dict1
->string1
, ==, udnp2
->dict1
->string1
);
281 g_assert_cmpint(udnp1
->dict1
->dict2
->userdef
->base
->integer
, ==,
282 udnp2
->dict1
->dict2
->userdef
->base
->integer
);
283 g_assert_cmpstr(udnp1
->dict1
->dict2
->userdef
->string
, ==,
284 udnp2
->dict1
->dict2
->userdef
->string
);
285 g_assert_cmpstr(udnp1
->dict1
->dict2
->string
, ==,
286 udnp2
->dict1
->dict2
->string
);
287 g_assert(udnp1
->dict1
->has_dict3
== udnp2
->dict1
->has_dict3
);
288 g_assert_cmpint(udnp1
->dict1
->dict3
->userdef
->base
->integer
, ==,
289 udnp2
->dict1
->dict3
->userdef
->base
->integer
);
290 g_assert_cmpstr(udnp1
->dict1
->dict3
->userdef
->string
, ==,
291 udnp2
->dict1
->dict3
->userdef
->string
);
292 g_assert_cmpstr(udnp1
->dict1
->dict3
->string
, ==,
293 udnp2
->dict1
->dict3
->string
);
296 static void nested_struct_cleanup(UserDefTwo
*udnp
)
298 qapi_free_UserDefTwo(udnp
);
301 static void visit_nested_struct(Visitor
*v
, void **native
, Error
**errp
)
303 visit_type_UserDefTwo(v
, (UserDefTwo
**)native
, NULL
, errp
);
306 static void visit_nested_struct_list(Visitor
*v
, void **native
, Error
**errp
)
308 visit_type_UserDefTwoList(v
, (UserDefTwoList
**)native
, NULL
, errp
);
313 typedef enum VisitorCapabilities
{
317 VCAP_PRIMITIVE_LISTS
= 8,
318 } VisitorCapabilities
;
320 typedef struct SerializeOps
{
321 void (*serialize
)(void *native_in
, void **datap
,
322 VisitorFunc visit
, Error
**errp
);
323 void (*deserialize
)(void **native_out
, void *datap
,
324 VisitorFunc visit
, Error
**errp
);
325 void (*cleanup
)(void *datap
);
327 VisitorCapabilities caps
;
330 typedef struct TestArgs
{
331 const SerializeOps
*ops
;
335 static void test_primitives(gconstpointer opaque
)
337 TestArgs
*args
= (TestArgs
*) opaque
;
338 const SerializeOps
*ops
= args
->ops
;
339 PrimitiveType
*pt
= args
->test_data
;
340 PrimitiveType
*pt_copy
= g_malloc0(sizeof(*pt_copy
));
342 void *serialize_data
;
344 pt_copy
->type
= pt
->type
;
345 ops
->serialize(pt
, &serialize_data
, visit_primitive_type
, &err
);
346 ops
->deserialize((void **)&pt_copy
, serialize_data
, visit_primitive_type
, &err
);
348 g_assert(err
== NULL
);
349 g_assert(pt_copy
!= NULL
);
350 if (pt
->type
== PTYPE_STRING
) {
351 g_assert_cmpstr(pt
->value
.string
, ==, pt_copy
->value
.string
);
352 g_free((char *)pt_copy
->value
.string
);
353 } else if (pt
->type
== PTYPE_NUMBER
) {
354 GString
*double_expected
= g_string_new("");
355 GString
*double_actual
= g_string_new("");
356 /* we serialize with %f for our reference visitors, so rather than fuzzy
357 * floating math to test "equality", just compare the formatted values
359 g_string_printf(double_expected
, "%.6f", pt
->value
.number
);
360 g_string_printf(double_actual
, "%.6f", pt_copy
->value
.number
);
361 g_assert_cmpstr(double_actual
->str
, ==, double_expected
->str
);
363 g_string_free(double_expected
, true);
364 g_string_free(double_actual
, true);
365 } else if (pt
->type
== PTYPE_BOOLEAN
) {
366 g_assert_cmpint(!!pt
->value
.max
, ==, !!pt
->value
.max
);
368 g_assert_cmpint(pt
->value
.max
, ==, pt_copy
->value
.max
);
371 ops
->cleanup(serialize_data
);
376 static void test_primitive_lists(gconstpointer opaque
)
378 TestArgs
*args
= (TestArgs
*) opaque
;
379 const SerializeOps
*ops
= args
->ops
;
380 PrimitiveType
*pt
= args
->test_data
;
381 PrimitiveList pl
= { .value
= { NULL
} };
382 PrimitiveList pl_copy
= { .value
= { NULL
} };
383 PrimitiveList
*pl_copy_ptr
= &pl_copy
;
385 void *serialize_data
;
386 void *cur_head
= NULL
;
389 pl
.type
= pl_copy
.type
= pt
->type
;
391 /* build up our list of primitive types */
392 for (i
= 0; i
< 32; i
++) {
395 strList
*tmp
= g_new0(strList
, 1);
396 tmp
->value
= g_strdup(pt
->value
.string
);
397 if (pl
.value
.strings
== NULL
) {
398 pl
.value
.strings
= tmp
;
400 tmp
->next
= pl
.value
.strings
;
401 pl
.value
.strings
= tmp
;
405 case PTYPE_INTEGER
: {
406 intList
*tmp
= g_new0(intList
, 1);
407 tmp
->value
= pt
->value
.integer
;
408 if (pl
.value
.integers
== NULL
) {
409 pl
.value
.integers
= tmp
;
411 tmp
->next
= pl
.value
.integers
;
412 pl
.value
.integers
= tmp
;
417 int8List
*tmp
= g_new0(int8List
, 1);
418 tmp
->value
= pt
->value
.s8
;
419 if (pl
.value
.s8_integers
== NULL
) {
420 pl
.value
.s8_integers
= tmp
;
422 tmp
->next
= pl
.value
.s8_integers
;
423 pl
.value
.s8_integers
= tmp
;
428 int16List
*tmp
= g_new0(int16List
, 1);
429 tmp
->value
= pt
->value
.s16
;
430 if (pl
.value
.s16_integers
== NULL
) {
431 pl
.value
.s16_integers
= tmp
;
433 tmp
->next
= pl
.value
.s16_integers
;
434 pl
.value
.s16_integers
= tmp
;
439 int32List
*tmp
= g_new0(int32List
, 1);
440 tmp
->value
= pt
->value
.s32
;
441 if (pl
.value
.s32_integers
== NULL
) {
442 pl
.value
.s32_integers
= tmp
;
444 tmp
->next
= pl
.value
.s32_integers
;
445 pl
.value
.s32_integers
= tmp
;
450 int64List
*tmp
= g_new0(int64List
, 1);
451 tmp
->value
= pt
->value
.s64
;
452 if (pl
.value
.s64_integers
== NULL
) {
453 pl
.value
.s64_integers
= tmp
;
455 tmp
->next
= pl
.value
.s64_integers
;
456 pl
.value
.s64_integers
= tmp
;
461 uint8List
*tmp
= g_new0(uint8List
, 1);
462 tmp
->value
= pt
->value
.u8
;
463 if (pl
.value
.u8_integers
== NULL
) {
464 pl
.value
.u8_integers
= tmp
;
466 tmp
->next
= pl
.value
.u8_integers
;
467 pl
.value
.u8_integers
= tmp
;
472 uint16List
*tmp
= g_new0(uint16List
, 1);
473 tmp
->value
= pt
->value
.u16
;
474 if (pl
.value
.u16_integers
== NULL
) {
475 pl
.value
.u16_integers
= tmp
;
477 tmp
->next
= pl
.value
.u16_integers
;
478 pl
.value
.u16_integers
= tmp
;
483 uint32List
*tmp
= g_new0(uint32List
, 1);
484 tmp
->value
= pt
->value
.u32
;
485 if (pl
.value
.u32_integers
== NULL
) {
486 pl
.value
.u32_integers
= tmp
;
488 tmp
->next
= pl
.value
.u32_integers
;
489 pl
.value
.u32_integers
= tmp
;
494 uint64List
*tmp
= g_new0(uint64List
, 1);
495 tmp
->value
= pt
->value
.u64
;
496 if (pl
.value
.u64_integers
== NULL
) {
497 pl
.value
.u64_integers
= tmp
;
499 tmp
->next
= pl
.value
.u64_integers
;
500 pl
.value
.u64_integers
= tmp
;
505 numberList
*tmp
= g_new0(numberList
, 1);
506 tmp
->value
= pt
->value
.number
;
507 if (pl
.value
.numbers
== NULL
) {
508 pl
.value
.numbers
= tmp
;
510 tmp
->next
= pl
.value
.numbers
;
511 pl
.value
.numbers
= tmp
;
515 case PTYPE_BOOLEAN
: {
516 boolList
*tmp
= g_new0(boolList
, 1);
517 tmp
->value
= pt
->value
.boolean
;
518 if (pl
.value
.booleans
== NULL
) {
519 pl
.value
.booleans
= tmp
;
521 tmp
->next
= pl
.value
.booleans
;
522 pl
.value
.booleans
= tmp
;
527 g_assert_not_reached();
531 ops
->serialize((void **)&pl
, &serialize_data
, visit_primitive_list
, &err
);
532 ops
->deserialize((void **)&pl_copy_ptr
, serialize_data
, visit_primitive_list
, &err
);
534 g_assert(err
== NULL
);
537 /* compare our deserialized list of primitives to the original */
539 switch (pl_copy
.type
) {
544 cur_head
= ptr
->next
;
546 cur_head
= ptr
= pl_copy
.value
.strings
;
548 g_assert_cmpstr(pt
->value
.string
, ==, ptr
->value
);
551 case PTYPE_INTEGER
: {
555 cur_head
= ptr
->next
;
557 cur_head
= ptr
= pl_copy
.value
.integers
;
559 g_assert_cmpint(pt
->value
.integer
, ==, ptr
->value
);
566 cur_head
= ptr
->next
;
568 cur_head
= ptr
= pl_copy
.value
.s8_integers
;
570 g_assert_cmpint(pt
->value
.s8
, ==, ptr
->value
);
577 cur_head
= ptr
->next
;
579 cur_head
= ptr
= pl_copy
.value
.s16_integers
;
581 g_assert_cmpint(pt
->value
.s16
, ==, ptr
->value
);
588 cur_head
= ptr
->next
;
590 cur_head
= ptr
= pl_copy
.value
.s32_integers
;
592 g_assert_cmpint(pt
->value
.s32
, ==, ptr
->value
);
599 cur_head
= ptr
->next
;
601 cur_head
= ptr
= pl_copy
.value
.s64_integers
;
603 g_assert_cmpint(pt
->value
.s64
, ==, ptr
->value
);
610 cur_head
= ptr
->next
;
612 cur_head
= ptr
= pl_copy
.value
.u8_integers
;
614 g_assert_cmpint(pt
->value
.u8
, ==, ptr
->value
);
621 cur_head
= ptr
->next
;
623 cur_head
= ptr
= pl_copy
.value
.u16_integers
;
625 g_assert_cmpint(pt
->value
.u16
, ==, ptr
->value
);
632 cur_head
= ptr
->next
;
634 cur_head
= ptr
= pl_copy
.value
.u32_integers
;
636 g_assert_cmpint(pt
->value
.u32
, ==, ptr
->value
);
643 cur_head
= ptr
->next
;
645 cur_head
= ptr
= pl_copy
.value
.u64_integers
;
647 g_assert_cmpint(pt
->value
.u64
, ==, ptr
->value
);
652 GString
*double_expected
= g_string_new("");
653 GString
*double_actual
= g_string_new("");
656 cur_head
= ptr
->next
;
658 cur_head
= ptr
= pl_copy
.value
.numbers
;
660 /* we serialize with %f for our reference visitors, so rather than
661 * fuzzy floating math to test "equality", just compare the
664 g_string_printf(double_expected
, "%.6f", pt
->value
.number
);
665 g_string_printf(double_actual
, "%.6f", ptr
->value
);
666 g_assert_cmpstr(double_actual
->str
, ==, double_expected
->str
);
667 g_string_free(double_expected
, true);
668 g_string_free(double_actual
, true);
671 case PTYPE_BOOLEAN
: {
675 cur_head
= ptr
->next
;
677 cur_head
= ptr
= pl_copy
.value
.booleans
;
679 g_assert_cmpint(!!pt
->value
.boolean
, ==, !!ptr
->value
);
683 g_assert_not_reached();
688 g_assert_cmpint(i
, ==, 33);
690 ops
->cleanup(serialize_data
);
691 dealloc_helper(&pl
, visit_primitive_list
, &err
);
693 dealloc_helper(&pl_copy
, visit_primitive_list
, &err
);
698 static void test_struct(gconstpointer opaque
)
700 TestArgs
*args
= (TestArgs
*) opaque
;
701 const SerializeOps
*ops
= args
->ops
;
702 TestStruct
*ts
= struct_create();
703 TestStruct
*ts_copy
= NULL
;
705 void *serialize_data
;
707 ops
->serialize(ts
, &serialize_data
, visit_struct
, &err
);
708 ops
->deserialize((void **)&ts_copy
, serialize_data
, visit_struct
, &err
);
710 g_assert(err
== NULL
);
711 struct_compare(ts
, ts_copy
);
714 struct_cleanup(ts_copy
);
716 ops
->cleanup(serialize_data
);
720 static void test_nested_struct(gconstpointer opaque
)
722 TestArgs
*args
= (TestArgs
*) opaque
;
723 const SerializeOps
*ops
= args
->ops
;
724 UserDefTwo
*udnp
= nested_struct_create();
725 UserDefTwo
*udnp_copy
= NULL
;
727 void *serialize_data
;
729 ops
->serialize(udnp
, &serialize_data
, visit_nested_struct
, &err
);
730 ops
->deserialize((void **)&udnp_copy
, serialize_data
, visit_nested_struct
,
733 g_assert(err
== NULL
);
734 nested_struct_compare(udnp
, udnp_copy
);
736 nested_struct_cleanup(udnp
);
737 nested_struct_cleanup(udnp_copy
);
739 ops
->cleanup(serialize_data
);
743 static void test_nested_struct_list(gconstpointer opaque
)
745 TestArgs
*args
= (TestArgs
*) opaque
;
746 const SerializeOps
*ops
= args
->ops
;
747 UserDefTwoList
*listp
= NULL
, *tmp
, *tmp_copy
, *listp_copy
= NULL
;
749 void *serialize_data
;
752 for (i
= 0; i
< 8; i
++) {
753 tmp
= g_new0(UserDefTwoList
, 1);
754 tmp
->value
= nested_struct_create();
759 ops
->serialize(listp
, &serialize_data
, visit_nested_struct_list
, &err
);
760 ops
->deserialize((void **)&listp_copy
, serialize_data
,
761 visit_nested_struct_list
, &err
);
763 g_assert(err
== NULL
);
766 tmp_copy
= listp_copy
;
769 nested_struct_compare(listp
->value
, listp_copy
->value
);
771 listp_copy
= listp_copy
->next
;
774 qapi_free_UserDefTwoList(tmp
);
775 qapi_free_UserDefTwoList(tmp_copy
);
777 ops
->cleanup(serialize_data
);
781 static PrimitiveType pt_values
[] = {
784 .description
= "string_empty",
785 .type
= PTYPE_STRING
,
789 .description
= "string_whitespace",
790 .type
= PTYPE_STRING
,
791 .value
.string
= "a b c\td",
794 .description
= "string_newlines",
795 .type
= PTYPE_STRING
,
796 .value
.string
= "a\nb\n",
799 .description
= "string_commas",
800 .type
= PTYPE_STRING
,
801 .value
.string
= "a,b, c,d",
804 .description
= "string_single_quoted",
805 .type
= PTYPE_STRING
,
806 .value
.string
= "'a b',cd",
809 .description
= "string_double_quoted",
810 .type
= PTYPE_STRING
,
811 .value
.string
= "\"a b\",cd",
815 .description
= "boolean_true1",
816 .type
= PTYPE_BOOLEAN
,
817 .value
.boolean
= true,
820 .description
= "boolean_true2",
821 .type
= PTYPE_BOOLEAN
,
825 .description
= "boolean_true3",
826 .type
= PTYPE_BOOLEAN
,
830 .description
= "boolean_false1",
831 .type
= PTYPE_BOOLEAN
,
832 .value
.boolean
= false,
835 .description
= "boolean_false2",
836 .type
= PTYPE_BOOLEAN
,
839 /* number tests (double) */
840 /* note: we format these to %.6f before comparing, since that's how
841 * we serialize them and it doesn't make sense to check precision
845 .description
= "number_sanity1",
846 .type
= PTYPE_NUMBER
,
850 .description
= "number_sanity2",
851 .type
= PTYPE_NUMBER
,
852 .value
.number
= 3.14159265,
855 .description
= "number_min",
856 .type
= PTYPE_NUMBER
,
857 .value
.number
= DBL_MIN
,
860 .description
= "number_max",
861 .type
= PTYPE_NUMBER
,
862 .value
.number
= DBL_MAX
,
864 /* integer tests (int64) */
866 .description
= "integer_sanity1",
867 .type
= PTYPE_INTEGER
,
871 .description
= "integer_sanity2",
872 .type
= PTYPE_INTEGER
,
873 .value
.integer
= INT64_MAX
/ 2 + 1,
876 .description
= "integer_min",
877 .type
= PTYPE_INTEGER
,
878 .value
.integer
= INT64_MIN
,
881 .description
= "integer_max",
882 .type
= PTYPE_INTEGER
,
883 .value
.integer
= INT64_MAX
,
887 .description
= "uint8_sanity1",
892 .description
= "uint8_sanity2",
894 .value
.u8
= UINT8_MAX
/ 2 + 1,
897 .description
= "uint8_min",
902 .description
= "uint8_max",
904 .value
.u8
= UINT8_MAX
,
908 .description
= "uint16_sanity1",
913 .description
= "uint16_sanity2",
915 .value
.u16
= UINT16_MAX
/ 2 + 1,
918 .description
= "uint16_min",
923 .description
= "uint16_max",
925 .value
.u16
= UINT16_MAX
,
929 .description
= "uint32_sanity1",
934 .description
= "uint32_sanity2",
936 .value
.u32
= UINT32_MAX
/ 2 + 1,
939 .description
= "uint32_min",
944 .description
= "uint32_max",
946 .value
.u32
= UINT32_MAX
,
950 .description
= "uint64_sanity1",
955 .description
= "uint64_sanity2",
957 .value
.u64
= UINT64_MAX
/ 2 + 1,
960 .description
= "uint64_min",
965 .description
= "uint64_max",
967 .value
.u64
= UINT64_MAX
,
971 .description
= "int8_sanity1",
976 .description
= "int8_sanity2",
978 .value
.s8
= INT8_MAX
/ 2 + 1,
981 .description
= "int8_min",
983 .value
.s8
= INT8_MIN
,
986 .description
= "int8_max",
988 .value
.s8
= INT8_MAX
,
992 .description
= "int16_sanity1",
997 .description
= "int16_sanity2",
999 .value
.s16
= INT16_MAX
/ 2 + 1,
1002 .description
= "int16_min",
1004 .value
.s16
= INT16_MIN
,
1007 .description
= "int16_max",
1009 .value
.s16
= INT16_MAX
,
1013 .description
= "int32_sanity1",
1018 .description
= "int32_sanity2",
1020 .value
.s32
= INT32_MAX
/ 2 + 1,
1023 .description
= "int32_min",
1025 .value
.s32
= INT32_MIN
,
1028 .description
= "int32_max",
1030 .value
.s32
= INT32_MAX
,
1034 .description
= "int64_sanity1",
1039 .description
= "int64_sanity2",
1041 .value
.s64
= INT64_MAX
/ 2 + 1,
1044 .description
= "int64_min",
1046 .value
.s64
= INT64_MIN
,
1049 .description
= "int64_max",
1051 .value
.s64
= INT64_MAX
,
1053 { .type
= PTYPE_EOL
}
1056 /* visitor-specific op implementations */
1058 typedef struct QmpSerializeData
{
1059 QmpOutputVisitor
*qov
;
1060 QmpInputVisitor
*qiv
;
1063 static void qmp_serialize(void *native_in
, void **datap
,
1064 VisitorFunc visit
, Error
**errp
)
1066 QmpSerializeData
*d
= g_malloc0(sizeof(*d
));
1068 d
->qov
= qmp_output_visitor_new();
1069 visit(qmp_output_get_visitor(d
->qov
), &native_in
, errp
);
1073 static void qmp_deserialize(void **native_out
, void *datap
,
1074 VisitorFunc visit
, Error
**errp
)
1076 QmpSerializeData
*d
= datap
;
1077 QString
*output_json
;
1078 QObject
*obj_orig
, *obj
;
1080 obj_orig
= qmp_output_get_qobject(d
->qov
);
1081 output_json
= qobject_to_json(obj_orig
);
1082 obj
= qobject_from_json(qstring_get_str(output_json
));
1084 QDECREF(output_json
);
1085 d
->qiv
= qmp_input_visitor_new(obj
);
1086 qobject_decref(obj_orig
);
1087 qobject_decref(obj
);
1088 visit(qmp_input_get_visitor(d
->qiv
), native_out
, errp
);
1091 static void qmp_cleanup(void *datap
)
1093 QmpSerializeData
*d
= datap
;
1094 qmp_output_visitor_cleanup(d
->qov
);
1095 qmp_input_visitor_cleanup(d
->qiv
);
1100 typedef struct StringSerializeData
{
1102 StringOutputVisitor
*sov
;
1103 StringInputVisitor
*siv
;
1104 } StringSerializeData
;
1106 static void string_serialize(void *native_in
, void **datap
,
1107 VisitorFunc visit
, Error
**errp
)
1109 StringSerializeData
*d
= g_malloc0(sizeof(*d
));
1111 d
->sov
= string_output_visitor_new(false);
1112 visit(string_output_get_visitor(d
->sov
), &native_in
, errp
);
1116 static void string_deserialize(void **native_out
, void *datap
,
1117 VisitorFunc visit
, Error
**errp
)
1119 StringSerializeData
*d
= datap
;
1121 d
->string
= string_output_get_string(d
->sov
);
1122 d
->siv
= string_input_visitor_new(d
->string
);
1123 visit(string_input_get_visitor(d
->siv
), native_out
, errp
);
1126 static void string_cleanup(void *datap
)
1128 StringSerializeData
*d
= datap
;
1130 string_output_visitor_cleanup(d
->sov
);
1131 string_input_visitor_cleanup(d
->siv
);
1136 /* visitor registration, test harness */
1138 /* note: to function interchangeably as a serialization mechanism your
1139 * visitor test implementation should pass the test cases for all visitor
1140 * capabilities: primitives, structures, and lists
1142 static const SerializeOps visitors
[] = {
1145 .serialize
= qmp_serialize
,
1146 .deserialize
= qmp_deserialize
,
1147 .cleanup
= qmp_cleanup
,
1148 .caps
= VCAP_PRIMITIVES
| VCAP_STRUCTURES
| VCAP_LISTS
|
1149 VCAP_PRIMITIVE_LISTS
1153 .serialize
= string_serialize
,
1154 .deserialize
= string_deserialize
,
1155 .cleanup
= string_cleanup
,
1156 .caps
= VCAP_PRIMITIVES
1161 static void add_visitor_type(const SerializeOps
*ops
)
1163 char testname_prefix
[128];
1168 sprintf(testname_prefix
, "/visitor/serialization/%s", ops
->type
);
1170 if (ops
->caps
& VCAP_PRIMITIVES
) {
1171 while (pt_values
[i
].type
!= PTYPE_EOL
) {
1172 sprintf(testname
, "%s/primitives/%s", testname_prefix
,
1173 pt_values
[i
].description
);
1174 args
= g_malloc0(sizeof(*args
));
1176 args
->test_data
= &pt_values
[i
];
1177 g_test_add_data_func(testname
, args
, test_primitives
);
1182 if (ops
->caps
& VCAP_STRUCTURES
) {
1183 sprintf(testname
, "%s/struct", testname_prefix
);
1184 args
= g_malloc0(sizeof(*args
));
1186 args
->test_data
= NULL
;
1187 g_test_add_data_func(testname
, args
, test_struct
);
1189 sprintf(testname
, "%s/nested_struct", testname_prefix
);
1190 args
= g_malloc0(sizeof(*args
));
1192 args
->test_data
= NULL
;
1193 g_test_add_data_func(testname
, args
, test_nested_struct
);
1196 if (ops
->caps
& VCAP_LISTS
) {
1197 sprintf(testname
, "%s/nested_struct_list", testname_prefix
);
1198 args
= g_malloc0(sizeof(*args
));
1200 args
->test_data
= NULL
;
1201 g_test_add_data_func(testname
, args
, test_nested_struct_list
);
1204 if (ops
->caps
& VCAP_PRIMITIVE_LISTS
) {
1206 while (pt_values
[i
].type
!= PTYPE_EOL
) {
1207 sprintf(testname
, "%s/primitive_list/%s", testname_prefix
,
1208 pt_values
[i
].description
);
1209 args
= g_malloc0(sizeof(*args
));
1211 args
->test_data
= &pt_values
[i
];
1212 g_test_add_data_func(testname
, args
, test_primitive_lists
);
1218 int main(int argc
, char **argv
)
1222 g_test_init(&argc
, &argv
, NULL
);
1224 while (visitors
[i
].type
!= NULL
) {
1225 add_visitor_type(&visitors
[i
]);