12d496105SMichael Roth /*
22d496105SMichael Roth * Unit-tests for visitor-based serialization
32d496105SMichael Roth *
46446a592SEric Blake * Copyright (C) 2014-2015 Red Hat, Inc.
52d496105SMichael Roth * Copyright IBM, Corp. 2012
62d496105SMichael Roth *
72d496105SMichael Roth * Authors:
82d496105SMichael Roth * Michael Roth <mdroth@linux.vnet.ibm.com>
92d496105SMichael Roth *
102d496105SMichael Roth * This work is licensed under the terms of the GNU GPL, version 2 or later.
112d496105SMichael Roth * See the COPYING file in the top-level directory.
122d496105SMichael Roth */
132d496105SMichael Roth
14681c28a3SPeter Maydell #include "qemu/osdep.h"
152d496105SMichael Roth #include <float.h>
1679ee7df8SPaolo Bonzini
172d496105SMichael Roth #include "test-qapi-visit.h"
18da34e65cSMarkus Armbruster #include "qapi/error.h"
19*407bc4bfSDaniel P. Berrangé #include "qobject/qjson.h"
20*407bc4bfSDaniel P. Berrangé #include "qobject/qstring.h"
21b3db211fSDaniel P. Berrange #include "qapi/qobject-input-visitor.h"
22b3db211fSDaniel P. Berrange #include "qapi/qobject-output-visitor.h"
230d30b0a2SMichael Roth #include "qapi/string-input-visitor.h"
240d30b0a2SMichael Roth #include "qapi/string-output-visitor.h"
258addacddSMichael Roth #include "qapi/dealloc-visitor.h"
268addacddSMichael Roth
278addacddSMichael Roth enum PrimitiveTypeKind {
288addacddSMichael Roth PTYPE_STRING = 0,
298addacddSMichael Roth PTYPE_BOOLEAN,
308addacddSMichael Roth PTYPE_NUMBER,
318addacddSMichael Roth PTYPE_INTEGER,
328addacddSMichael Roth PTYPE_U8,
338addacddSMichael Roth PTYPE_U16,
348addacddSMichael Roth PTYPE_U32,
358addacddSMichael Roth PTYPE_U64,
368addacddSMichael Roth PTYPE_S8,
378addacddSMichael Roth PTYPE_S16,
388addacddSMichael Roth PTYPE_S32,
398addacddSMichael Roth PTYPE_S64,
408addacddSMichael Roth PTYPE_EOL,
418addacddSMichael Roth };
422d496105SMichael Roth
432d496105SMichael Roth typedef struct PrimitiveType {
442d496105SMichael Roth union {
452d496105SMichael Roth const char *string;
462d496105SMichael Roth bool boolean;
472d496105SMichael Roth double number;
482d496105SMichael Roth int64_t integer;
492d496105SMichael Roth uint8_t u8;
502d496105SMichael Roth uint16_t u16;
512d496105SMichael Roth uint32_t u32;
522d496105SMichael Roth uint64_t u64;
532d496105SMichael Roth int8_t s8;
542d496105SMichael Roth int16_t s16;
552d496105SMichael Roth int32_t s32;
562d496105SMichael Roth int64_t s64;
572d496105SMichael Roth } value;
588addacddSMichael Roth enum PrimitiveTypeKind type;
592d496105SMichael Roth const char *description;
602d496105SMichael Roth } PrimitiveType;
612d496105SMichael Roth
628addacddSMichael Roth typedef struct PrimitiveList {
638addacddSMichael Roth union {
648addacddSMichael Roth strList *strings;
658addacddSMichael Roth boolList *booleans;
668addacddSMichael Roth numberList *numbers;
678addacddSMichael Roth intList *integers;
688addacddSMichael Roth int8List *s8_integers;
698addacddSMichael Roth int16List *s16_integers;
708addacddSMichael Roth int32List *s32_integers;
718addacddSMichael Roth int64List *s64_integers;
728addacddSMichael Roth uint8List *u8_integers;
738addacddSMichael Roth uint16List *u16_integers;
748addacddSMichael Roth uint32List *u32_integers;
758addacddSMichael Roth uint64List *u64_integers;
768addacddSMichael Roth } value;
778addacddSMichael Roth enum PrimitiveTypeKind type;
788addacddSMichael Roth const char *description;
798addacddSMichael Roth } PrimitiveList;
808addacddSMichael Roth
812d496105SMichael Roth /* test helpers */
822d496105SMichael Roth
838addacddSMichael Roth typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp);
848addacddSMichael Roth
dealloc_helper(void * native_in,VisitorFunc visit,Error ** errp)858addacddSMichael Roth static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp)
868addacddSMichael Roth {
872c0ef9f4SEric Blake Visitor *v = qapi_dealloc_visitor_new();
888addacddSMichael Roth
892c0ef9f4SEric Blake visit(v, &native_in, errp);
908addacddSMichael Roth
912c0ef9f4SEric Blake visit_free(v);
928addacddSMichael Roth }
938addacddSMichael Roth
visit_primitive_type(Visitor * v,void ** native,Error ** errp)942d496105SMichael Roth static void visit_primitive_type(Visitor *v, void **native, Error **errp)
952d496105SMichael Roth {
962d496105SMichael Roth PrimitiveType *pt = *native;
972d496105SMichael Roth switch(pt->type) {
982d496105SMichael Roth case PTYPE_STRING:
9951e72bc1SEric Blake visit_type_str(v, NULL, (char **)&pt->value.string, errp);
1002d496105SMichael Roth break;
1012d496105SMichael Roth case PTYPE_BOOLEAN:
10251e72bc1SEric Blake visit_type_bool(v, NULL, &pt->value.boolean, errp);
1032d496105SMichael Roth break;
1042d496105SMichael Roth case PTYPE_NUMBER:
10551e72bc1SEric Blake visit_type_number(v, NULL, &pt->value.number, errp);
1062d496105SMichael Roth break;
1072d496105SMichael Roth case PTYPE_INTEGER:
10851e72bc1SEric Blake visit_type_int(v, NULL, &pt->value.integer, errp);
1092d496105SMichael Roth break;
1102d496105SMichael Roth case PTYPE_U8:
11151e72bc1SEric Blake visit_type_uint8(v, NULL, &pt->value.u8, errp);
1122d496105SMichael Roth break;
1132d496105SMichael Roth case PTYPE_U16:
11451e72bc1SEric Blake visit_type_uint16(v, NULL, &pt->value.u16, errp);
1152d496105SMichael Roth break;
1162d496105SMichael Roth case PTYPE_U32:
11751e72bc1SEric Blake visit_type_uint32(v, NULL, &pt->value.u32, errp);
1182d496105SMichael Roth break;
1192d496105SMichael Roth case PTYPE_U64:
12051e72bc1SEric Blake visit_type_uint64(v, NULL, &pt->value.u64, errp);
1212d496105SMichael Roth break;
1222d496105SMichael Roth case PTYPE_S8:
12351e72bc1SEric Blake visit_type_int8(v, NULL, &pt->value.s8, errp);
1242d496105SMichael Roth break;
1252d496105SMichael Roth case PTYPE_S16:
12651e72bc1SEric Blake visit_type_int16(v, NULL, &pt->value.s16, errp);
1272d496105SMichael Roth break;
1282d496105SMichael Roth case PTYPE_S32:
12951e72bc1SEric Blake visit_type_int32(v, NULL, &pt->value.s32, errp);
1302d496105SMichael Roth break;
1312d496105SMichael Roth case PTYPE_S64:
13251e72bc1SEric Blake visit_type_int64(v, NULL, &pt->value.s64, errp);
1332d496105SMichael Roth break;
1342d496105SMichael Roth case PTYPE_EOL:
135dfc6f865SStefan Weil g_assert_not_reached();
1362d496105SMichael Roth }
1372d496105SMichael Roth }
1382d496105SMichael Roth
visit_primitive_list(Visitor * v,void ** native,Error ** errp)1398addacddSMichael Roth static void visit_primitive_list(Visitor *v, void **native, Error **errp)
1408addacddSMichael Roth {
1418addacddSMichael Roth PrimitiveList *pl = *native;
1428addacddSMichael Roth switch (pl->type) {
1438addacddSMichael Roth case PTYPE_STRING:
14451e72bc1SEric Blake visit_type_strList(v, NULL, &pl->value.strings, errp);
1458addacddSMichael Roth break;
1468addacddSMichael Roth case PTYPE_BOOLEAN:
14751e72bc1SEric Blake visit_type_boolList(v, NULL, &pl->value.booleans, errp);
1488addacddSMichael Roth break;
1498addacddSMichael Roth case PTYPE_NUMBER:
15051e72bc1SEric Blake visit_type_numberList(v, NULL, &pl->value.numbers, errp);
1518addacddSMichael Roth break;
1528addacddSMichael Roth case PTYPE_INTEGER:
15351e72bc1SEric Blake visit_type_intList(v, NULL, &pl->value.integers, errp);
1548addacddSMichael Roth break;
1558addacddSMichael Roth case PTYPE_S8:
15651e72bc1SEric Blake visit_type_int8List(v, NULL, &pl->value.s8_integers, errp);
1578addacddSMichael Roth break;
1588addacddSMichael Roth case PTYPE_S16:
15951e72bc1SEric Blake visit_type_int16List(v, NULL, &pl->value.s16_integers, errp);
1608addacddSMichael Roth break;
1618addacddSMichael Roth case PTYPE_S32:
16251e72bc1SEric Blake visit_type_int32List(v, NULL, &pl->value.s32_integers, errp);
1638addacddSMichael Roth break;
1648addacddSMichael Roth case PTYPE_S64:
16551e72bc1SEric Blake visit_type_int64List(v, NULL, &pl->value.s64_integers, errp);
1668addacddSMichael Roth break;
1678addacddSMichael Roth case PTYPE_U8:
16851e72bc1SEric Blake visit_type_uint8List(v, NULL, &pl->value.u8_integers, errp);
1698addacddSMichael Roth break;
1708addacddSMichael Roth case PTYPE_U16:
17151e72bc1SEric Blake visit_type_uint16List(v, NULL, &pl->value.u16_integers, errp);
1728addacddSMichael Roth break;
1738addacddSMichael Roth case PTYPE_U32:
17451e72bc1SEric Blake visit_type_uint32List(v, NULL, &pl->value.u32_integers, errp);
1758addacddSMichael Roth break;
1768addacddSMichael Roth case PTYPE_U64:
17751e72bc1SEric Blake visit_type_uint64List(v, NULL, &pl->value.u64_integers, errp);
1788addacddSMichael Roth break;
1798addacddSMichael Roth default:
180dfc6f865SStefan Weil g_assert_not_reached();
1818addacddSMichael Roth }
1828addacddSMichael Roth }
1838addacddSMichael Roth
1842d496105SMichael Roth
struct_create(void)1852d496105SMichael Roth static TestStruct *struct_create(void)
1862d496105SMichael Roth {
1872d496105SMichael Roth TestStruct *ts = g_malloc0(sizeof(*ts));
1882d496105SMichael Roth ts->integer = -42;
1892d496105SMichael Roth ts->boolean = true;
1902d496105SMichael Roth ts->string = strdup("test string");
1912d496105SMichael Roth return ts;
1922d496105SMichael Roth }
1932d496105SMichael Roth
struct_compare(TestStruct * ts1,TestStruct * ts2)1942d496105SMichael Roth static void struct_compare(TestStruct *ts1, TestStruct *ts2)
1952d496105SMichael Roth {
1962d496105SMichael Roth g_assert(ts1);
1972d496105SMichael Roth g_assert(ts2);
1982d496105SMichael Roth g_assert_cmpint(ts1->integer, ==, ts2->integer);
1992d496105SMichael Roth g_assert(ts1->boolean == ts2->boolean);
2002d496105SMichael Roth g_assert_cmpstr(ts1->string, ==, ts2->string);
2012d496105SMichael Roth }
2022d496105SMichael Roth
struct_cleanup(TestStruct * ts)2032d496105SMichael Roth static void struct_cleanup(TestStruct *ts)
2042d496105SMichael Roth {
2052d496105SMichael Roth g_free(ts->string);
2062d496105SMichael Roth g_free(ts);
2072d496105SMichael Roth }
2082d496105SMichael Roth
visit_struct(Visitor * v,void ** native,Error ** errp)2092d496105SMichael Roth static void visit_struct(Visitor *v, void **native, Error **errp)
2102d496105SMichael Roth {
21151e72bc1SEric Blake visit_type_TestStruct(v, NULL, (TestStruct **)native, errp);
2122d496105SMichael Roth }
2132d496105SMichael Roth
nested_struct_create(void)214b6fcf32dSEric Blake static UserDefTwo *nested_struct_create(void)
2152d496105SMichael Roth {
216b6fcf32dSEric Blake UserDefTwo *udnp = g_malloc0(sizeof(*udnp));
2172d496105SMichael Roth udnp->string0 = strdup("test_string0");
2186446a592SEric Blake udnp->dict1 = g_malloc0(sizeof(*udnp->dict1));
2196446a592SEric Blake udnp->dict1->string1 = strdup("test_string1");
2206446a592SEric Blake udnp->dict1->dict2 = g_malloc0(sizeof(*udnp->dict1->dict2));
2216446a592SEric Blake udnp->dict1->dict2->userdef = g_new0(UserDefOne, 1);
222ddf21908SEric Blake udnp->dict1->dict2->userdef->integer = 42;
2236446a592SEric Blake udnp->dict1->dict2->userdef->string = strdup("test_string");
2246446a592SEric Blake udnp->dict1->dict2->string = strdup("test_string2");
2256446a592SEric Blake udnp->dict1->dict3 = g_malloc0(sizeof(*udnp->dict1->dict3));
2266446a592SEric Blake udnp->dict1->dict3->userdef = g_new0(UserDefOne, 1);
227ddf21908SEric Blake udnp->dict1->dict3->userdef->integer = 43;
2286446a592SEric Blake udnp->dict1->dict3->userdef->string = strdup("test_string");
2296446a592SEric Blake udnp->dict1->dict3->string = strdup("test_string3");
2302d496105SMichael Roth return udnp;
2312d496105SMichael Roth }
2322d496105SMichael Roth
nested_struct_compare(UserDefTwo * udnp1,UserDefTwo * udnp2)233b6fcf32dSEric Blake static void nested_struct_compare(UserDefTwo *udnp1, UserDefTwo *udnp2)
2342d496105SMichael Roth {
2352d496105SMichael Roth g_assert(udnp1);
2362d496105SMichael Roth g_assert(udnp2);
2372d496105SMichael Roth g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
2386446a592SEric Blake g_assert_cmpstr(udnp1->dict1->string1, ==, udnp2->dict1->string1);
239ddf21908SEric Blake g_assert_cmpint(udnp1->dict1->dict2->userdef->integer, ==,
240ddf21908SEric Blake udnp2->dict1->dict2->userdef->integer);
2416446a592SEric Blake g_assert_cmpstr(udnp1->dict1->dict2->userdef->string, ==,
2426446a592SEric Blake udnp2->dict1->dict2->userdef->string);
2436446a592SEric Blake g_assert_cmpstr(udnp1->dict1->dict2->string, ==,
2446446a592SEric Blake udnp2->dict1->dict2->string);
2454b2fc7dbSMarkus Armbruster g_assert(!udnp1->dict1->dict3 == !udnp2->dict1->dict3);
246ddf21908SEric Blake g_assert_cmpint(udnp1->dict1->dict3->userdef->integer, ==,
247ddf21908SEric Blake udnp2->dict1->dict3->userdef->integer);
2486446a592SEric Blake g_assert_cmpstr(udnp1->dict1->dict3->userdef->string, ==,
2496446a592SEric Blake udnp2->dict1->dict3->userdef->string);
2506446a592SEric Blake g_assert_cmpstr(udnp1->dict1->dict3->string, ==,
2516446a592SEric Blake udnp2->dict1->dict3->string);
2522d496105SMichael Roth }
2532d496105SMichael Roth
nested_struct_cleanup(UserDefTwo * udnp)254b6fcf32dSEric Blake static void nested_struct_cleanup(UserDefTwo *udnp)
2552d496105SMichael Roth {
256b6fcf32dSEric Blake qapi_free_UserDefTwo(udnp);
2572d496105SMichael Roth }
2582d496105SMichael Roth
visit_nested_struct(Visitor * v,void ** native,Error ** errp)2592d496105SMichael Roth static void visit_nested_struct(Visitor *v, void **native, Error **errp)
2602d496105SMichael Roth {
26151e72bc1SEric Blake visit_type_UserDefTwo(v, NULL, (UserDefTwo **)native, errp);
2622d496105SMichael Roth }
2632d496105SMichael Roth
visit_nested_struct_list(Visitor * v,void ** native,Error ** errp)2642d496105SMichael Roth static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
2652d496105SMichael Roth {
26651e72bc1SEric Blake visit_type_UserDefTwoList(v, NULL, (UserDefTwoList **)native, errp);
2672d496105SMichael Roth }
2682d496105SMichael Roth
2692d496105SMichael Roth /* test cases */
2702d496105SMichael Roth
2712d496105SMichael Roth typedef enum VisitorCapabilities {
2722d496105SMichael Roth VCAP_PRIMITIVES = 1,
2732d496105SMichael Roth VCAP_STRUCTURES = 2,
2742d496105SMichael Roth VCAP_LISTS = 4,
2758addacddSMichael Roth VCAP_PRIMITIVE_LISTS = 8,
2762d496105SMichael Roth } VisitorCapabilities;
2772d496105SMichael Roth
2782d496105SMichael Roth typedef struct SerializeOps {
2792d496105SMichael Roth void (*serialize)(void *native_in, void **datap,
2802d496105SMichael Roth VisitorFunc visit, Error **errp);
2812d496105SMichael Roth void (*deserialize)(void **native_out, void *datap,
2822d496105SMichael Roth VisitorFunc visit, Error **errp);
2832d496105SMichael Roth void (*cleanup)(void *datap);
2842d496105SMichael Roth const char *type;
2852d496105SMichael Roth VisitorCapabilities caps;
2862d496105SMichael Roth } SerializeOps;
2872d496105SMichael Roth
2882d496105SMichael Roth typedef struct TestArgs {
2892d496105SMichael Roth const SerializeOps *ops;
2902d496105SMichael Roth void *test_data;
2912d496105SMichael Roth } TestArgs;
2922d496105SMichael Roth
test_primitives(gconstpointer opaque)2932d496105SMichael Roth static void test_primitives(gconstpointer opaque)
2942d496105SMichael Roth {
2952d496105SMichael Roth TestArgs *args = (TestArgs *) opaque;
2962d496105SMichael Roth const SerializeOps *ops = args->ops;
2972d496105SMichael Roth PrimitiveType *pt = args->test_data;
2982d496105SMichael Roth PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
2992d496105SMichael Roth void *serialize_data;
3002d496105SMichael Roth
3012d496105SMichael Roth pt_copy->type = pt->type;
3023f66f764SEric Blake ops->serialize(pt, &serialize_data, visit_primitive_type, &error_abort);
3033f66f764SEric Blake ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type,
3043f66f764SEric Blake &error_abort);
3052d496105SMichael Roth
3062d496105SMichael Roth g_assert(pt_copy != NULL);
30728f1c1f6SMarkus Armbruster switch (pt->type) {
30828f1c1f6SMarkus Armbruster case PTYPE_STRING:
3092d496105SMichael Roth g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
3102bd01ac1SStefan Berger g_free((char *)pt_copy->value.string);
31128f1c1f6SMarkus Armbruster break;
31228f1c1f6SMarkus Armbruster case PTYPE_BOOLEAN:
31328f1c1f6SMarkus Armbruster g_assert_cmpint(pt->value.boolean, ==, pt->value.boolean);
31428f1c1f6SMarkus Armbruster break;
31528f1c1f6SMarkus Armbruster case PTYPE_NUMBER:
3162a02c139SMarkus Armbruster g_assert_cmpfloat(pt->value.number, ==, pt_copy->value.number);
31728f1c1f6SMarkus Armbruster break;
31828f1c1f6SMarkus Armbruster case PTYPE_INTEGER:
31928f1c1f6SMarkus Armbruster g_assert_cmpint(pt->value.integer, ==, pt_copy->value.integer);
32028f1c1f6SMarkus Armbruster break;
32128f1c1f6SMarkus Armbruster case PTYPE_U8:
32228f1c1f6SMarkus Armbruster g_assert_cmpuint(pt->value.u8, ==, pt_copy->value.u8);
32328f1c1f6SMarkus Armbruster break;
32428f1c1f6SMarkus Armbruster case PTYPE_U16:
32528f1c1f6SMarkus Armbruster g_assert_cmpuint(pt->value.u16, ==, pt_copy->value.u16);
32628f1c1f6SMarkus Armbruster break;
32728f1c1f6SMarkus Armbruster case PTYPE_U32:
32828f1c1f6SMarkus Armbruster g_assert_cmpuint(pt->value.u32, ==, pt_copy->value.u32);
32928f1c1f6SMarkus Armbruster break;
33028f1c1f6SMarkus Armbruster case PTYPE_U64:
33128f1c1f6SMarkus Armbruster g_assert_cmpuint(pt->value.u64, ==, pt_copy->value.u64);
33228f1c1f6SMarkus Armbruster break;
33328f1c1f6SMarkus Armbruster case PTYPE_S8:
33428f1c1f6SMarkus Armbruster g_assert_cmpint(pt->value.s8, ==, pt_copy->value.s8);
33528f1c1f6SMarkus Armbruster break;
33628f1c1f6SMarkus Armbruster case PTYPE_S16:
33728f1c1f6SMarkus Armbruster g_assert_cmpint(pt->value.s16, ==, pt_copy->value.s16);
33828f1c1f6SMarkus Armbruster break;
33928f1c1f6SMarkus Armbruster case PTYPE_S32:
34028f1c1f6SMarkus Armbruster g_assert_cmpint(pt->value.s32, ==, pt_copy->value.s32);
34128f1c1f6SMarkus Armbruster break;
34228f1c1f6SMarkus Armbruster case PTYPE_S64:
34328f1c1f6SMarkus Armbruster g_assert_cmpint(pt->value.s64, ==, pt_copy->value.s64);
34428f1c1f6SMarkus Armbruster break;
34528f1c1f6SMarkus Armbruster case PTYPE_EOL:
34628f1c1f6SMarkus Armbruster g_assert_not_reached();
3472d496105SMichael Roth }
3482d496105SMichael Roth
3492d496105SMichael Roth ops->cleanup(serialize_data);
3502d496105SMichael Roth g_free(args);
3512bd01ac1SStefan Berger g_free(pt_copy);
3522d496105SMichael Roth }
3532d496105SMichael Roth
test_primitive_lists(gconstpointer opaque)3548addacddSMichael Roth static void test_primitive_lists(gconstpointer opaque)
3558addacddSMichael Roth {
3568addacddSMichael Roth TestArgs *args = (TestArgs *) opaque;
3578addacddSMichael Roth const SerializeOps *ops = args->ops;
3588addacddSMichael Roth PrimitiveType *pt = args->test_data;
359748bfb4eSStefan Weil PrimitiveList pl = { .value = { NULL } };
360748bfb4eSStefan Weil PrimitiveList pl_copy = { .value = { NULL } };
3618addacddSMichael Roth PrimitiveList *pl_copy_ptr = &pl_copy;
3628addacddSMichael Roth void *serialize_data;
3638addacddSMichael Roth void *cur_head = NULL;
3648addacddSMichael Roth int i;
3658addacddSMichael Roth
3668addacddSMichael Roth pl.type = pl_copy.type = pt->type;
3678addacddSMichael Roth
3688addacddSMichael Roth /* build up our list of primitive types */
3698addacddSMichael Roth for (i = 0; i < 32; i++) {
3708addacddSMichael Roth switch (pl.type) {
3718addacddSMichael Roth case PTYPE_STRING: {
37254aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.strings, g_strdup(pt->value.string));
3738addacddSMichael Roth break;
3748addacddSMichael Roth }
3758addacddSMichael Roth case PTYPE_INTEGER: {
37654aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.integers, pt->value.integer);
3778addacddSMichael Roth break;
3788addacddSMichael Roth }
3798addacddSMichael Roth case PTYPE_S8: {
38054aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.s8_integers, pt->value.s8);
3818addacddSMichael Roth break;
3828addacddSMichael Roth }
3838addacddSMichael Roth case PTYPE_S16: {
38454aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.s16_integers, pt->value.s16);
3858addacddSMichael Roth break;
3868addacddSMichael Roth }
3878addacddSMichael Roth case PTYPE_S32: {
38854aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.s32_integers, pt->value.s32);
3898addacddSMichael Roth break;
3908addacddSMichael Roth }
3918addacddSMichael Roth case PTYPE_S64: {
39254aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.s64_integers, pt->value.s64);
3938addacddSMichael Roth break;
3948addacddSMichael Roth }
3958addacddSMichael Roth case PTYPE_U8: {
39654aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.u8_integers, pt->value.u8);
3978addacddSMichael Roth break;
3988addacddSMichael Roth }
3998addacddSMichael Roth case PTYPE_U16: {
40054aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.u16_integers, pt->value.u16);
4018addacddSMichael Roth break;
4028addacddSMichael Roth }
4038addacddSMichael Roth case PTYPE_U32: {
40454aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.u32_integers, pt->value.u32);
4058addacddSMichael Roth break;
4068addacddSMichael Roth }
4078addacddSMichael Roth case PTYPE_U64: {
40854aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.u64_integers, pt->value.u64);
4098addacddSMichael Roth break;
4108addacddSMichael Roth }
4118addacddSMichael Roth case PTYPE_NUMBER: {
41254aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.numbers, pt->value.number);
4138addacddSMichael Roth break;
4148addacddSMichael Roth }
4158addacddSMichael Roth case PTYPE_BOOLEAN: {
41654aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.booleans, pt->value.boolean);
4178addacddSMichael Roth break;
4188addacddSMichael Roth }
4198addacddSMichael Roth default:
420dfc6f865SStefan Weil g_assert_not_reached();
4218addacddSMichael Roth }
4228addacddSMichael Roth }
4238addacddSMichael Roth
4243f66f764SEric Blake ops->serialize((void **)&pl, &serialize_data, visit_primitive_list,
4253f66f764SEric Blake &error_abort);
4263f66f764SEric Blake ops->deserialize((void **)&pl_copy_ptr, serialize_data,
4273f66f764SEric Blake visit_primitive_list, &error_abort);
4288addacddSMichael Roth
429ac9e723fSPaolo Bonzini
430ac9e723fSPaolo Bonzini switch (pl_copy.type) {
431ac9e723fSPaolo Bonzini case PTYPE_STRING:
432ac9e723fSPaolo Bonzini cur_head = pl_copy.value.strings;
433ac9e723fSPaolo Bonzini break;
434ac9e723fSPaolo Bonzini case PTYPE_INTEGER:
435ac9e723fSPaolo Bonzini cur_head = pl_copy.value.integers;
436ac9e723fSPaolo Bonzini break;
437ac9e723fSPaolo Bonzini case PTYPE_S8:
438ac9e723fSPaolo Bonzini cur_head = pl_copy.value.s8_integers;
439ac9e723fSPaolo Bonzini break;
440ac9e723fSPaolo Bonzini case PTYPE_S16:
441ac9e723fSPaolo Bonzini cur_head = pl_copy.value.s16_integers;
442ac9e723fSPaolo Bonzini break;
443ac9e723fSPaolo Bonzini case PTYPE_S32:
444ac9e723fSPaolo Bonzini cur_head = pl_copy.value.s32_integers;
445ac9e723fSPaolo Bonzini break;
446ac9e723fSPaolo Bonzini case PTYPE_S64:
447ac9e723fSPaolo Bonzini cur_head = pl_copy.value.s64_integers;
448ac9e723fSPaolo Bonzini break;
449ac9e723fSPaolo Bonzini case PTYPE_U8:
450ac9e723fSPaolo Bonzini cur_head = pl_copy.value.u8_integers;
451ac9e723fSPaolo Bonzini break;
452ac9e723fSPaolo Bonzini case PTYPE_U16:
453ac9e723fSPaolo Bonzini cur_head = pl_copy.value.u16_integers;
454ac9e723fSPaolo Bonzini break;
455ac9e723fSPaolo Bonzini case PTYPE_U32:
456ac9e723fSPaolo Bonzini cur_head = pl_copy.value.u32_integers;
457ac9e723fSPaolo Bonzini break;
458ac9e723fSPaolo Bonzini case PTYPE_U64:
459ac9e723fSPaolo Bonzini cur_head = pl_copy.value.u64_integers;
460ac9e723fSPaolo Bonzini break;
461ac9e723fSPaolo Bonzini case PTYPE_NUMBER:
462ac9e723fSPaolo Bonzini cur_head = pl_copy.value.numbers;
463ac9e723fSPaolo Bonzini break;
464ac9e723fSPaolo Bonzini case PTYPE_BOOLEAN:
465ac9e723fSPaolo Bonzini cur_head = pl_copy.value.booleans;
466ac9e723fSPaolo Bonzini break;
467ac9e723fSPaolo Bonzini default:
468ac9e723fSPaolo Bonzini g_assert_not_reached();
469ac9e723fSPaolo Bonzini }
4708addacddSMichael Roth
4718addacddSMichael Roth /* compare our deserialized list of primitives to the original */
472ac9e723fSPaolo Bonzini i = 0;
473ac9e723fSPaolo Bonzini while (cur_head) {
4748addacddSMichael Roth switch (pl_copy.type) {
4758addacddSMichael Roth case PTYPE_STRING: {
476ac9e723fSPaolo Bonzini strList *ptr = cur_head;
4778addacddSMichael Roth cur_head = ptr->next;
4788addacddSMichael Roth g_assert_cmpstr(pt->value.string, ==, ptr->value);
4798addacddSMichael Roth break;
4808addacddSMichael Roth }
4818addacddSMichael Roth case PTYPE_INTEGER: {
482ac9e723fSPaolo Bonzini intList *ptr = cur_head;
4838addacddSMichael Roth cur_head = ptr->next;
4848addacddSMichael Roth g_assert_cmpint(pt->value.integer, ==, ptr->value);
4858addacddSMichael Roth break;
4868addacddSMichael Roth }
4878addacddSMichael Roth case PTYPE_S8: {
488ac9e723fSPaolo Bonzini int8List *ptr = cur_head;
4898addacddSMichael Roth cur_head = ptr->next;
4908addacddSMichael Roth g_assert_cmpint(pt->value.s8, ==, ptr->value);
4918addacddSMichael Roth break;
4928addacddSMichael Roth }
4938addacddSMichael Roth case PTYPE_S16: {
494ac9e723fSPaolo Bonzini int16List *ptr = cur_head;
4958addacddSMichael Roth cur_head = ptr->next;
4968addacddSMichael Roth g_assert_cmpint(pt->value.s16, ==, ptr->value);
4978addacddSMichael Roth break;
4988addacddSMichael Roth }
4998addacddSMichael Roth case PTYPE_S32: {
500ac9e723fSPaolo Bonzini int32List *ptr = cur_head;
5018addacddSMichael Roth cur_head = ptr->next;
5028addacddSMichael Roth g_assert_cmpint(pt->value.s32, ==, ptr->value);
5038addacddSMichael Roth break;
5048addacddSMichael Roth }
5058addacddSMichael Roth case PTYPE_S64: {
506ac9e723fSPaolo Bonzini int64List *ptr = cur_head;
5078addacddSMichael Roth cur_head = ptr->next;
5088addacddSMichael Roth g_assert_cmpint(pt->value.s64, ==, ptr->value);
5098addacddSMichael Roth break;
5108addacddSMichael Roth }
5118addacddSMichael Roth case PTYPE_U8: {
512ac9e723fSPaolo Bonzini uint8List *ptr = cur_head;
5138addacddSMichael Roth cur_head = ptr->next;
5148addacddSMichael Roth g_assert_cmpint(pt->value.u8, ==, ptr->value);
5158addacddSMichael Roth break;
5168addacddSMichael Roth }
5178addacddSMichael Roth case PTYPE_U16: {
518ac9e723fSPaolo Bonzini uint16List *ptr = cur_head;
5198addacddSMichael Roth cur_head = ptr->next;
5208addacddSMichael Roth g_assert_cmpint(pt->value.u16, ==, ptr->value);
5218addacddSMichael Roth break;
5228addacddSMichael Roth }
5238addacddSMichael Roth case PTYPE_U32: {
524ac9e723fSPaolo Bonzini uint32List *ptr = cur_head;
5258addacddSMichael Roth cur_head = ptr->next;
5268addacddSMichael Roth g_assert_cmpint(pt->value.u32, ==, ptr->value);
5278addacddSMichael Roth break;
5288addacddSMichael Roth }
5298addacddSMichael Roth case PTYPE_U64: {
530ac9e723fSPaolo Bonzini uint64List *ptr = cur_head;
5318addacddSMichael Roth cur_head = ptr->next;
5328addacddSMichael Roth g_assert_cmpint(pt->value.u64, ==, ptr->value);
5338addacddSMichael Roth break;
5348addacddSMichael Roth }
5358addacddSMichael Roth case PTYPE_NUMBER: {
5368addacddSMichael Roth GString *double_expected = g_string_new("");
5378addacddSMichael Roth GString *double_actual = g_string_new("");
538ac9e723fSPaolo Bonzini numberList *ptr = cur_head;
5398addacddSMichael Roth cur_head = ptr->next;
5408addacddSMichael Roth /* we serialize with %f for our reference visitors, so rather than
5418addacddSMichael Roth * fuzzy floating math to test "equality", just compare the
5428addacddSMichael Roth * formatted values
5438addacddSMichael Roth */
5448addacddSMichael Roth g_string_printf(double_expected, "%.6f", pt->value.number);
5458addacddSMichael Roth g_string_printf(double_actual, "%.6f", ptr->value);
5468addacddSMichael Roth g_assert_cmpstr(double_actual->str, ==, double_expected->str);
5478addacddSMichael Roth g_string_free(double_expected, true);
5488addacddSMichael Roth g_string_free(double_actual, true);
5498addacddSMichael Roth break;
5508addacddSMichael Roth }
5518addacddSMichael Roth case PTYPE_BOOLEAN: {
552ac9e723fSPaolo Bonzini boolList *ptr = cur_head;
5538addacddSMichael Roth cur_head = ptr->next;
5548addacddSMichael Roth g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value);
5558addacddSMichael Roth break;
5568addacddSMichael Roth }
5578addacddSMichael Roth default:
558dfc6f865SStefan Weil g_assert_not_reached();
5598addacddSMichael Roth }
5608addacddSMichael Roth i++;
561ac9e723fSPaolo Bonzini }
5628addacddSMichael Roth
563ac9e723fSPaolo Bonzini g_assert_cmpint(i, ==, 32);
5648addacddSMichael Roth
5658addacddSMichael Roth ops->cleanup(serialize_data);
5663f66f764SEric Blake dealloc_helper(&pl, visit_primitive_list, &error_abort);
5673f66f764SEric Blake dealloc_helper(&pl_copy, visit_primitive_list, &error_abort);
5688addacddSMichael Roth g_free(args);
5698addacddSMichael Roth }
5708addacddSMichael Roth
test_struct(gconstpointer opaque)5712d496105SMichael Roth static void test_struct(gconstpointer opaque)
5722d496105SMichael Roth {
5732d496105SMichael Roth TestArgs *args = (TestArgs *) opaque;
5742d496105SMichael Roth const SerializeOps *ops = args->ops;
5752d496105SMichael Roth TestStruct *ts = struct_create();
5762d496105SMichael Roth TestStruct *ts_copy = NULL;
5772d496105SMichael Roth void *serialize_data;
5782d496105SMichael Roth
5793f66f764SEric Blake ops->serialize(ts, &serialize_data, visit_struct, &error_abort);
5803f66f764SEric Blake ops->deserialize((void **)&ts_copy, serialize_data, visit_struct,
5813f66f764SEric Blake &error_abort);
5822d496105SMichael Roth
5832d496105SMichael Roth struct_compare(ts, ts_copy);
5842d496105SMichael Roth
5852d496105SMichael Roth struct_cleanup(ts);
5862d496105SMichael Roth struct_cleanup(ts_copy);
5872d496105SMichael Roth
5882d496105SMichael Roth ops->cleanup(serialize_data);
5892d496105SMichael Roth g_free(args);
5902d496105SMichael Roth }
5912d496105SMichael Roth
test_nested_struct(gconstpointer opaque)5922d496105SMichael Roth static void test_nested_struct(gconstpointer opaque)
5932d496105SMichael Roth {
5942d496105SMichael Roth TestArgs *args = (TestArgs *) opaque;
5952d496105SMichael Roth const SerializeOps *ops = args->ops;
596b6fcf32dSEric Blake UserDefTwo *udnp = nested_struct_create();
597b6fcf32dSEric Blake UserDefTwo *udnp_copy = NULL;
5982d496105SMichael Roth void *serialize_data;
5992d496105SMichael Roth
6003f66f764SEric Blake ops->serialize(udnp, &serialize_data, visit_nested_struct, &error_abort);
601b6fcf32dSEric Blake ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct,
6023f66f764SEric Blake &error_abort);
6032d496105SMichael Roth
6042d496105SMichael Roth nested_struct_compare(udnp, udnp_copy);
6052d496105SMichael Roth
6062d496105SMichael Roth nested_struct_cleanup(udnp);
6072d496105SMichael Roth nested_struct_cleanup(udnp_copy);
6082d496105SMichael Roth
6092d496105SMichael Roth ops->cleanup(serialize_data);
6102d496105SMichael Roth g_free(args);
6112d496105SMichael Roth }
6122d496105SMichael Roth
test_nested_struct_list(gconstpointer opaque)6132d496105SMichael Roth static void test_nested_struct_list(gconstpointer opaque)
6142d496105SMichael Roth {
6152d496105SMichael Roth TestArgs *args = (TestArgs *) opaque;
6162d496105SMichael Roth const SerializeOps *ops = args->ops;
617b6fcf32dSEric Blake UserDefTwoList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
6182d496105SMichael Roth void *serialize_data;
6192d496105SMichael Roth int i = 0;
6202d496105SMichael Roth
6212d496105SMichael Roth for (i = 0; i < 8; i++) {
62254aa3de7SEric Blake QAPI_LIST_PREPEND(listp, nested_struct_create());
6232d496105SMichael Roth }
6242d496105SMichael Roth
6253f66f764SEric Blake ops->serialize(listp, &serialize_data, visit_nested_struct_list,
6263f66f764SEric Blake &error_abort);
6272d496105SMichael Roth ops->deserialize((void **)&listp_copy, serialize_data,
6283f66f764SEric Blake visit_nested_struct_list, &error_abort);
6292d496105SMichael Roth
6302d496105SMichael Roth tmp = listp;
6312d496105SMichael Roth tmp_copy = listp_copy;
6322d496105SMichael Roth while (listp_copy) {
6332d496105SMichael Roth g_assert(listp);
6342d496105SMichael Roth nested_struct_compare(listp->value, listp_copy->value);
6352d496105SMichael Roth listp = listp->next;
6362d496105SMichael Roth listp_copy = listp_copy->next;
6372d496105SMichael Roth }
6382d496105SMichael Roth
639b6fcf32dSEric Blake qapi_free_UserDefTwoList(tmp);
640b6fcf32dSEric Blake qapi_free_UserDefTwoList(tmp_copy);
6412d496105SMichael Roth
6422d496105SMichael Roth ops->cleanup(serialize_data);
6432d496105SMichael Roth g_free(args);
6442d496105SMichael Roth }
6452d496105SMichael Roth
646748bfb4eSStefan Weil static PrimitiveType pt_values[] = {
6472d496105SMichael Roth /* string tests */
6482d496105SMichael Roth {
6492d496105SMichael Roth .description = "string_empty",
6502d496105SMichael Roth .type = PTYPE_STRING,
6512d496105SMichael Roth .value.string = "",
6522d496105SMichael Roth },
6532d496105SMichael Roth {
6542d496105SMichael Roth .description = "string_whitespace",
6552d496105SMichael Roth .type = PTYPE_STRING,
6562d496105SMichael Roth .value.string = "a b c\td",
6572d496105SMichael Roth },
6582d496105SMichael Roth {
6592d496105SMichael Roth .description = "string_newlines",
6602d496105SMichael Roth .type = PTYPE_STRING,
6612d496105SMichael Roth .value.string = "a\nb\n",
6622d496105SMichael Roth },
6632d496105SMichael Roth {
6642d496105SMichael Roth .description = "string_commas",
6652d496105SMichael Roth .type = PTYPE_STRING,
6662d496105SMichael Roth .value.string = "a,b, c,d",
6672d496105SMichael Roth },
6682d496105SMichael Roth {
6692d496105SMichael Roth .description = "string_single_quoted",
6702d496105SMichael Roth .type = PTYPE_STRING,
6712d496105SMichael Roth .value.string = "'a b',cd",
6722d496105SMichael Roth },
6732d496105SMichael Roth {
6742d496105SMichael Roth .description = "string_double_quoted",
6752d496105SMichael Roth .type = PTYPE_STRING,
6762d496105SMichael Roth .value.string = "\"a b\",cd",
6772d496105SMichael Roth },
6782d496105SMichael Roth /* boolean tests */
6792d496105SMichael Roth {
6802d496105SMichael Roth .description = "boolean_true1",
6812d496105SMichael Roth .type = PTYPE_BOOLEAN,
6822d496105SMichael Roth .value.boolean = true,
6832d496105SMichael Roth },
6842d496105SMichael Roth {
6852d496105SMichael Roth .description = "boolean_true2",
6862d496105SMichael Roth .type = PTYPE_BOOLEAN,
6872d496105SMichael Roth .value.boolean = 8,
6882d496105SMichael Roth },
6892d496105SMichael Roth {
6902d496105SMichael Roth .description = "boolean_true3",
6912d496105SMichael Roth .type = PTYPE_BOOLEAN,
6922d496105SMichael Roth .value.boolean = -1,
6932d496105SMichael Roth },
6942d496105SMichael Roth {
6952d496105SMichael Roth .description = "boolean_false1",
6962d496105SMichael Roth .type = PTYPE_BOOLEAN,
6972d496105SMichael Roth .value.boolean = false,
6982d496105SMichael Roth },
6992d496105SMichael Roth {
7002d496105SMichael Roth .description = "boolean_false2",
7012d496105SMichael Roth .type = PTYPE_BOOLEAN,
7022d496105SMichael Roth .value.boolean = 0,
7032d496105SMichael Roth },
7042d496105SMichael Roth /* number tests (double) */
7052d496105SMichael Roth {
7062d496105SMichael Roth .description = "number_sanity1",
7072d496105SMichael Roth .type = PTYPE_NUMBER,
7082d496105SMichael Roth .value.number = -1,
7092d496105SMichael Roth },
7102d496105SMichael Roth {
7112d496105SMichael Roth .description = "number_sanity2",
7122d496105SMichael Roth .type = PTYPE_NUMBER,
7132a02c139SMarkus Armbruster .value.number = 3.141593,
7142d496105SMichael Roth },
7152d496105SMichael Roth {
7162d496105SMichael Roth .description = "number_min",
7172d496105SMichael Roth .type = PTYPE_NUMBER,
7182d496105SMichael Roth .value.number = DBL_MIN,
7192d496105SMichael Roth },
7202d496105SMichael Roth {
7212d496105SMichael Roth .description = "number_max",
7222d496105SMichael Roth .type = PTYPE_NUMBER,
7232d496105SMichael Roth .value.number = DBL_MAX,
7242d496105SMichael Roth },
7252d496105SMichael Roth /* integer tests (int64) */
7262d496105SMichael Roth {
7272d496105SMichael Roth .description = "integer_sanity1",
7282d496105SMichael Roth .type = PTYPE_INTEGER,
7292d496105SMichael Roth .value.integer = -1,
7302d496105SMichael Roth },
7312d496105SMichael Roth {
7322d496105SMichael Roth .description = "integer_sanity2",
7332d496105SMichael Roth .type = PTYPE_INTEGER,
7342d496105SMichael Roth .value.integer = INT64_MAX / 2 + 1,
7352d496105SMichael Roth },
7362d496105SMichael Roth {
7372d496105SMichael Roth .description = "integer_min",
7382d496105SMichael Roth .type = PTYPE_INTEGER,
7392d496105SMichael Roth .value.integer = INT64_MIN,
7402d496105SMichael Roth },
7412d496105SMichael Roth {
7422d496105SMichael Roth .description = "integer_max",
7432d496105SMichael Roth .type = PTYPE_INTEGER,
7442d496105SMichael Roth .value.integer = INT64_MAX,
7452d496105SMichael Roth },
7462d496105SMichael Roth /* uint8 tests */
7472d496105SMichael Roth {
7482d496105SMichael Roth .description = "uint8_sanity1",
7492d496105SMichael Roth .type = PTYPE_U8,
7502d496105SMichael Roth .value.u8 = 1,
7512d496105SMichael Roth },
7522d496105SMichael Roth {
7532d496105SMichael Roth .description = "uint8_sanity2",
7542d496105SMichael Roth .type = PTYPE_U8,
7552d496105SMichael Roth .value.u8 = UINT8_MAX / 2 + 1,
7562d496105SMichael Roth },
7572d496105SMichael Roth {
7582d496105SMichael Roth .description = "uint8_min",
7592d496105SMichael Roth .type = PTYPE_U8,
7602d496105SMichael Roth .value.u8 = 0,
7612d496105SMichael Roth },
7622d496105SMichael Roth {
7632d496105SMichael Roth .description = "uint8_max",
7642d496105SMichael Roth .type = PTYPE_U8,
7652d496105SMichael Roth .value.u8 = UINT8_MAX,
7662d496105SMichael Roth },
7672d496105SMichael Roth /* uint16 tests */
7682d496105SMichael Roth {
7692d496105SMichael Roth .description = "uint16_sanity1",
7702d496105SMichael Roth .type = PTYPE_U16,
7712d496105SMichael Roth .value.u16 = 1,
7722d496105SMichael Roth },
7732d496105SMichael Roth {
7742d496105SMichael Roth .description = "uint16_sanity2",
7752d496105SMichael Roth .type = PTYPE_U16,
7762d496105SMichael Roth .value.u16 = UINT16_MAX / 2 + 1,
7772d496105SMichael Roth },
7782d496105SMichael Roth {
7792d496105SMichael Roth .description = "uint16_min",
7802d496105SMichael Roth .type = PTYPE_U16,
7812d496105SMichael Roth .value.u16 = 0,
7822d496105SMichael Roth },
7832d496105SMichael Roth {
7842d496105SMichael Roth .description = "uint16_max",
7852d496105SMichael Roth .type = PTYPE_U16,
7862d496105SMichael Roth .value.u16 = UINT16_MAX,
7872d496105SMichael Roth },
7882d496105SMichael Roth /* uint32 tests */
7892d496105SMichael Roth {
7902d496105SMichael Roth .description = "uint32_sanity1",
7912d496105SMichael Roth .type = PTYPE_U32,
7922d496105SMichael Roth .value.u32 = 1,
7932d496105SMichael Roth },
7942d496105SMichael Roth {
7952d496105SMichael Roth .description = "uint32_sanity2",
7962d496105SMichael Roth .type = PTYPE_U32,
7972d496105SMichael Roth .value.u32 = UINT32_MAX / 2 + 1,
7982d496105SMichael Roth },
7992d496105SMichael Roth {
8002d496105SMichael Roth .description = "uint32_min",
8012d496105SMichael Roth .type = PTYPE_U32,
8022d496105SMichael Roth .value.u32 = 0,
8032d496105SMichael Roth },
8042d496105SMichael Roth {
8052d496105SMichael Roth .description = "uint32_max",
8062d496105SMichael Roth .type = PTYPE_U32,
8072d496105SMichael Roth .value.u32 = UINT32_MAX,
8082d496105SMichael Roth },
8092d496105SMichael Roth /* uint64 tests */
8102d496105SMichael Roth {
8112d496105SMichael Roth .description = "uint64_sanity1",
8122d496105SMichael Roth .type = PTYPE_U64,
8132d496105SMichael Roth .value.u64 = 1,
8142d496105SMichael Roth },
8152d496105SMichael Roth {
8162d496105SMichael Roth .description = "uint64_sanity2",
8172d496105SMichael Roth .type = PTYPE_U64,
8182d496105SMichael Roth .value.u64 = UINT64_MAX / 2 + 1,
8192d496105SMichael Roth },
8202d496105SMichael Roth {
8212d496105SMichael Roth .description = "uint64_min",
8222d496105SMichael Roth .type = PTYPE_U64,
8232d496105SMichael Roth .value.u64 = 0,
8242d496105SMichael Roth },
8252d496105SMichael Roth {
8262d496105SMichael Roth .description = "uint64_max",
8272d496105SMichael Roth .type = PTYPE_U64,
8282d496105SMichael Roth .value.u64 = UINT64_MAX,
8292d496105SMichael Roth },
8302d496105SMichael Roth /* int8 tests */
8312d496105SMichael Roth {
8322d496105SMichael Roth .description = "int8_sanity1",
8332d496105SMichael Roth .type = PTYPE_S8,
8342d496105SMichael Roth .value.s8 = -1,
8352d496105SMichael Roth },
8362d496105SMichael Roth {
8372d496105SMichael Roth .description = "int8_sanity2",
8382d496105SMichael Roth .type = PTYPE_S8,
8392d496105SMichael Roth .value.s8 = INT8_MAX / 2 + 1,
8402d496105SMichael Roth },
8412d496105SMichael Roth {
8422d496105SMichael Roth .description = "int8_min",
8432d496105SMichael Roth .type = PTYPE_S8,
8442d496105SMichael Roth .value.s8 = INT8_MIN,
8452d496105SMichael Roth },
8462d496105SMichael Roth {
8472d496105SMichael Roth .description = "int8_max",
8482d496105SMichael Roth .type = PTYPE_S8,
8492d496105SMichael Roth .value.s8 = INT8_MAX,
8502d496105SMichael Roth },
8512d496105SMichael Roth /* int16 tests */
8522d496105SMichael Roth {
8532d496105SMichael Roth .description = "int16_sanity1",
8542d496105SMichael Roth .type = PTYPE_S16,
8552d496105SMichael Roth .value.s16 = -1,
8562d496105SMichael Roth },
8572d496105SMichael Roth {
8582d496105SMichael Roth .description = "int16_sanity2",
8592d496105SMichael Roth .type = PTYPE_S16,
8602d496105SMichael Roth .value.s16 = INT16_MAX / 2 + 1,
8612d496105SMichael Roth },
8622d496105SMichael Roth {
8632d496105SMichael Roth .description = "int16_min",
8642d496105SMichael Roth .type = PTYPE_S16,
8652d496105SMichael Roth .value.s16 = INT16_MIN,
8662d496105SMichael Roth },
8672d496105SMichael Roth {
8682d496105SMichael Roth .description = "int16_max",
8692d496105SMichael Roth .type = PTYPE_S16,
8702d496105SMichael Roth .value.s16 = INT16_MAX,
8712d496105SMichael Roth },
8722d496105SMichael Roth /* int32 tests */
8732d496105SMichael Roth {
8742d496105SMichael Roth .description = "int32_sanity1",
8752d496105SMichael Roth .type = PTYPE_S32,
8762d496105SMichael Roth .value.s32 = -1,
8772d496105SMichael Roth },
8782d496105SMichael Roth {
8792d496105SMichael Roth .description = "int32_sanity2",
8802d496105SMichael Roth .type = PTYPE_S32,
8812d496105SMichael Roth .value.s32 = INT32_MAX / 2 + 1,
8822d496105SMichael Roth },
8832d496105SMichael Roth {
8842d496105SMichael Roth .description = "int32_min",
8852d496105SMichael Roth .type = PTYPE_S32,
8862d496105SMichael Roth .value.s32 = INT32_MIN,
8872d496105SMichael Roth },
8882d496105SMichael Roth {
8892d496105SMichael Roth .description = "int32_max",
8902d496105SMichael Roth .type = PTYPE_S32,
8912d496105SMichael Roth .value.s32 = INT32_MAX,
8922d496105SMichael Roth },
8932d496105SMichael Roth /* int64 tests */
8942d496105SMichael Roth {
8952d496105SMichael Roth .description = "int64_sanity1",
8962d496105SMichael Roth .type = PTYPE_S64,
8972d496105SMichael Roth .value.s64 = -1,
8982d496105SMichael Roth },
8992d496105SMichael Roth {
9002d496105SMichael Roth .description = "int64_sanity2",
9012d496105SMichael Roth .type = PTYPE_S64,
9022d496105SMichael Roth .value.s64 = INT64_MAX / 2 + 1,
9032d496105SMichael Roth },
9042d496105SMichael Roth {
9052d496105SMichael Roth .description = "int64_min",
9062d496105SMichael Roth .type = PTYPE_S64,
9072d496105SMichael Roth .value.s64 = INT64_MIN,
9082d496105SMichael Roth },
9092d496105SMichael Roth {
9102d496105SMichael Roth .description = "int64_max",
9112d496105SMichael Roth .type = PTYPE_S64,
9122d496105SMichael Roth .value.s64 = INT64_MAX,
9132d496105SMichael Roth },
9142d496105SMichael Roth { .type = PTYPE_EOL }
9152d496105SMichael Roth };
9162d496105SMichael Roth
9172d496105SMichael Roth /* visitor-specific op implementations */
9182d496105SMichael Roth
9192d496105SMichael Roth typedef struct QmpSerializeData {
9203b098d56SEric Blake Visitor *qov;
9213b098d56SEric Blake QObject *obj;
922b70ce101SEric Blake Visitor *qiv;
9232d496105SMichael Roth } QmpSerializeData;
9242d496105SMichael Roth
qmp_serialize(void * native_in,void ** datap,VisitorFunc visit,Error ** errp)9252d496105SMichael Roth static void qmp_serialize(void *native_in, void **datap,
9262d496105SMichael Roth VisitorFunc visit, Error **errp)
9272d496105SMichael Roth {
9282d496105SMichael Roth QmpSerializeData *d = g_malloc0(sizeof(*d));
9292d496105SMichael Roth
9307d5e199aSDaniel P. Berrange d->qov = qobject_output_visitor_new(&d->obj);
9313b098d56SEric Blake visit(d->qov, &native_in, errp);
9322d496105SMichael Roth *datap = d;
9332d496105SMichael Roth }
9342d496105SMichael Roth
qmp_deserialize(void ** native_out,void * datap,VisitorFunc visit,Error ** errp)9352d496105SMichael Roth static void qmp_deserialize(void **native_out, void *datap,
9362d496105SMichael Roth VisitorFunc visit, Error **errp)
9372d496105SMichael Roth {
9382d496105SMichael Roth QmpSerializeData *d = datap;
939eab3a467SMarkus Armbruster GString *output_json;
940ad7f375dSMichael Roth QObject *obj_orig, *obj;
941ad7f375dSMichael Roth
9423b098d56SEric Blake visit_complete(d->qov, &d->obj);
9433b098d56SEric Blake obj_orig = d->obj;
944ad7f375dSMichael Roth output_json = qobject_to_json(obj_orig);
945eab3a467SMarkus Armbruster obj = qobject_from_json(output_json->str, &error_abort);
9462d496105SMichael Roth
947eab3a467SMarkus Armbruster g_string_free(output_json, true);
948048abb7bSMarkus Armbruster d->qiv = qobject_input_visitor_new(obj);
949cb3e7f08SMarc-André Lureau qobject_unref(obj_orig);
950cb3e7f08SMarc-André Lureau qobject_unref(obj);
951b70ce101SEric Blake visit(d->qiv, native_out, errp);
9522d496105SMichael Roth }
9532d496105SMichael Roth
qmp_cleanup(void * datap)9542d496105SMichael Roth static void qmp_cleanup(void *datap)
9552d496105SMichael Roth {
9562d496105SMichael Roth QmpSerializeData *d = datap;
9573b098d56SEric Blake visit_free(d->qov);
958b70ce101SEric Blake visit_free(d->qiv);
9592bd01ac1SStefan Berger
9602bd01ac1SStefan Berger g_free(d);
9612d496105SMichael Roth }
9622d496105SMichael Roth
9630d30b0a2SMichael Roth typedef struct StringSerializeData {
9642bd01ac1SStefan Berger char *string;
9653b098d56SEric Blake Visitor *sov;
9667a0525c7SEric Blake Visitor *siv;
9670d30b0a2SMichael Roth } StringSerializeData;
9680d30b0a2SMichael Roth
string_serialize(void * native_in,void ** datap,VisitorFunc visit,Error ** errp)9690d30b0a2SMichael Roth static void string_serialize(void *native_in, void **datap,
9700d30b0a2SMichael Roth VisitorFunc visit, Error **errp)
9710d30b0a2SMichael Roth {
9720d30b0a2SMichael Roth StringSerializeData *d = g_malloc0(sizeof(*d));
9730d30b0a2SMichael Roth
9743b098d56SEric Blake d->sov = string_output_visitor_new(false, &d->string);
9753b098d56SEric Blake visit(d->sov, &native_in, errp);
9760d30b0a2SMichael Roth *datap = d;
9770d30b0a2SMichael Roth }
9780d30b0a2SMichael Roth
string_deserialize(void ** native_out,void * datap,VisitorFunc visit,Error ** errp)9790d30b0a2SMichael Roth static void string_deserialize(void **native_out, void *datap,
9800d30b0a2SMichael Roth VisitorFunc visit, Error **errp)
9810d30b0a2SMichael Roth {
9820d30b0a2SMichael Roth StringSerializeData *d = datap;
9830d30b0a2SMichael Roth
9843b098d56SEric Blake visit_complete(d->sov, &d->string);
9852bd01ac1SStefan Berger d->siv = string_input_visitor_new(d->string);
9867a0525c7SEric Blake visit(d->siv, native_out, errp);
9870d30b0a2SMichael Roth }
9880d30b0a2SMichael Roth
string_cleanup(void * datap)9890d30b0a2SMichael Roth static void string_cleanup(void *datap)
9900d30b0a2SMichael Roth {
9910d30b0a2SMichael Roth StringSerializeData *d = datap;
9922bd01ac1SStefan Berger
9933b098d56SEric Blake visit_free(d->sov);
9947a0525c7SEric Blake visit_free(d->siv);
9952bd01ac1SStefan Berger g_free(d->string);
9962bd01ac1SStefan Berger g_free(d);
9970d30b0a2SMichael Roth }
9980d30b0a2SMichael Roth
9992d496105SMichael Roth /* visitor registration, test harness */
10002d496105SMichael Roth
10012d496105SMichael Roth /* note: to function interchangeably as a serialization mechanism your
10022d496105SMichael Roth * visitor test implementation should pass the test cases for all visitor
10032d496105SMichael Roth * capabilities: primitives, structures, and lists
10042d496105SMichael Roth */
10052d496105SMichael Roth static const SerializeOps visitors[] = {
10062d496105SMichael Roth {
10072d496105SMichael Roth .type = "QMP",
10082d496105SMichael Roth .serialize = qmp_serialize,
10092d496105SMichael Roth .deserialize = qmp_deserialize,
10102d496105SMichael Roth .cleanup = qmp_cleanup,
10118addacddSMichael Roth .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS |
10128addacddSMichael Roth VCAP_PRIMITIVE_LISTS
10132d496105SMichael Roth },
10140d30b0a2SMichael Roth {
10150d30b0a2SMichael Roth .type = "String",
10160d30b0a2SMichael Roth .serialize = string_serialize,
10170d30b0a2SMichael Roth .deserialize = string_deserialize,
10180d30b0a2SMichael Roth .cleanup = string_cleanup,
10190d30b0a2SMichael Roth .caps = VCAP_PRIMITIVES
10200d30b0a2SMichael Roth },
10212d496105SMichael Roth { NULL }
10222d496105SMichael Roth };
10232d496105SMichael Roth
add_visitor_type(const SerializeOps * ops)10242d496105SMichael Roth static void add_visitor_type(const SerializeOps *ops)
10252d496105SMichael Roth {
1026fdf235baSEric Blake char testname_prefix[32];
10272d496105SMichael Roth char testname[128];
10282d496105SMichael Roth TestArgs *args;
10292d496105SMichael Roth int i = 0;
10302d496105SMichael Roth
10312d496105SMichael Roth sprintf(testname_prefix, "/visitor/serialization/%s", ops->type);
10322d496105SMichael Roth
10332d496105SMichael Roth if (ops->caps & VCAP_PRIMITIVES) {
10342d496105SMichael Roth while (pt_values[i].type != PTYPE_EOL) {
10352d496105SMichael Roth sprintf(testname, "%s/primitives/%s", testname_prefix,
10362d496105SMichael Roth pt_values[i].description);
10372d496105SMichael Roth args = g_malloc0(sizeof(*args));
10382d496105SMichael Roth args->ops = ops;
10392d496105SMichael Roth args->test_data = &pt_values[i];
10402d496105SMichael Roth g_test_add_data_func(testname, args, test_primitives);
10412d496105SMichael Roth i++;
10422d496105SMichael Roth }
10432d496105SMichael Roth }
10442d496105SMichael Roth
10452d496105SMichael Roth if (ops->caps & VCAP_STRUCTURES) {
10462d496105SMichael Roth sprintf(testname, "%s/struct", testname_prefix);
10472d496105SMichael Roth args = g_malloc0(sizeof(*args));
10482d496105SMichael Roth args->ops = ops;
10492d496105SMichael Roth args->test_data = NULL;
10502d496105SMichael Roth g_test_add_data_func(testname, args, test_struct);
10512d496105SMichael Roth
10522d496105SMichael Roth sprintf(testname, "%s/nested_struct", testname_prefix);
10532d496105SMichael Roth args = g_malloc0(sizeof(*args));
10542d496105SMichael Roth args->ops = ops;
10552d496105SMichael Roth args->test_data = NULL;
10562d496105SMichael Roth g_test_add_data_func(testname, args, test_nested_struct);
10572d496105SMichael Roth }
10582d496105SMichael Roth
10592d496105SMichael Roth if (ops->caps & VCAP_LISTS) {
10602d496105SMichael Roth sprintf(testname, "%s/nested_struct_list", testname_prefix);
10612d496105SMichael Roth args = g_malloc0(sizeof(*args));
10622d496105SMichael Roth args->ops = ops;
10632d496105SMichael Roth args->test_data = NULL;
10642d496105SMichael Roth g_test_add_data_func(testname, args, test_nested_struct_list);
10652d496105SMichael Roth }
10668addacddSMichael Roth
10678addacddSMichael Roth if (ops->caps & VCAP_PRIMITIVE_LISTS) {
10688addacddSMichael Roth i = 0;
10698addacddSMichael Roth while (pt_values[i].type != PTYPE_EOL) {
10708addacddSMichael Roth sprintf(testname, "%s/primitive_list/%s", testname_prefix,
10718addacddSMichael Roth pt_values[i].description);
10728addacddSMichael Roth args = g_malloc0(sizeof(*args));
10738addacddSMichael Roth args->ops = ops;
10748addacddSMichael Roth args->test_data = &pt_values[i];
10758addacddSMichael Roth g_test_add_data_func(testname, args, test_primitive_lists);
10768addacddSMichael Roth i++;
10778addacddSMichael Roth }
10788addacddSMichael Roth }
10792d496105SMichael Roth }
10802d496105SMichael Roth
main(int argc,char ** argv)10812d496105SMichael Roth int main(int argc, char **argv)
10822d496105SMichael Roth {
10832d496105SMichael Roth int i = 0;
10842d496105SMichael Roth
10852d496105SMichael Roth g_test_init(&argc, &argv, NULL);
10862d496105SMichael Roth
10872d496105SMichael Roth while (visitors[i].type != NULL) {
10882d496105SMichael Roth add_visitor_type(&visitors[i]);
10892d496105SMichael Roth i++;
10902d496105SMichael Roth }
10912d496105SMichael Roth
10922d496105SMichael Roth g_test_run();
10932d496105SMichael Roth
10942d496105SMichael Roth return 0;
10952d496105SMichael Roth }
1096