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 1779ee7df8SPaolo Bonzini #include "qemu-common.h" 182d496105SMichael Roth #include "test-qapi-visit.h" 19da34e65cSMarkus Armbruster #include "qapi/error.h" 20c7eb39cbSEric Blake #include "qapi/qmp/qjson.h" 21fc81fa1eSMarkus Armbruster #include "qapi/qmp/qstring.h" 22b3db211fSDaniel P. Berrange #include "qapi/qobject-input-visitor.h" 23b3db211fSDaniel P. Berrange #include "qapi/qobject-output-visitor.h" 240d30b0a2SMichael Roth #include "qapi/string-input-visitor.h" 250d30b0a2SMichael Roth #include "qapi/string-output-visitor.h" 268addacddSMichael Roth #include "qapi/dealloc-visitor.h" 278addacddSMichael Roth 288addacddSMichael Roth enum PrimitiveTypeKind { 298addacddSMichael Roth PTYPE_STRING = 0, 308addacddSMichael Roth PTYPE_BOOLEAN, 318addacddSMichael Roth PTYPE_NUMBER, 328addacddSMichael Roth PTYPE_INTEGER, 338addacddSMichael Roth PTYPE_U8, 348addacddSMichael Roth PTYPE_U16, 358addacddSMichael Roth PTYPE_U32, 368addacddSMichael Roth PTYPE_U64, 378addacddSMichael Roth PTYPE_S8, 388addacddSMichael Roth PTYPE_S16, 398addacddSMichael Roth PTYPE_S32, 408addacddSMichael Roth PTYPE_S64, 418addacddSMichael Roth PTYPE_EOL, 428addacddSMichael Roth }; 432d496105SMichael Roth 442d496105SMichael Roth typedef struct PrimitiveType { 452d496105SMichael Roth union { 462d496105SMichael Roth const char *string; 472d496105SMichael Roth bool boolean; 482d496105SMichael Roth double number; 492d496105SMichael Roth int64_t integer; 502d496105SMichael Roth uint8_t u8; 512d496105SMichael Roth uint16_t u16; 522d496105SMichael Roth uint32_t u32; 532d496105SMichael Roth uint64_t u64; 542d496105SMichael Roth int8_t s8; 552d496105SMichael Roth int16_t s16; 562d496105SMichael Roth int32_t s32; 572d496105SMichael Roth int64_t s64; 582d496105SMichael Roth intmax_t max; 592d496105SMichael Roth } value; 608addacddSMichael Roth enum PrimitiveTypeKind type; 612d496105SMichael Roth const char *description; 622d496105SMichael Roth } PrimitiveType; 632d496105SMichael Roth 648addacddSMichael Roth typedef struct PrimitiveList { 658addacddSMichael Roth union { 668addacddSMichael Roth strList *strings; 678addacddSMichael Roth boolList *booleans; 688addacddSMichael Roth numberList *numbers; 698addacddSMichael Roth intList *integers; 708addacddSMichael Roth int8List *s8_integers; 718addacddSMichael Roth int16List *s16_integers; 728addacddSMichael Roth int32List *s32_integers; 738addacddSMichael Roth int64List *s64_integers; 748addacddSMichael Roth uint8List *u8_integers; 758addacddSMichael Roth uint16List *u16_integers; 768addacddSMichael Roth uint32List *u32_integers; 778addacddSMichael Roth uint64List *u64_integers; 788addacddSMichael Roth } value; 798addacddSMichael Roth enum PrimitiveTypeKind type; 808addacddSMichael Roth const char *description; 818addacddSMichael Roth } PrimitiveList; 828addacddSMichael Roth 832d496105SMichael Roth /* test helpers */ 842d496105SMichael Roth 858addacddSMichael Roth typedef void (*VisitorFunc)(Visitor *v, void **native, Error **errp); 868addacddSMichael Roth 878addacddSMichael Roth static void dealloc_helper(void *native_in, VisitorFunc visit, Error **errp) 888addacddSMichael Roth { 892c0ef9f4SEric Blake Visitor *v = qapi_dealloc_visitor_new(); 908addacddSMichael Roth 912c0ef9f4SEric Blake visit(v, &native_in, errp); 928addacddSMichael Roth 932c0ef9f4SEric Blake visit_free(v); 948addacddSMichael Roth } 958addacddSMichael Roth 962d496105SMichael Roth static void visit_primitive_type(Visitor *v, void **native, Error **errp) 972d496105SMichael Roth { 982d496105SMichael Roth PrimitiveType *pt = *native; 992d496105SMichael Roth switch(pt->type) { 1002d496105SMichael Roth case PTYPE_STRING: 10151e72bc1SEric Blake visit_type_str(v, NULL, (char **)&pt->value.string, errp); 1022d496105SMichael Roth break; 1032d496105SMichael Roth case PTYPE_BOOLEAN: 10451e72bc1SEric Blake visit_type_bool(v, NULL, &pt->value.boolean, errp); 1052d496105SMichael Roth break; 1062d496105SMichael Roth case PTYPE_NUMBER: 10751e72bc1SEric Blake visit_type_number(v, NULL, &pt->value.number, errp); 1082d496105SMichael Roth break; 1092d496105SMichael Roth case PTYPE_INTEGER: 11051e72bc1SEric Blake visit_type_int(v, NULL, &pt->value.integer, errp); 1112d496105SMichael Roth break; 1122d496105SMichael Roth case PTYPE_U8: 11351e72bc1SEric Blake visit_type_uint8(v, NULL, &pt->value.u8, errp); 1142d496105SMichael Roth break; 1152d496105SMichael Roth case PTYPE_U16: 11651e72bc1SEric Blake visit_type_uint16(v, NULL, &pt->value.u16, errp); 1172d496105SMichael Roth break; 1182d496105SMichael Roth case PTYPE_U32: 11951e72bc1SEric Blake visit_type_uint32(v, NULL, &pt->value.u32, errp); 1202d496105SMichael Roth break; 1212d496105SMichael Roth case PTYPE_U64: 12251e72bc1SEric Blake visit_type_uint64(v, NULL, &pt->value.u64, errp); 1232d496105SMichael Roth break; 1242d496105SMichael Roth case PTYPE_S8: 12551e72bc1SEric Blake visit_type_int8(v, NULL, &pt->value.s8, errp); 1262d496105SMichael Roth break; 1272d496105SMichael Roth case PTYPE_S16: 12851e72bc1SEric Blake visit_type_int16(v, NULL, &pt->value.s16, errp); 1292d496105SMichael Roth break; 1302d496105SMichael Roth case PTYPE_S32: 13151e72bc1SEric Blake visit_type_int32(v, NULL, &pt->value.s32, errp); 1322d496105SMichael Roth break; 1332d496105SMichael Roth case PTYPE_S64: 13451e72bc1SEric Blake visit_type_int64(v, NULL, &pt->value.s64, errp); 1352d496105SMichael Roth break; 1362d496105SMichael Roth case PTYPE_EOL: 137dfc6f865SStefan Weil g_assert_not_reached(); 1382d496105SMichael Roth } 1392d496105SMichael Roth } 1402d496105SMichael Roth 1418addacddSMichael Roth static void visit_primitive_list(Visitor *v, void **native, Error **errp) 1428addacddSMichael Roth { 1438addacddSMichael Roth PrimitiveList *pl = *native; 1448addacddSMichael Roth switch (pl->type) { 1458addacddSMichael Roth case PTYPE_STRING: 14651e72bc1SEric Blake visit_type_strList(v, NULL, &pl->value.strings, errp); 1478addacddSMichael Roth break; 1488addacddSMichael Roth case PTYPE_BOOLEAN: 14951e72bc1SEric Blake visit_type_boolList(v, NULL, &pl->value.booleans, errp); 1508addacddSMichael Roth break; 1518addacddSMichael Roth case PTYPE_NUMBER: 15251e72bc1SEric Blake visit_type_numberList(v, NULL, &pl->value.numbers, errp); 1538addacddSMichael Roth break; 1548addacddSMichael Roth case PTYPE_INTEGER: 15551e72bc1SEric Blake visit_type_intList(v, NULL, &pl->value.integers, errp); 1568addacddSMichael Roth break; 1578addacddSMichael Roth case PTYPE_S8: 15851e72bc1SEric Blake visit_type_int8List(v, NULL, &pl->value.s8_integers, errp); 1598addacddSMichael Roth break; 1608addacddSMichael Roth case PTYPE_S16: 16151e72bc1SEric Blake visit_type_int16List(v, NULL, &pl->value.s16_integers, errp); 1628addacddSMichael Roth break; 1638addacddSMichael Roth case PTYPE_S32: 16451e72bc1SEric Blake visit_type_int32List(v, NULL, &pl->value.s32_integers, errp); 1658addacddSMichael Roth break; 1668addacddSMichael Roth case PTYPE_S64: 16751e72bc1SEric Blake visit_type_int64List(v, NULL, &pl->value.s64_integers, errp); 1688addacddSMichael Roth break; 1698addacddSMichael Roth case PTYPE_U8: 17051e72bc1SEric Blake visit_type_uint8List(v, NULL, &pl->value.u8_integers, errp); 1718addacddSMichael Roth break; 1728addacddSMichael Roth case PTYPE_U16: 17351e72bc1SEric Blake visit_type_uint16List(v, NULL, &pl->value.u16_integers, errp); 1748addacddSMichael Roth break; 1758addacddSMichael Roth case PTYPE_U32: 17651e72bc1SEric Blake visit_type_uint32List(v, NULL, &pl->value.u32_integers, errp); 1778addacddSMichael Roth break; 1788addacddSMichael Roth case PTYPE_U64: 17951e72bc1SEric Blake visit_type_uint64List(v, NULL, &pl->value.u64_integers, errp); 1808addacddSMichael Roth break; 1818addacddSMichael Roth default: 182dfc6f865SStefan Weil g_assert_not_reached(); 1838addacddSMichael Roth } 1848addacddSMichael Roth } 1858addacddSMichael Roth 1862d496105SMichael Roth 1872d496105SMichael Roth static TestStruct *struct_create(void) 1882d496105SMichael Roth { 1892d496105SMichael Roth TestStruct *ts = g_malloc0(sizeof(*ts)); 1902d496105SMichael Roth ts->integer = -42; 1912d496105SMichael Roth ts->boolean = true; 1922d496105SMichael Roth ts->string = strdup("test string"); 1932d496105SMichael Roth return ts; 1942d496105SMichael Roth } 1952d496105SMichael Roth 1962d496105SMichael Roth static void struct_compare(TestStruct *ts1, TestStruct *ts2) 1972d496105SMichael Roth { 1982d496105SMichael Roth g_assert(ts1); 1992d496105SMichael Roth g_assert(ts2); 2002d496105SMichael Roth g_assert_cmpint(ts1->integer, ==, ts2->integer); 2012d496105SMichael Roth g_assert(ts1->boolean == ts2->boolean); 2022d496105SMichael Roth g_assert_cmpstr(ts1->string, ==, ts2->string); 2032d496105SMichael Roth } 2042d496105SMichael Roth 2052d496105SMichael Roth static void struct_cleanup(TestStruct *ts) 2062d496105SMichael Roth { 2072d496105SMichael Roth g_free(ts->string); 2082d496105SMichael Roth g_free(ts); 2092d496105SMichael Roth } 2102d496105SMichael Roth 2112d496105SMichael Roth static void visit_struct(Visitor *v, void **native, Error **errp) 2122d496105SMichael Roth { 21351e72bc1SEric Blake visit_type_TestStruct(v, NULL, (TestStruct **)native, errp); 2142d496105SMichael Roth } 2152d496105SMichael Roth 216b6fcf32dSEric Blake static UserDefTwo *nested_struct_create(void) 2172d496105SMichael Roth { 218b6fcf32dSEric Blake UserDefTwo *udnp = g_malloc0(sizeof(*udnp)); 2192d496105SMichael Roth udnp->string0 = strdup("test_string0"); 2206446a592SEric Blake udnp->dict1 = g_malloc0(sizeof(*udnp->dict1)); 2216446a592SEric Blake udnp->dict1->string1 = strdup("test_string1"); 2226446a592SEric Blake udnp->dict1->dict2 = g_malloc0(sizeof(*udnp->dict1->dict2)); 2236446a592SEric Blake udnp->dict1->dict2->userdef = g_new0(UserDefOne, 1); 224ddf21908SEric Blake udnp->dict1->dict2->userdef->integer = 42; 2256446a592SEric Blake udnp->dict1->dict2->userdef->string = strdup("test_string"); 2266446a592SEric Blake udnp->dict1->dict2->string = strdup("test_string2"); 2276446a592SEric Blake udnp->dict1->dict3 = g_malloc0(sizeof(*udnp->dict1->dict3)); 2286446a592SEric Blake udnp->dict1->has_dict3 = true; 2296446a592SEric Blake udnp->dict1->dict3->userdef = g_new0(UserDefOne, 1); 230ddf21908SEric Blake udnp->dict1->dict3->userdef->integer = 43; 2316446a592SEric Blake udnp->dict1->dict3->userdef->string = strdup("test_string"); 2326446a592SEric Blake udnp->dict1->dict3->string = strdup("test_string3"); 2332d496105SMichael Roth return udnp; 2342d496105SMichael Roth } 2352d496105SMichael Roth 236b6fcf32dSEric Blake static void nested_struct_compare(UserDefTwo *udnp1, UserDefTwo *udnp2) 2372d496105SMichael Roth { 2382d496105SMichael Roth g_assert(udnp1); 2392d496105SMichael Roth g_assert(udnp2); 2402d496105SMichael Roth g_assert_cmpstr(udnp1->string0, ==, udnp2->string0); 2416446a592SEric Blake g_assert_cmpstr(udnp1->dict1->string1, ==, udnp2->dict1->string1); 242ddf21908SEric Blake g_assert_cmpint(udnp1->dict1->dict2->userdef->integer, ==, 243ddf21908SEric Blake udnp2->dict1->dict2->userdef->integer); 2446446a592SEric Blake g_assert_cmpstr(udnp1->dict1->dict2->userdef->string, ==, 2456446a592SEric Blake udnp2->dict1->dict2->userdef->string); 2466446a592SEric Blake g_assert_cmpstr(udnp1->dict1->dict2->string, ==, 2476446a592SEric Blake udnp2->dict1->dict2->string); 2486446a592SEric Blake g_assert(udnp1->dict1->has_dict3 == udnp2->dict1->has_dict3); 249ddf21908SEric Blake g_assert_cmpint(udnp1->dict1->dict3->userdef->integer, ==, 250ddf21908SEric Blake udnp2->dict1->dict3->userdef->integer); 2516446a592SEric Blake g_assert_cmpstr(udnp1->dict1->dict3->userdef->string, ==, 2526446a592SEric Blake udnp2->dict1->dict3->userdef->string); 2536446a592SEric Blake g_assert_cmpstr(udnp1->dict1->dict3->string, ==, 2546446a592SEric Blake udnp2->dict1->dict3->string); 2552d496105SMichael Roth } 2562d496105SMichael Roth 257b6fcf32dSEric Blake static void nested_struct_cleanup(UserDefTwo *udnp) 2582d496105SMichael Roth { 259b6fcf32dSEric Blake qapi_free_UserDefTwo(udnp); 2602d496105SMichael Roth } 2612d496105SMichael Roth 2622d496105SMichael Roth static void visit_nested_struct(Visitor *v, void **native, Error **errp) 2632d496105SMichael Roth { 26451e72bc1SEric Blake visit_type_UserDefTwo(v, NULL, (UserDefTwo **)native, errp); 2652d496105SMichael Roth } 2662d496105SMichael Roth 2672d496105SMichael Roth static void visit_nested_struct_list(Visitor *v, void **native, Error **errp) 2682d496105SMichael Roth { 26951e72bc1SEric Blake visit_type_UserDefTwoList(v, NULL, (UserDefTwoList **)native, errp); 2702d496105SMichael Roth } 2712d496105SMichael Roth 2722d496105SMichael Roth /* test cases */ 2732d496105SMichael Roth 2742d496105SMichael Roth typedef enum VisitorCapabilities { 2752d496105SMichael Roth VCAP_PRIMITIVES = 1, 2762d496105SMichael Roth VCAP_STRUCTURES = 2, 2772d496105SMichael Roth VCAP_LISTS = 4, 2788addacddSMichael Roth VCAP_PRIMITIVE_LISTS = 8, 2792d496105SMichael Roth } VisitorCapabilities; 2802d496105SMichael Roth 2812d496105SMichael Roth typedef struct SerializeOps { 2822d496105SMichael Roth void (*serialize)(void *native_in, void **datap, 2832d496105SMichael Roth VisitorFunc visit, Error **errp); 2842d496105SMichael Roth void (*deserialize)(void **native_out, void *datap, 2852d496105SMichael Roth VisitorFunc visit, Error **errp); 2862d496105SMichael Roth void (*cleanup)(void *datap); 2872d496105SMichael Roth const char *type; 2882d496105SMichael Roth VisitorCapabilities caps; 2892d496105SMichael Roth } SerializeOps; 2902d496105SMichael Roth 2912d496105SMichael Roth typedef struct TestArgs { 2922d496105SMichael Roth const SerializeOps *ops; 2932d496105SMichael Roth void *test_data; 2942d496105SMichael Roth } TestArgs; 2952d496105SMichael Roth 2962d496105SMichael Roth static void test_primitives(gconstpointer opaque) 2972d496105SMichael Roth { 2982d496105SMichael Roth TestArgs *args = (TestArgs *) opaque; 2992d496105SMichael Roth const SerializeOps *ops = args->ops; 3002d496105SMichael Roth PrimitiveType *pt = args->test_data; 3012d496105SMichael Roth PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy)); 3022d496105SMichael Roth void *serialize_data; 3032d496105SMichael Roth 3042d496105SMichael Roth pt_copy->type = pt->type; 3053f66f764SEric Blake ops->serialize(pt, &serialize_data, visit_primitive_type, &error_abort); 3063f66f764SEric Blake ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type, 3073f66f764SEric Blake &error_abort); 3082d496105SMichael Roth 3092d496105SMichael Roth g_assert(pt_copy != NULL); 3102d496105SMichael Roth if (pt->type == PTYPE_STRING) { 3112d496105SMichael Roth g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string); 3122bd01ac1SStefan Berger g_free((char *)pt_copy->value.string); 3132d496105SMichael Roth } else if (pt->type == PTYPE_NUMBER) { 314*2a02c139SMarkus Armbruster g_assert_cmpfloat(pt->value.number, ==, pt_copy->value.number); 3152d496105SMichael Roth } else if (pt->type == PTYPE_BOOLEAN) { 3162d496105SMichael Roth g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max); 3172d496105SMichael Roth } else { 3182d496105SMichael Roth g_assert_cmpint(pt->value.max, ==, pt_copy->value.max); 3192d496105SMichael Roth } 3202d496105SMichael Roth 3212d496105SMichael Roth ops->cleanup(serialize_data); 3222d496105SMichael Roth g_free(args); 3232bd01ac1SStefan Berger g_free(pt_copy); 3242d496105SMichael Roth } 3252d496105SMichael Roth 3268addacddSMichael Roth static void test_primitive_lists(gconstpointer opaque) 3278addacddSMichael Roth { 3288addacddSMichael Roth TestArgs *args = (TestArgs *) opaque; 3298addacddSMichael Roth const SerializeOps *ops = args->ops; 3308addacddSMichael Roth PrimitiveType *pt = args->test_data; 331748bfb4eSStefan Weil PrimitiveList pl = { .value = { NULL } }; 332748bfb4eSStefan Weil PrimitiveList pl_copy = { .value = { NULL } }; 3338addacddSMichael Roth PrimitiveList *pl_copy_ptr = &pl_copy; 3348addacddSMichael Roth void *serialize_data; 3358addacddSMichael Roth void *cur_head = NULL; 3368addacddSMichael Roth int i; 3378addacddSMichael Roth 3388addacddSMichael Roth pl.type = pl_copy.type = pt->type; 3398addacddSMichael Roth 3408addacddSMichael Roth /* build up our list of primitive types */ 3418addacddSMichael Roth for (i = 0; i < 32; i++) { 3428addacddSMichael Roth switch (pl.type) { 3438addacddSMichael Roth case PTYPE_STRING: { 34454aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.strings, g_strdup(pt->value.string)); 3458addacddSMichael Roth break; 3468addacddSMichael Roth } 3478addacddSMichael Roth case PTYPE_INTEGER: { 34854aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.integers, pt->value.integer); 3498addacddSMichael Roth break; 3508addacddSMichael Roth } 3518addacddSMichael Roth case PTYPE_S8: { 35254aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.s8_integers, pt->value.s8); 3538addacddSMichael Roth break; 3548addacddSMichael Roth } 3558addacddSMichael Roth case PTYPE_S16: { 35654aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.s16_integers, pt->value.s16); 3578addacddSMichael Roth break; 3588addacddSMichael Roth } 3598addacddSMichael Roth case PTYPE_S32: { 36054aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.s32_integers, pt->value.s32); 3618addacddSMichael Roth break; 3628addacddSMichael Roth } 3638addacddSMichael Roth case PTYPE_S64: { 36454aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.s64_integers, pt->value.s64); 3658addacddSMichael Roth break; 3668addacddSMichael Roth } 3678addacddSMichael Roth case PTYPE_U8: { 36854aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.u8_integers, pt->value.u8); 3698addacddSMichael Roth break; 3708addacddSMichael Roth } 3718addacddSMichael Roth case PTYPE_U16: { 37254aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.u16_integers, pt->value.u16); 3738addacddSMichael Roth break; 3748addacddSMichael Roth } 3758addacddSMichael Roth case PTYPE_U32: { 37654aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.u32_integers, pt->value.u32); 3778addacddSMichael Roth break; 3788addacddSMichael Roth } 3798addacddSMichael Roth case PTYPE_U64: { 38054aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.u64_integers, pt->value.u64); 3818addacddSMichael Roth break; 3828addacddSMichael Roth } 3838addacddSMichael Roth case PTYPE_NUMBER: { 38454aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.numbers, pt->value.number); 3858addacddSMichael Roth break; 3868addacddSMichael Roth } 3878addacddSMichael Roth case PTYPE_BOOLEAN: { 38854aa3de7SEric Blake QAPI_LIST_PREPEND(pl.value.booleans, pt->value.boolean); 3898addacddSMichael Roth break; 3908addacddSMichael Roth } 3918addacddSMichael Roth default: 392dfc6f865SStefan Weil g_assert_not_reached(); 3938addacddSMichael Roth } 3948addacddSMichael Roth } 3958addacddSMichael Roth 3963f66f764SEric Blake ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, 3973f66f764SEric Blake &error_abort); 3983f66f764SEric Blake ops->deserialize((void **)&pl_copy_ptr, serialize_data, 3993f66f764SEric Blake visit_primitive_list, &error_abort); 4008addacddSMichael Roth 4018addacddSMichael Roth i = 0; 4028addacddSMichael Roth 4038addacddSMichael Roth /* compare our deserialized list of primitives to the original */ 4048addacddSMichael Roth do { 4058addacddSMichael Roth switch (pl_copy.type) { 4068addacddSMichael Roth case PTYPE_STRING: { 4078addacddSMichael Roth strList *ptr; 4088addacddSMichael Roth if (cur_head) { 4098addacddSMichael Roth ptr = cur_head; 4108addacddSMichael Roth cur_head = ptr->next; 4118addacddSMichael Roth } else { 4128addacddSMichael Roth cur_head = ptr = pl_copy.value.strings; 4138addacddSMichael Roth } 4148addacddSMichael Roth g_assert_cmpstr(pt->value.string, ==, ptr->value); 4158addacddSMichael Roth break; 4168addacddSMichael Roth } 4178addacddSMichael Roth case PTYPE_INTEGER: { 4188addacddSMichael Roth intList *ptr; 4198addacddSMichael Roth if (cur_head) { 4208addacddSMichael Roth ptr = cur_head; 4218addacddSMichael Roth cur_head = ptr->next; 4228addacddSMichael Roth } else { 4238addacddSMichael Roth cur_head = ptr = pl_copy.value.integers; 4248addacddSMichael Roth } 4258addacddSMichael Roth g_assert_cmpint(pt->value.integer, ==, ptr->value); 4268addacddSMichael Roth break; 4278addacddSMichael Roth } 4288addacddSMichael Roth case PTYPE_S8: { 4298addacddSMichael Roth int8List *ptr; 4308addacddSMichael Roth if (cur_head) { 4318addacddSMichael Roth ptr = cur_head; 4328addacddSMichael Roth cur_head = ptr->next; 4338addacddSMichael Roth } else { 4348addacddSMichael Roth cur_head = ptr = pl_copy.value.s8_integers; 4358addacddSMichael Roth } 4368addacddSMichael Roth g_assert_cmpint(pt->value.s8, ==, ptr->value); 4378addacddSMichael Roth break; 4388addacddSMichael Roth } 4398addacddSMichael Roth case PTYPE_S16: { 4408addacddSMichael Roth int16List *ptr; 4418addacddSMichael Roth if (cur_head) { 4428addacddSMichael Roth ptr = cur_head; 4438addacddSMichael Roth cur_head = ptr->next; 4448addacddSMichael Roth } else { 4458addacddSMichael Roth cur_head = ptr = pl_copy.value.s16_integers; 4468addacddSMichael Roth } 4478addacddSMichael Roth g_assert_cmpint(pt->value.s16, ==, ptr->value); 4488addacddSMichael Roth break; 4498addacddSMichael Roth } 4508addacddSMichael Roth case PTYPE_S32: { 4518addacddSMichael Roth int32List *ptr; 4528addacddSMichael Roth if (cur_head) { 4538addacddSMichael Roth ptr = cur_head; 4548addacddSMichael Roth cur_head = ptr->next; 4558addacddSMichael Roth } else { 4568addacddSMichael Roth cur_head = ptr = pl_copy.value.s32_integers; 4578addacddSMichael Roth } 4588addacddSMichael Roth g_assert_cmpint(pt->value.s32, ==, ptr->value); 4598addacddSMichael Roth break; 4608addacddSMichael Roth } 4618addacddSMichael Roth case PTYPE_S64: { 4628addacddSMichael Roth int64List *ptr; 4638addacddSMichael Roth if (cur_head) { 4648addacddSMichael Roth ptr = cur_head; 4658addacddSMichael Roth cur_head = ptr->next; 4668addacddSMichael Roth } else { 4678addacddSMichael Roth cur_head = ptr = pl_copy.value.s64_integers; 4688addacddSMichael Roth } 4698addacddSMichael Roth g_assert_cmpint(pt->value.s64, ==, ptr->value); 4708addacddSMichael Roth break; 4718addacddSMichael Roth } 4728addacddSMichael Roth case PTYPE_U8: { 4738addacddSMichael Roth uint8List *ptr; 4748addacddSMichael Roth if (cur_head) { 4758addacddSMichael Roth ptr = cur_head; 4768addacddSMichael Roth cur_head = ptr->next; 4778addacddSMichael Roth } else { 4788addacddSMichael Roth cur_head = ptr = pl_copy.value.u8_integers; 4798addacddSMichael Roth } 4808addacddSMichael Roth g_assert_cmpint(pt->value.u8, ==, ptr->value); 4818addacddSMichael Roth break; 4828addacddSMichael Roth } 4838addacddSMichael Roth case PTYPE_U16: { 4848addacddSMichael Roth uint16List *ptr; 4858addacddSMichael Roth if (cur_head) { 4868addacddSMichael Roth ptr = cur_head; 4878addacddSMichael Roth cur_head = ptr->next; 4888addacddSMichael Roth } else { 4898addacddSMichael Roth cur_head = ptr = pl_copy.value.u16_integers; 4908addacddSMichael Roth } 4918addacddSMichael Roth g_assert_cmpint(pt->value.u16, ==, ptr->value); 4928addacddSMichael Roth break; 4938addacddSMichael Roth } 4948addacddSMichael Roth case PTYPE_U32: { 4958addacddSMichael Roth uint32List *ptr; 4968addacddSMichael Roth if (cur_head) { 4978addacddSMichael Roth ptr = cur_head; 4988addacddSMichael Roth cur_head = ptr->next; 4998addacddSMichael Roth } else { 5008addacddSMichael Roth cur_head = ptr = pl_copy.value.u32_integers; 5018addacddSMichael Roth } 5028addacddSMichael Roth g_assert_cmpint(pt->value.u32, ==, ptr->value); 5038addacddSMichael Roth break; 5048addacddSMichael Roth } 5058addacddSMichael Roth case PTYPE_U64: { 5068addacddSMichael Roth uint64List *ptr; 5078addacddSMichael Roth if (cur_head) { 5088addacddSMichael Roth ptr = cur_head; 5098addacddSMichael Roth cur_head = ptr->next; 5108addacddSMichael Roth } else { 5118addacddSMichael Roth cur_head = ptr = pl_copy.value.u64_integers; 5128addacddSMichael Roth } 5138addacddSMichael Roth g_assert_cmpint(pt->value.u64, ==, ptr->value); 5148addacddSMichael Roth break; 5158addacddSMichael Roth } 5168addacddSMichael Roth case PTYPE_NUMBER: { 5178addacddSMichael Roth numberList *ptr; 5188addacddSMichael Roth GString *double_expected = g_string_new(""); 5198addacddSMichael Roth GString *double_actual = g_string_new(""); 5208addacddSMichael Roth if (cur_head) { 5218addacddSMichael Roth ptr = cur_head; 5228addacddSMichael Roth cur_head = ptr->next; 5238addacddSMichael Roth } else { 5248addacddSMichael Roth cur_head = ptr = pl_copy.value.numbers; 5258addacddSMichael Roth } 5268addacddSMichael Roth /* we serialize with %f for our reference visitors, so rather than 5278addacddSMichael Roth * fuzzy floating math to test "equality", just compare the 5288addacddSMichael Roth * formatted values 5298addacddSMichael Roth */ 5308addacddSMichael Roth g_string_printf(double_expected, "%.6f", pt->value.number); 5318addacddSMichael Roth g_string_printf(double_actual, "%.6f", ptr->value); 5328addacddSMichael Roth g_assert_cmpstr(double_actual->str, ==, double_expected->str); 5338addacddSMichael Roth g_string_free(double_expected, true); 5348addacddSMichael Roth g_string_free(double_actual, true); 5358addacddSMichael Roth break; 5368addacddSMichael Roth } 5378addacddSMichael Roth case PTYPE_BOOLEAN: { 5388addacddSMichael Roth boolList *ptr; 5398addacddSMichael Roth if (cur_head) { 5408addacddSMichael Roth ptr = cur_head; 5418addacddSMichael Roth cur_head = ptr->next; 5428addacddSMichael Roth } else { 5438addacddSMichael Roth cur_head = ptr = pl_copy.value.booleans; 5448addacddSMichael Roth } 5458addacddSMichael Roth g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value); 5468addacddSMichael Roth break; 5478addacddSMichael Roth } 5488addacddSMichael Roth default: 549dfc6f865SStefan Weil g_assert_not_reached(); 5508addacddSMichael Roth } 5518addacddSMichael Roth i++; 5528addacddSMichael Roth } while (cur_head); 5538addacddSMichael Roth 5548addacddSMichael Roth g_assert_cmpint(i, ==, 33); 5558addacddSMichael Roth 5568addacddSMichael Roth ops->cleanup(serialize_data); 5573f66f764SEric Blake dealloc_helper(&pl, visit_primitive_list, &error_abort); 5583f66f764SEric Blake dealloc_helper(&pl_copy, visit_primitive_list, &error_abort); 5598addacddSMichael Roth g_free(args); 5608addacddSMichael Roth } 5618addacddSMichael Roth 5622d496105SMichael Roth static void test_struct(gconstpointer opaque) 5632d496105SMichael Roth { 5642d496105SMichael Roth TestArgs *args = (TestArgs *) opaque; 5652d496105SMichael Roth const SerializeOps *ops = args->ops; 5662d496105SMichael Roth TestStruct *ts = struct_create(); 5672d496105SMichael Roth TestStruct *ts_copy = NULL; 5682d496105SMichael Roth void *serialize_data; 5692d496105SMichael Roth 5703f66f764SEric Blake ops->serialize(ts, &serialize_data, visit_struct, &error_abort); 5713f66f764SEric Blake ops->deserialize((void **)&ts_copy, serialize_data, visit_struct, 5723f66f764SEric Blake &error_abort); 5732d496105SMichael Roth 5742d496105SMichael Roth struct_compare(ts, ts_copy); 5752d496105SMichael Roth 5762d496105SMichael Roth struct_cleanup(ts); 5772d496105SMichael Roth struct_cleanup(ts_copy); 5782d496105SMichael Roth 5792d496105SMichael Roth ops->cleanup(serialize_data); 5802d496105SMichael Roth g_free(args); 5812d496105SMichael Roth } 5822d496105SMichael Roth 5832d496105SMichael Roth static void test_nested_struct(gconstpointer opaque) 5842d496105SMichael Roth { 5852d496105SMichael Roth TestArgs *args = (TestArgs *) opaque; 5862d496105SMichael Roth const SerializeOps *ops = args->ops; 587b6fcf32dSEric Blake UserDefTwo *udnp = nested_struct_create(); 588b6fcf32dSEric Blake UserDefTwo *udnp_copy = NULL; 5892d496105SMichael Roth void *serialize_data; 5902d496105SMichael Roth 5913f66f764SEric Blake ops->serialize(udnp, &serialize_data, visit_nested_struct, &error_abort); 592b6fcf32dSEric Blake ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct, 5933f66f764SEric Blake &error_abort); 5942d496105SMichael Roth 5952d496105SMichael Roth nested_struct_compare(udnp, udnp_copy); 5962d496105SMichael Roth 5972d496105SMichael Roth nested_struct_cleanup(udnp); 5982d496105SMichael Roth nested_struct_cleanup(udnp_copy); 5992d496105SMichael Roth 6002d496105SMichael Roth ops->cleanup(serialize_data); 6012d496105SMichael Roth g_free(args); 6022d496105SMichael Roth } 6032d496105SMichael Roth 6042d496105SMichael Roth static void test_nested_struct_list(gconstpointer opaque) 6052d496105SMichael Roth { 6062d496105SMichael Roth TestArgs *args = (TestArgs *) opaque; 6072d496105SMichael Roth const SerializeOps *ops = args->ops; 608b6fcf32dSEric Blake UserDefTwoList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL; 6092d496105SMichael Roth void *serialize_data; 6102d496105SMichael Roth int i = 0; 6112d496105SMichael Roth 6122d496105SMichael Roth for (i = 0; i < 8; i++) { 61354aa3de7SEric Blake QAPI_LIST_PREPEND(listp, nested_struct_create()); 6142d496105SMichael Roth } 6152d496105SMichael Roth 6163f66f764SEric Blake ops->serialize(listp, &serialize_data, visit_nested_struct_list, 6173f66f764SEric Blake &error_abort); 6182d496105SMichael Roth ops->deserialize((void **)&listp_copy, serialize_data, 6193f66f764SEric Blake visit_nested_struct_list, &error_abort); 6202d496105SMichael Roth 6212d496105SMichael Roth tmp = listp; 6222d496105SMichael Roth tmp_copy = listp_copy; 6232d496105SMichael Roth while (listp_copy) { 6242d496105SMichael Roth g_assert(listp); 6252d496105SMichael Roth nested_struct_compare(listp->value, listp_copy->value); 6262d496105SMichael Roth listp = listp->next; 6272d496105SMichael Roth listp_copy = listp_copy->next; 6282d496105SMichael Roth } 6292d496105SMichael Roth 630b6fcf32dSEric Blake qapi_free_UserDefTwoList(tmp); 631b6fcf32dSEric Blake qapi_free_UserDefTwoList(tmp_copy); 6322d496105SMichael Roth 6332d496105SMichael Roth ops->cleanup(serialize_data); 6342d496105SMichael Roth g_free(args); 6352d496105SMichael Roth } 6362d496105SMichael Roth 637748bfb4eSStefan Weil static PrimitiveType pt_values[] = { 6382d496105SMichael Roth /* string tests */ 6392d496105SMichael Roth { 6402d496105SMichael Roth .description = "string_empty", 6412d496105SMichael Roth .type = PTYPE_STRING, 6422d496105SMichael Roth .value.string = "", 6432d496105SMichael Roth }, 6442d496105SMichael Roth { 6452d496105SMichael Roth .description = "string_whitespace", 6462d496105SMichael Roth .type = PTYPE_STRING, 6472d496105SMichael Roth .value.string = "a b c\td", 6482d496105SMichael Roth }, 6492d496105SMichael Roth { 6502d496105SMichael Roth .description = "string_newlines", 6512d496105SMichael Roth .type = PTYPE_STRING, 6522d496105SMichael Roth .value.string = "a\nb\n", 6532d496105SMichael Roth }, 6542d496105SMichael Roth { 6552d496105SMichael Roth .description = "string_commas", 6562d496105SMichael Roth .type = PTYPE_STRING, 6572d496105SMichael Roth .value.string = "a,b, c,d", 6582d496105SMichael Roth }, 6592d496105SMichael Roth { 6602d496105SMichael Roth .description = "string_single_quoted", 6612d496105SMichael Roth .type = PTYPE_STRING, 6622d496105SMichael Roth .value.string = "'a b',cd", 6632d496105SMichael Roth }, 6642d496105SMichael Roth { 6652d496105SMichael Roth .description = "string_double_quoted", 6662d496105SMichael Roth .type = PTYPE_STRING, 6672d496105SMichael Roth .value.string = "\"a b\",cd", 6682d496105SMichael Roth }, 6692d496105SMichael Roth /* boolean tests */ 6702d496105SMichael Roth { 6712d496105SMichael Roth .description = "boolean_true1", 6722d496105SMichael Roth .type = PTYPE_BOOLEAN, 6732d496105SMichael Roth .value.boolean = true, 6742d496105SMichael Roth }, 6752d496105SMichael Roth { 6762d496105SMichael Roth .description = "boolean_true2", 6772d496105SMichael Roth .type = PTYPE_BOOLEAN, 6782d496105SMichael Roth .value.boolean = 8, 6792d496105SMichael Roth }, 6802d496105SMichael Roth { 6812d496105SMichael Roth .description = "boolean_true3", 6822d496105SMichael Roth .type = PTYPE_BOOLEAN, 6832d496105SMichael Roth .value.boolean = -1, 6842d496105SMichael Roth }, 6852d496105SMichael Roth { 6862d496105SMichael Roth .description = "boolean_false1", 6872d496105SMichael Roth .type = PTYPE_BOOLEAN, 6882d496105SMichael Roth .value.boolean = false, 6892d496105SMichael Roth }, 6902d496105SMichael Roth { 6912d496105SMichael Roth .description = "boolean_false2", 6922d496105SMichael Roth .type = PTYPE_BOOLEAN, 6932d496105SMichael Roth .value.boolean = 0, 6942d496105SMichael Roth }, 6952d496105SMichael Roth /* number tests (double) */ 6962d496105SMichael Roth { 6972d496105SMichael Roth .description = "number_sanity1", 6982d496105SMichael Roth .type = PTYPE_NUMBER, 6992d496105SMichael Roth .value.number = -1, 7002d496105SMichael Roth }, 7012d496105SMichael Roth { 7022d496105SMichael Roth .description = "number_sanity2", 7032d496105SMichael Roth .type = PTYPE_NUMBER, 704*2a02c139SMarkus Armbruster .value.number = 3.141593, 7052d496105SMichael Roth }, 7062d496105SMichael Roth { 7072d496105SMichael Roth .description = "number_min", 7082d496105SMichael Roth .type = PTYPE_NUMBER, 7092d496105SMichael Roth .value.number = DBL_MIN, 7102d496105SMichael Roth }, 7112d496105SMichael Roth { 7122d496105SMichael Roth .description = "number_max", 7132d496105SMichael Roth .type = PTYPE_NUMBER, 7142d496105SMichael Roth .value.number = DBL_MAX, 7152d496105SMichael Roth }, 7162d496105SMichael Roth /* integer tests (int64) */ 7172d496105SMichael Roth { 7182d496105SMichael Roth .description = "integer_sanity1", 7192d496105SMichael Roth .type = PTYPE_INTEGER, 7202d496105SMichael Roth .value.integer = -1, 7212d496105SMichael Roth }, 7222d496105SMichael Roth { 7232d496105SMichael Roth .description = "integer_sanity2", 7242d496105SMichael Roth .type = PTYPE_INTEGER, 7252d496105SMichael Roth .value.integer = INT64_MAX / 2 + 1, 7262d496105SMichael Roth }, 7272d496105SMichael Roth { 7282d496105SMichael Roth .description = "integer_min", 7292d496105SMichael Roth .type = PTYPE_INTEGER, 7302d496105SMichael Roth .value.integer = INT64_MIN, 7312d496105SMichael Roth }, 7322d496105SMichael Roth { 7332d496105SMichael Roth .description = "integer_max", 7342d496105SMichael Roth .type = PTYPE_INTEGER, 7352d496105SMichael Roth .value.integer = INT64_MAX, 7362d496105SMichael Roth }, 7372d496105SMichael Roth /* uint8 tests */ 7382d496105SMichael Roth { 7392d496105SMichael Roth .description = "uint8_sanity1", 7402d496105SMichael Roth .type = PTYPE_U8, 7412d496105SMichael Roth .value.u8 = 1, 7422d496105SMichael Roth }, 7432d496105SMichael Roth { 7442d496105SMichael Roth .description = "uint8_sanity2", 7452d496105SMichael Roth .type = PTYPE_U8, 7462d496105SMichael Roth .value.u8 = UINT8_MAX / 2 + 1, 7472d496105SMichael Roth }, 7482d496105SMichael Roth { 7492d496105SMichael Roth .description = "uint8_min", 7502d496105SMichael Roth .type = PTYPE_U8, 7512d496105SMichael Roth .value.u8 = 0, 7522d496105SMichael Roth }, 7532d496105SMichael Roth { 7542d496105SMichael Roth .description = "uint8_max", 7552d496105SMichael Roth .type = PTYPE_U8, 7562d496105SMichael Roth .value.u8 = UINT8_MAX, 7572d496105SMichael Roth }, 7582d496105SMichael Roth /* uint16 tests */ 7592d496105SMichael Roth { 7602d496105SMichael Roth .description = "uint16_sanity1", 7612d496105SMichael Roth .type = PTYPE_U16, 7622d496105SMichael Roth .value.u16 = 1, 7632d496105SMichael Roth }, 7642d496105SMichael Roth { 7652d496105SMichael Roth .description = "uint16_sanity2", 7662d496105SMichael Roth .type = PTYPE_U16, 7672d496105SMichael Roth .value.u16 = UINT16_MAX / 2 + 1, 7682d496105SMichael Roth }, 7692d496105SMichael Roth { 7702d496105SMichael Roth .description = "uint16_min", 7712d496105SMichael Roth .type = PTYPE_U16, 7722d496105SMichael Roth .value.u16 = 0, 7732d496105SMichael Roth }, 7742d496105SMichael Roth { 7752d496105SMichael Roth .description = "uint16_max", 7762d496105SMichael Roth .type = PTYPE_U16, 7772d496105SMichael Roth .value.u16 = UINT16_MAX, 7782d496105SMichael Roth }, 7792d496105SMichael Roth /* uint32 tests */ 7802d496105SMichael Roth { 7812d496105SMichael Roth .description = "uint32_sanity1", 7822d496105SMichael Roth .type = PTYPE_U32, 7832d496105SMichael Roth .value.u32 = 1, 7842d496105SMichael Roth }, 7852d496105SMichael Roth { 7862d496105SMichael Roth .description = "uint32_sanity2", 7872d496105SMichael Roth .type = PTYPE_U32, 7882d496105SMichael Roth .value.u32 = UINT32_MAX / 2 + 1, 7892d496105SMichael Roth }, 7902d496105SMichael Roth { 7912d496105SMichael Roth .description = "uint32_min", 7922d496105SMichael Roth .type = PTYPE_U32, 7932d496105SMichael Roth .value.u32 = 0, 7942d496105SMichael Roth }, 7952d496105SMichael Roth { 7962d496105SMichael Roth .description = "uint32_max", 7972d496105SMichael Roth .type = PTYPE_U32, 7982d496105SMichael Roth .value.u32 = UINT32_MAX, 7992d496105SMichael Roth }, 8002d496105SMichael Roth /* uint64 tests */ 8012d496105SMichael Roth { 8022d496105SMichael Roth .description = "uint64_sanity1", 8032d496105SMichael Roth .type = PTYPE_U64, 8042d496105SMichael Roth .value.u64 = 1, 8052d496105SMichael Roth }, 8062d496105SMichael Roth { 8072d496105SMichael Roth .description = "uint64_sanity2", 8082d496105SMichael Roth .type = PTYPE_U64, 8092d496105SMichael Roth .value.u64 = UINT64_MAX / 2 + 1, 8102d496105SMichael Roth }, 8112d496105SMichael Roth { 8122d496105SMichael Roth .description = "uint64_min", 8132d496105SMichael Roth .type = PTYPE_U64, 8142d496105SMichael Roth .value.u64 = 0, 8152d496105SMichael Roth }, 8162d496105SMichael Roth { 8172d496105SMichael Roth .description = "uint64_max", 8182d496105SMichael Roth .type = PTYPE_U64, 8192d496105SMichael Roth .value.u64 = UINT64_MAX, 8202d496105SMichael Roth }, 8212d496105SMichael Roth /* int8 tests */ 8222d496105SMichael Roth { 8232d496105SMichael Roth .description = "int8_sanity1", 8242d496105SMichael Roth .type = PTYPE_S8, 8252d496105SMichael Roth .value.s8 = -1, 8262d496105SMichael Roth }, 8272d496105SMichael Roth { 8282d496105SMichael Roth .description = "int8_sanity2", 8292d496105SMichael Roth .type = PTYPE_S8, 8302d496105SMichael Roth .value.s8 = INT8_MAX / 2 + 1, 8312d496105SMichael Roth }, 8322d496105SMichael Roth { 8332d496105SMichael Roth .description = "int8_min", 8342d496105SMichael Roth .type = PTYPE_S8, 8352d496105SMichael Roth .value.s8 = INT8_MIN, 8362d496105SMichael Roth }, 8372d496105SMichael Roth { 8382d496105SMichael Roth .description = "int8_max", 8392d496105SMichael Roth .type = PTYPE_S8, 8402d496105SMichael Roth .value.s8 = INT8_MAX, 8412d496105SMichael Roth }, 8422d496105SMichael Roth /* int16 tests */ 8432d496105SMichael Roth { 8442d496105SMichael Roth .description = "int16_sanity1", 8452d496105SMichael Roth .type = PTYPE_S16, 8462d496105SMichael Roth .value.s16 = -1, 8472d496105SMichael Roth }, 8482d496105SMichael Roth { 8492d496105SMichael Roth .description = "int16_sanity2", 8502d496105SMichael Roth .type = PTYPE_S16, 8512d496105SMichael Roth .value.s16 = INT16_MAX / 2 + 1, 8522d496105SMichael Roth }, 8532d496105SMichael Roth { 8542d496105SMichael Roth .description = "int16_min", 8552d496105SMichael Roth .type = PTYPE_S16, 8562d496105SMichael Roth .value.s16 = INT16_MIN, 8572d496105SMichael Roth }, 8582d496105SMichael Roth { 8592d496105SMichael Roth .description = "int16_max", 8602d496105SMichael Roth .type = PTYPE_S16, 8612d496105SMichael Roth .value.s16 = INT16_MAX, 8622d496105SMichael Roth }, 8632d496105SMichael Roth /* int32 tests */ 8642d496105SMichael Roth { 8652d496105SMichael Roth .description = "int32_sanity1", 8662d496105SMichael Roth .type = PTYPE_S32, 8672d496105SMichael Roth .value.s32 = -1, 8682d496105SMichael Roth }, 8692d496105SMichael Roth { 8702d496105SMichael Roth .description = "int32_sanity2", 8712d496105SMichael Roth .type = PTYPE_S32, 8722d496105SMichael Roth .value.s32 = INT32_MAX / 2 + 1, 8732d496105SMichael Roth }, 8742d496105SMichael Roth { 8752d496105SMichael Roth .description = "int32_min", 8762d496105SMichael Roth .type = PTYPE_S32, 8772d496105SMichael Roth .value.s32 = INT32_MIN, 8782d496105SMichael Roth }, 8792d496105SMichael Roth { 8802d496105SMichael Roth .description = "int32_max", 8812d496105SMichael Roth .type = PTYPE_S32, 8822d496105SMichael Roth .value.s32 = INT32_MAX, 8832d496105SMichael Roth }, 8842d496105SMichael Roth /* int64 tests */ 8852d496105SMichael Roth { 8862d496105SMichael Roth .description = "int64_sanity1", 8872d496105SMichael Roth .type = PTYPE_S64, 8882d496105SMichael Roth .value.s64 = -1, 8892d496105SMichael Roth }, 8902d496105SMichael Roth { 8912d496105SMichael Roth .description = "int64_sanity2", 8922d496105SMichael Roth .type = PTYPE_S64, 8932d496105SMichael Roth .value.s64 = INT64_MAX / 2 + 1, 8942d496105SMichael Roth }, 8952d496105SMichael Roth { 8962d496105SMichael Roth .description = "int64_min", 8972d496105SMichael Roth .type = PTYPE_S64, 8982d496105SMichael Roth .value.s64 = INT64_MIN, 8992d496105SMichael Roth }, 9002d496105SMichael Roth { 9012d496105SMichael Roth .description = "int64_max", 9022d496105SMichael Roth .type = PTYPE_S64, 9032d496105SMichael Roth .value.s64 = INT64_MAX, 9042d496105SMichael Roth }, 9052d496105SMichael Roth { .type = PTYPE_EOL } 9062d496105SMichael Roth }; 9072d496105SMichael Roth 9082d496105SMichael Roth /* visitor-specific op implementations */ 9092d496105SMichael Roth 9102d496105SMichael Roth typedef struct QmpSerializeData { 9113b098d56SEric Blake Visitor *qov; 9123b098d56SEric Blake QObject *obj; 913b70ce101SEric Blake Visitor *qiv; 9142d496105SMichael Roth } QmpSerializeData; 9152d496105SMichael Roth 9162d496105SMichael Roth static void qmp_serialize(void *native_in, void **datap, 9172d496105SMichael Roth VisitorFunc visit, Error **errp) 9182d496105SMichael Roth { 9192d496105SMichael Roth QmpSerializeData *d = g_malloc0(sizeof(*d)); 9202d496105SMichael Roth 9217d5e199aSDaniel P. Berrange d->qov = qobject_output_visitor_new(&d->obj); 9223b098d56SEric Blake visit(d->qov, &native_in, errp); 9232d496105SMichael Roth *datap = d; 9242d496105SMichael Roth } 9252d496105SMichael Roth 9262d496105SMichael Roth static void qmp_deserialize(void **native_out, void *datap, 9272d496105SMichael Roth VisitorFunc visit, Error **errp) 9282d496105SMichael Roth { 9292d496105SMichael Roth QmpSerializeData *d = datap; 930ad7f375dSMichael Roth QString *output_json; 931ad7f375dSMichael Roth QObject *obj_orig, *obj; 932ad7f375dSMichael Roth 9333b098d56SEric Blake visit_complete(d->qov, &d->obj); 9343b098d56SEric Blake obj_orig = d->obj; 935ad7f375dSMichael Roth output_json = qobject_to_json(obj_orig); 93602146d27SMarkus Armbruster obj = qobject_from_json(qstring_get_str(output_json), &error_abort); 9372d496105SMichael Roth 938cb3e7f08SMarc-André Lureau qobject_unref(output_json); 939048abb7bSMarkus Armbruster d->qiv = qobject_input_visitor_new(obj); 940cb3e7f08SMarc-André Lureau qobject_unref(obj_orig); 941cb3e7f08SMarc-André Lureau qobject_unref(obj); 942b70ce101SEric Blake visit(d->qiv, native_out, errp); 9432d496105SMichael Roth } 9442d496105SMichael Roth 9452d496105SMichael Roth static void qmp_cleanup(void *datap) 9462d496105SMichael Roth { 9472d496105SMichael Roth QmpSerializeData *d = datap; 9483b098d56SEric Blake visit_free(d->qov); 949b70ce101SEric Blake visit_free(d->qiv); 9502bd01ac1SStefan Berger 9512bd01ac1SStefan Berger g_free(d); 9522d496105SMichael Roth } 9532d496105SMichael Roth 9540d30b0a2SMichael Roth typedef struct StringSerializeData { 9552bd01ac1SStefan Berger char *string; 9563b098d56SEric Blake Visitor *sov; 9577a0525c7SEric Blake Visitor *siv; 9580d30b0a2SMichael Roth } StringSerializeData; 9590d30b0a2SMichael Roth 9600d30b0a2SMichael Roth static void string_serialize(void *native_in, void **datap, 9610d30b0a2SMichael Roth VisitorFunc visit, Error **errp) 9620d30b0a2SMichael Roth { 9630d30b0a2SMichael Roth StringSerializeData *d = g_malloc0(sizeof(*d)); 9640d30b0a2SMichael Roth 9653b098d56SEric Blake d->sov = string_output_visitor_new(false, &d->string); 9663b098d56SEric Blake visit(d->sov, &native_in, errp); 9670d30b0a2SMichael Roth *datap = d; 9680d30b0a2SMichael Roth } 9690d30b0a2SMichael Roth 9700d30b0a2SMichael Roth static void string_deserialize(void **native_out, void *datap, 9710d30b0a2SMichael Roth VisitorFunc visit, Error **errp) 9720d30b0a2SMichael Roth { 9730d30b0a2SMichael Roth StringSerializeData *d = datap; 9740d30b0a2SMichael Roth 9753b098d56SEric Blake visit_complete(d->sov, &d->string); 9762bd01ac1SStefan Berger d->siv = string_input_visitor_new(d->string); 9777a0525c7SEric Blake visit(d->siv, native_out, errp); 9780d30b0a2SMichael Roth } 9790d30b0a2SMichael Roth 9800d30b0a2SMichael Roth static void string_cleanup(void *datap) 9810d30b0a2SMichael Roth { 9820d30b0a2SMichael Roth StringSerializeData *d = datap; 9832bd01ac1SStefan Berger 9843b098d56SEric Blake visit_free(d->sov); 9857a0525c7SEric Blake visit_free(d->siv); 9862bd01ac1SStefan Berger g_free(d->string); 9872bd01ac1SStefan Berger g_free(d); 9880d30b0a2SMichael Roth } 9890d30b0a2SMichael Roth 9902d496105SMichael Roth /* visitor registration, test harness */ 9912d496105SMichael Roth 9922d496105SMichael Roth /* note: to function interchangeably as a serialization mechanism your 9932d496105SMichael Roth * visitor test implementation should pass the test cases for all visitor 9942d496105SMichael Roth * capabilities: primitives, structures, and lists 9952d496105SMichael Roth */ 9962d496105SMichael Roth static const SerializeOps visitors[] = { 9972d496105SMichael Roth { 9982d496105SMichael Roth .type = "QMP", 9992d496105SMichael Roth .serialize = qmp_serialize, 10002d496105SMichael Roth .deserialize = qmp_deserialize, 10012d496105SMichael Roth .cleanup = qmp_cleanup, 10028addacddSMichael Roth .caps = VCAP_PRIMITIVES | VCAP_STRUCTURES | VCAP_LISTS | 10038addacddSMichael Roth VCAP_PRIMITIVE_LISTS 10042d496105SMichael Roth }, 10050d30b0a2SMichael Roth { 10060d30b0a2SMichael Roth .type = "String", 10070d30b0a2SMichael Roth .serialize = string_serialize, 10080d30b0a2SMichael Roth .deserialize = string_deserialize, 10090d30b0a2SMichael Roth .cleanup = string_cleanup, 10100d30b0a2SMichael Roth .caps = VCAP_PRIMITIVES 10110d30b0a2SMichael Roth }, 10122d496105SMichael Roth { NULL } 10132d496105SMichael Roth }; 10142d496105SMichael Roth 10152d496105SMichael Roth static void add_visitor_type(const SerializeOps *ops) 10162d496105SMichael Roth { 1017fdf235baSEric Blake char testname_prefix[32]; 10182d496105SMichael Roth char testname[128]; 10192d496105SMichael Roth TestArgs *args; 10202d496105SMichael Roth int i = 0; 10212d496105SMichael Roth 10222d496105SMichael Roth sprintf(testname_prefix, "/visitor/serialization/%s", ops->type); 10232d496105SMichael Roth 10242d496105SMichael Roth if (ops->caps & VCAP_PRIMITIVES) { 10252d496105SMichael Roth while (pt_values[i].type != PTYPE_EOL) { 10262d496105SMichael Roth sprintf(testname, "%s/primitives/%s", testname_prefix, 10272d496105SMichael Roth pt_values[i].description); 10282d496105SMichael Roth args = g_malloc0(sizeof(*args)); 10292d496105SMichael Roth args->ops = ops; 10302d496105SMichael Roth args->test_data = &pt_values[i]; 10312d496105SMichael Roth g_test_add_data_func(testname, args, test_primitives); 10322d496105SMichael Roth i++; 10332d496105SMichael Roth } 10342d496105SMichael Roth } 10352d496105SMichael Roth 10362d496105SMichael Roth if (ops->caps & VCAP_STRUCTURES) { 10372d496105SMichael Roth sprintf(testname, "%s/struct", testname_prefix); 10382d496105SMichael Roth args = g_malloc0(sizeof(*args)); 10392d496105SMichael Roth args->ops = ops; 10402d496105SMichael Roth args->test_data = NULL; 10412d496105SMichael Roth g_test_add_data_func(testname, args, test_struct); 10422d496105SMichael Roth 10432d496105SMichael Roth sprintf(testname, "%s/nested_struct", testname_prefix); 10442d496105SMichael Roth args = g_malloc0(sizeof(*args)); 10452d496105SMichael Roth args->ops = ops; 10462d496105SMichael Roth args->test_data = NULL; 10472d496105SMichael Roth g_test_add_data_func(testname, args, test_nested_struct); 10482d496105SMichael Roth } 10492d496105SMichael Roth 10502d496105SMichael Roth if (ops->caps & VCAP_LISTS) { 10512d496105SMichael Roth sprintf(testname, "%s/nested_struct_list", testname_prefix); 10522d496105SMichael Roth args = g_malloc0(sizeof(*args)); 10532d496105SMichael Roth args->ops = ops; 10542d496105SMichael Roth args->test_data = NULL; 10552d496105SMichael Roth g_test_add_data_func(testname, args, test_nested_struct_list); 10562d496105SMichael Roth } 10578addacddSMichael Roth 10588addacddSMichael Roth if (ops->caps & VCAP_PRIMITIVE_LISTS) { 10598addacddSMichael Roth i = 0; 10608addacddSMichael Roth while (pt_values[i].type != PTYPE_EOL) { 10618addacddSMichael Roth sprintf(testname, "%s/primitive_list/%s", testname_prefix, 10628addacddSMichael Roth pt_values[i].description); 10638addacddSMichael Roth args = g_malloc0(sizeof(*args)); 10648addacddSMichael Roth args->ops = ops; 10658addacddSMichael Roth args->test_data = &pt_values[i]; 10668addacddSMichael Roth g_test_add_data_func(testname, args, test_primitive_lists); 10678addacddSMichael Roth i++; 10688addacddSMichael Roth } 10698addacddSMichael Roth } 10702d496105SMichael Roth } 10712d496105SMichael Roth 10722d496105SMichael Roth int main(int argc, char **argv) 10732d496105SMichael Roth { 10742d496105SMichael Roth int i = 0; 10752d496105SMichael Roth 10762d496105SMichael Roth g_test_init(&argc, &argv, NULL); 10772d496105SMichael Roth 10782d496105SMichael Roth while (visitors[i].type != NULL) { 10792d496105SMichael Roth add_visitor_type(&visitors[i]); 10802d496105SMichael Roth i++; 10812d496105SMichael Roth } 10822d496105SMichael Roth 10832d496105SMichael Roth g_test_run(); 10842d496105SMichael Roth 10852d496105SMichael Roth return 0; 10862d496105SMichael Roth } 1087