1da668aa1SThomas Huth /* 2da668aa1SThomas Huth * QObject Output Visitor unit-tests. 3da668aa1SThomas Huth * 4da668aa1SThomas Huth * Copyright (C) 2011-2016 Red Hat Inc. 5da668aa1SThomas Huth * 6da668aa1SThomas Huth * Authors: 7da668aa1SThomas Huth * Luiz Capitulino <lcapitulino@redhat.com> 8da668aa1SThomas Huth * 9da668aa1SThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or later. 10da668aa1SThomas Huth * See the COPYING file in the top-level directory. 11da668aa1SThomas Huth */ 12da668aa1SThomas Huth 13da668aa1SThomas Huth #include "qemu/osdep.h" 14da668aa1SThomas Huth 15da668aa1SThomas Huth #include "qapi/error.h" 16da668aa1SThomas Huth #include "qapi/qobject-output-visitor.h" 17da668aa1SThomas Huth #include "test-qapi-visit.h" 18da668aa1SThomas Huth #include "qapi/qmp/qbool.h" 19da668aa1SThomas Huth #include "qapi/qmp/qdict.h" 20da668aa1SThomas Huth #include "qapi/qmp/qlist.h" 21da668aa1SThomas Huth #include "qapi/qmp/qnull.h" 22da668aa1SThomas Huth #include "qapi/qmp/qnum.h" 23da668aa1SThomas Huth #include "qapi/qmp/qstring.h" 24da668aa1SThomas Huth 25da668aa1SThomas Huth typedef struct TestOutputVisitorData { 26da668aa1SThomas Huth Visitor *ov; 27da668aa1SThomas Huth QObject *obj; 28da668aa1SThomas Huth } TestOutputVisitorData; 29da668aa1SThomas Huth 30da668aa1SThomas Huth static void visitor_output_setup(TestOutputVisitorData *data, 31da668aa1SThomas Huth const void *unused) 32da668aa1SThomas Huth { 33da668aa1SThomas Huth data->ov = qobject_output_visitor_new(&data->obj); 34da668aa1SThomas Huth g_assert(data->ov); 35da668aa1SThomas Huth } 36da668aa1SThomas Huth 37da668aa1SThomas Huth static void visitor_output_teardown(TestOutputVisitorData *data, 38da668aa1SThomas Huth const void *unused) 39da668aa1SThomas Huth { 40da668aa1SThomas Huth visit_free(data->ov); 41da668aa1SThomas Huth data->ov = NULL; 42da668aa1SThomas Huth qobject_unref(data->obj); 43da668aa1SThomas Huth data->obj = NULL; 44da668aa1SThomas Huth } 45da668aa1SThomas Huth 46da668aa1SThomas Huth static QObject *visitor_get(TestOutputVisitorData *data) 47da668aa1SThomas Huth { 48da668aa1SThomas Huth visit_complete(data->ov, &data->obj); 49da668aa1SThomas Huth g_assert(data->obj); 50da668aa1SThomas Huth return data->obj; 51da668aa1SThomas Huth } 52da668aa1SThomas Huth 53da668aa1SThomas Huth static void visitor_reset(TestOutputVisitorData *data) 54da668aa1SThomas Huth { 55da668aa1SThomas Huth visitor_output_teardown(data, NULL); 56da668aa1SThomas Huth visitor_output_setup(data, NULL); 57da668aa1SThomas Huth } 58da668aa1SThomas Huth 59da668aa1SThomas Huth static void test_visitor_out_int(TestOutputVisitorData *data, 60da668aa1SThomas Huth const void *unused) 61da668aa1SThomas Huth { 62da668aa1SThomas Huth int64_t value = -42; 63da668aa1SThomas Huth int64_t val; 64da668aa1SThomas Huth QNum *qnum; 65da668aa1SThomas Huth 66da668aa1SThomas Huth visit_type_int(data->ov, NULL, &value, &error_abort); 67da668aa1SThomas Huth 68da668aa1SThomas Huth qnum = qobject_to(QNum, visitor_get(data)); 69da668aa1SThomas Huth g_assert(qnum); 70da668aa1SThomas Huth g_assert(qnum_get_try_int(qnum, &val)); 71da668aa1SThomas Huth g_assert_cmpint(val, ==, value); 72da668aa1SThomas Huth } 73da668aa1SThomas Huth 74da668aa1SThomas Huth static void test_visitor_out_bool(TestOutputVisitorData *data, 75da668aa1SThomas Huth const void *unused) 76da668aa1SThomas Huth { 77da668aa1SThomas Huth bool value = true; 78da668aa1SThomas Huth QBool *qbool; 79da668aa1SThomas Huth 80da668aa1SThomas Huth visit_type_bool(data->ov, NULL, &value, &error_abort); 81da668aa1SThomas Huth 82da668aa1SThomas Huth qbool = qobject_to(QBool, visitor_get(data)); 83da668aa1SThomas Huth g_assert(qbool); 84da668aa1SThomas Huth g_assert(qbool_get_bool(qbool) == value); 85da668aa1SThomas Huth } 86da668aa1SThomas Huth 87da668aa1SThomas Huth static void test_visitor_out_number(TestOutputVisitorData *data, 88da668aa1SThomas Huth const void *unused) 89da668aa1SThomas Huth { 90da668aa1SThomas Huth double value = 3.14; 91da668aa1SThomas Huth QNum *qnum; 92da668aa1SThomas Huth 93da668aa1SThomas Huth visit_type_number(data->ov, NULL, &value, &error_abort); 94da668aa1SThomas Huth 95da668aa1SThomas Huth qnum = qobject_to(QNum, visitor_get(data)); 96da668aa1SThomas Huth g_assert(qnum); 97da668aa1SThomas Huth g_assert(qnum_get_double(qnum) == value); 98da668aa1SThomas Huth } 99da668aa1SThomas Huth 100da668aa1SThomas Huth static void test_visitor_out_string(TestOutputVisitorData *data, 101da668aa1SThomas Huth const void *unused) 102da668aa1SThomas Huth { 103da668aa1SThomas Huth char *string = (char *) "Q E M U"; 104da668aa1SThomas Huth QString *qstr; 105da668aa1SThomas Huth 106da668aa1SThomas Huth visit_type_str(data->ov, NULL, &string, &error_abort); 107da668aa1SThomas Huth 108da668aa1SThomas Huth qstr = qobject_to(QString, visitor_get(data)); 109da668aa1SThomas Huth g_assert(qstr); 110da668aa1SThomas Huth g_assert_cmpstr(qstring_get_str(qstr), ==, string); 111da668aa1SThomas Huth } 112da668aa1SThomas Huth 113da668aa1SThomas Huth static void test_visitor_out_no_string(TestOutputVisitorData *data, 114da668aa1SThomas Huth const void *unused) 115da668aa1SThomas Huth { 116da668aa1SThomas Huth char *string = NULL; 117da668aa1SThomas Huth QString *qstr; 118da668aa1SThomas Huth 119da668aa1SThomas Huth /* A null string should return "" */ 120da668aa1SThomas Huth visit_type_str(data->ov, NULL, &string, &error_abort); 121da668aa1SThomas Huth 122da668aa1SThomas Huth qstr = qobject_to(QString, visitor_get(data)); 123da668aa1SThomas Huth g_assert(qstr); 124da668aa1SThomas Huth g_assert_cmpstr(qstring_get_str(qstr), ==, ""); 125da668aa1SThomas Huth } 126da668aa1SThomas Huth 127da668aa1SThomas Huth static void test_visitor_out_enum(TestOutputVisitorData *data, 128da668aa1SThomas Huth const void *unused) 129da668aa1SThomas Huth { 130da668aa1SThomas Huth EnumOne i; 131da668aa1SThomas Huth QString *qstr; 132da668aa1SThomas Huth 133da668aa1SThomas Huth for (i = 0; i < ENUM_ONE__MAX; i++) { 134da668aa1SThomas Huth visit_type_EnumOne(data->ov, "unused", &i, &error_abort); 135da668aa1SThomas Huth 136da668aa1SThomas Huth qstr = qobject_to(QString, visitor_get(data)); 137da668aa1SThomas Huth g_assert(qstr); 138da668aa1SThomas Huth g_assert_cmpstr(qstring_get_str(qstr), ==, EnumOne_str(i)); 139da668aa1SThomas Huth visitor_reset(data); 140da668aa1SThomas Huth } 141da668aa1SThomas Huth } 142da668aa1SThomas Huth 143da668aa1SThomas Huth static void test_visitor_out_struct(TestOutputVisitorData *data, 144da668aa1SThomas Huth const void *unused) 145da668aa1SThomas Huth { 146da668aa1SThomas Huth TestStruct test_struct = { .integer = 42, 147da668aa1SThomas Huth .boolean = false, 148da668aa1SThomas Huth .string = (char *) "foo"}; 149da668aa1SThomas Huth TestStruct *p = &test_struct; 150da668aa1SThomas Huth QDict *qdict; 151da668aa1SThomas Huth 152da668aa1SThomas Huth visit_type_TestStruct(data->ov, NULL, &p, &error_abort); 153da668aa1SThomas Huth 154da668aa1SThomas Huth qdict = qobject_to(QDict, visitor_get(data)); 155da668aa1SThomas Huth g_assert(qdict); 156da668aa1SThomas Huth g_assert_cmpint(qdict_size(qdict), ==, 3); 157da668aa1SThomas Huth g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42); 158da668aa1SThomas Huth g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, false); 159da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo"); 160da668aa1SThomas Huth } 161da668aa1SThomas Huth 162da668aa1SThomas Huth static void test_visitor_out_struct_nested(TestOutputVisitorData *data, 163da668aa1SThomas Huth const void *unused) 164da668aa1SThomas Huth { 165da668aa1SThomas Huth int64_t value = 42; 166da668aa1SThomas Huth UserDefTwo *ud2; 167da668aa1SThomas Huth QDict *qdict, *dict1, *dict2, *dict3, *userdef; 168da668aa1SThomas Huth const char *string = "user def string"; 169da668aa1SThomas Huth const char *strings[] = { "forty two", "forty three", "forty four", 170da668aa1SThomas Huth "forty five" }; 171da668aa1SThomas Huth 172da668aa1SThomas Huth ud2 = g_malloc0(sizeof(*ud2)); 173da668aa1SThomas Huth ud2->string0 = g_strdup(strings[0]); 174da668aa1SThomas Huth 175da668aa1SThomas Huth ud2->dict1 = g_malloc0(sizeof(*ud2->dict1)); 176da668aa1SThomas Huth ud2->dict1->string1 = g_strdup(strings[1]); 177da668aa1SThomas Huth 178da668aa1SThomas Huth ud2->dict1->dict2 = g_malloc0(sizeof(*ud2->dict1->dict2)); 179da668aa1SThomas Huth ud2->dict1->dict2->userdef = g_new0(UserDefOne, 1); 180da668aa1SThomas Huth ud2->dict1->dict2->userdef->string = g_strdup(string); 181da668aa1SThomas Huth ud2->dict1->dict2->userdef->integer = value; 182da668aa1SThomas Huth ud2->dict1->dict2->string = g_strdup(strings[2]); 183da668aa1SThomas Huth 184da668aa1SThomas Huth ud2->dict1->dict3 = g_malloc0(sizeof(*ud2->dict1->dict3)); 185da668aa1SThomas Huth ud2->dict1->dict3->userdef = g_new0(UserDefOne, 1); 186da668aa1SThomas Huth ud2->dict1->dict3->userdef->string = g_strdup(string); 187da668aa1SThomas Huth ud2->dict1->dict3->userdef->integer = value; 188da668aa1SThomas Huth ud2->dict1->dict3->string = g_strdup(strings[3]); 189da668aa1SThomas Huth 190da668aa1SThomas Huth visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort); 191da668aa1SThomas Huth 192da668aa1SThomas Huth qdict = qobject_to(QDict, visitor_get(data)); 193da668aa1SThomas Huth g_assert(qdict); 194da668aa1SThomas Huth g_assert_cmpint(qdict_size(qdict), ==, 2); 195da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]); 196da668aa1SThomas Huth 197da668aa1SThomas Huth dict1 = qdict_get_qdict(qdict, "dict1"); 198da668aa1SThomas Huth g_assert_cmpint(qdict_size(dict1), ==, 3); 199da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]); 200da668aa1SThomas Huth 201da668aa1SThomas Huth dict2 = qdict_get_qdict(dict1, "dict2"); 202da668aa1SThomas Huth g_assert_cmpint(qdict_size(dict2), ==, 2); 203da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(dict2, "string"), ==, strings[2]); 204da668aa1SThomas Huth userdef = qdict_get_qdict(dict2, "userdef"); 205da668aa1SThomas Huth g_assert_cmpint(qdict_size(userdef), ==, 2); 206da668aa1SThomas Huth g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value); 207da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string); 208da668aa1SThomas Huth 209da668aa1SThomas Huth dict3 = qdict_get_qdict(dict1, "dict3"); 210da668aa1SThomas Huth g_assert_cmpint(qdict_size(dict3), ==, 2); 211da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(dict3, "string"), ==, strings[3]); 212da668aa1SThomas Huth userdef = qdict_get_qdict(dict3, "userdef"); 213da668aa1SThomas Huth g_assert_cmpint(qdict_size(userdef), ==, 2); 214da668aa1SThomas Huth g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value); 215da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string); 216da668aa1SThomas Huth 217da668aa1SThomas Huth qapi_free_UserDefTwo(ud2); 218da668aa1SThomas Huth } 219da668aa1SThomas Huth 220da668aa1SThomas Huth static void test_visitor_out_list(TestOutputVisitorData *data, 221da668aa1SThomas Huth const void *unused) 222da668aa1SThomas Huth { 223da668aa1SThomas Huth const char *value_str = "list value"; 224da668aa1SThomas Huth TestStruct *value; 225da668aa1SThomas Huth TestStructList *head = NULL; 226da668aa1SThomas Huth const int max_items = 10; 227da668aa1SThomas Huth bool value_bool = true; 228da668aa1SThomas Huth int value_int = 10; 229da668aa1SThomas Huth QListEntry *entry; 230da668aa1SThomas Huth QList *qlist; 231da668aa1SThomas Huth int i; 232da668aa1SThomas Huth 233da668aa1SThomas Huth /* Build the list in reverse order... */ 234da668aa1SThomas Huth for (i = 0; i < max_items; i++) { 235da668aa1SThomas Huth value = g_malloc0(sizeof(*value)); 236da668aa1SThomas Huth value->integer = value_int + (max_items - i - 1); 237da668aa1SThomas Huth value->boolean = value_bool; 238da668aa1SThomas Huth value->string = g_strdup(value_str); 239da668aa1SThomas Huth 240da668aa1SThomas Huth QAPI_LIST_PREPEND(head, value); 241da668aa1SThomas Huth } 242da668aa1SThomas Huth 243da668aa1SThomas Huth visit_type_TestStructList(data->ov, NULL, &head, &error_abort); 244da668aa1SThomas Huth 245da668aa1SThomas Huth qlist = qobject_to(QList, visitor_get(data)); 246da668aa1SThomas Huth g_assert(qlist); 247da668aa1SThomas Huth g_assert(!qlist_empty(qlist)); 248da668aa1SThomas Huth 249da668aa1SThomas Huth /* ...and ensure that the visitor sees it in order */ 250da668aa1SThomas Huth i = 0; 251da668aa1SThomas Huth QLIST_FOREACH_ENTRY(qlist, entry) { 252da668aa1SThomas Huth QDict *qdict; 253da668aa1SThomas Huth 254da668aa1SThomas Huth qdict = qobject_to(QDict, entry->value); 255da668aa1SThomas Huth g_assert(qdict); 256da668aa1SThomas Huth g_assert_cmpint(qdict_size(qdict), ==, 3); 257da668aa1SThomas Huth g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int + i); 258da668aa1SThomas Huth g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool); 259da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str); 260da668aa1SThomas Huth i++; 261da668aa1SThomas Huth } 262da668aa1SThomas Huth g_assert_cmpint(i, ==, max_items); 263da668aa1SThomas Huth 264da668aa1SThomas Huth qapi_free_TestStructList(head); 265da668aa1SThomas Huth } 266da668aa1SThomas Huth 267da668aa1SThomas Huth static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data, 268da668aa1SThomas Huth const void *unused) 269da668aa1SThomas Huth { 270da668aa1SThomas Huth UserDefTwo *value; 271da668aa1SThomas Huth UserDefTwoList *head = NULL; 272da668aa1SThomas Huth const char string[] = "foo bar"; 273da668aa1SThomas Huth int i, max_count = 1024; 274da668aa1SThomas Huth 275da668aa1SThomas Huth for (i = 0; i < max_count; i++) { 276da668aa1SThomas Huth value = g_malloc0(sizeof(*value)); 277da668aa1SThomas Huth 278da668aa1SThomas Huth value->string0 = g_strdup(string); 279da668aa1SThomas Huth value->dict1 = g_new0(UserDefTwoDict, 1); 280da668aa1SThomas Huth value->dict1->string1 = g_strdup(string); 281da668aa1SThomas Huth value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1); 282da668aa1SThomas Huth value->dict1->dict2->userdef = g_new0(UserDefOne, 1); 283da668aa1SThomas Huth value->dict1->dict2->userdef->string = g_strdup(string); 284da668aa1SThomas Huth value->dict1->dict2->userdef->integer = 42; 285da668aa1SThomas Huth value->dict1->dict2->string = g_strdup(string); 286da668aa1SThomas Huth 287da668aa1SThomas Huth QAPI_LIST_PREPEND(head, value); 288da668aa1SThomas Huth } 289da668aa1SThomas Huth 290da668aa1SThomas Huth qapi_free_UserDefTwoList(head); 291da668aa1SThomas Huth } 292da668aa1SThomas Huth 293da668aa1SThomas Huth static void test_visitor_out_any(TestOutputVisitorData *data, 294da668aa1SThomas Huth const void *unused) 295da668aa1SThomas Huth { 296da668aa1SThomas Huth QObject *qobj; 297da668aa1SThomas Huth QNum *qnum; 298da668aa1SThomas Huth QBool *qbool; 299da668aa1SThomas Huth QString *qstring; 300da668aa1SThomas Huth QDict *qdict; 301da668aa1SThomas Huth int64_t val; 302da668aa1SThomas Huth 303da668aa1SThomas Huth qobj = QOBJECT(qnum_from_int(-42)); 304da668aa1SThomas Huth visit_type_any(data->ov, NULL, &qobj, &error_abort); 305da668aa1SThomas Huth qnum = qobject_to(QNum, visitor_get(data)); 306da668aa1SThomas Huth g_assert(qnum); 307da668aa1SThomas Huth g_assert(qnum_get_try_int(qnum, &val)); 308da668aa1SThomas Huth g_assert_cmpint(val, ==, -42); 309da668aa1SThomas Huth qobject_unref(qobj); 310da668aa1SThomas Huth 311da668aa1SThomas Huth visitor_reset(data); 312da668aa1SThomas Huth qdict = qdict_new(); 313da668aa1SThomas Huth qdict_put_int(qdict, "integer", -42); 314da668aa1SThomas Huth qdict_put_bool(qdict, "boolean", true); 315da668aa1SThomas Huth qdict_put_str(qdict, "string", "foo"); 316da668aa1SThomas Huth qobj = QOBJECT(qdict); 317da668aa1SThomas Huth visit_type_any(data->ov, NULL, &qobj, &error_abort); 318da668aa1SThomas Huth qobject_unref(qobj); 319da668aa1SThomas Huth qdict = qobject_to(QDict, visitor_get(data)); 320da668aa1SThomas Huth g_assert(qdict); 321da668aa1SThomas Huth qnum = qobject_to(QNum, qdict_get(qdict, "integer")); 322da668aa1SThomas Huth g_assert(qnum); 323da668aa1SThomas Huth g_assert(qnum_get_try_int(qnum, &val)); 324da668aa1SThomas Huth g_assert_cmpint(val, ==, -42); 325da668aa1SThomas Huth qbool = qobject_to(QBool, qdict_get(qdict, "boolean")); 326da668aa1SThomas Huth g_assert(qbool); 327da668aa1SThomas Huth g_assert(qbool_get_bool(qbool) == true); 328da668aa1SThomas Huth qstring = qobject_to(QString, qdict_get(qdict, "string")); 329da668aa1SThomas Huth g_assert(qstring); 330da668aa1SThomas Huth g_assert_cmpstr(qstring_get_str(qstring), ==, "foo"); 331da668aa1SThomas Huth } 332da668aa1SThomas Huth 333da668aa1SThomas Huth static void test_visitor_out_union_flat(TestOutputVisitorData *data, 334da668aa1SThomas Huth const void *unused) 335da668aa1SThomas Huth { 336da668aa1SThomas Huth QDict *qdict; 337da668aa1SThomas Huth 338b21e2380SMarkus Armbruster UserDefFlatUnion *tmp = g_new0(UserDefFlatUnion, 1); 339da668aa1SThomas Huth tmp->enum1 = ENUM_ONE_VALUE1; 340da668aa1SThomas Huth tmp->string = g_strdup("str"); 341da668aa1SThomas Huth tmp->integer = 41; 342da668aa1SThomas Huth tmp->u.value1.boolean = true; 343da668aa1SThomas Huth 344da668aa1SThomas Huth visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort); 345da668aa1SThomas Huth qdict = qobject_to(QDict, visitor_get(data)); 346da668aa1SThomas Huth g_assert(qdict); 347da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1"); 348da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str"); 349da668aa1SThomas Huth g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41); 350da668aa1SThomas Huth g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true); 351da668aa1SThomas Huth 352da668aa1SThomas Huth qapi_free_UserDefFlatUnion(tmp); 353da668aa1SThomas Huth } 354da668aa1SThomas Huth 355*a17dbc4bSDaniel P. Berrangé static void test_visitor_out_union_in_union(TestOutputVisitorData *data, 356*a17dbc4bSDaniel P. Berrangé const void *unused) 357*a17dbc4bSDaniel P. Berrangé { 358*a17dbc4bSDaniel P. Berrangé QDict *qdict; 359*a17dbc4bSDaniel P. Berrangé 360*a17dbc4bSDaniel P. Berrangé TestUnionInUnion *tmp = g_new0(TestUnionInUnion, 1); 361*a17dbc4bSDaniel P. Berrangé tmp->type = TEST_UNION_ENUM_VALUE_A; 362*a17dbc4bSDaniel P. Berrangé tmp->u.value_a.type_a = TEST_UNION_ENUMA_VALUE_A1; 363*a17dbc4bSDaniel P. Berrangé tmp->u.value_a.u.value_a1.integer = 42; 364*a17dbc4bSDaniel P. Berrangé tmp->u.value_a.u.value_a1.name = g_strdup("fish"); 365*a17dbc4bSDaniel P. Berrangé 366*a17dbc4bSDaniel P. Berrangé visit_type_TestUnionInUnion(data->ov, NULL, &tmp, &error_abort); 367*a17dbc4bSDaniel P. Berrangé qdict = qobject_to(QDict, visitor_get(data)); 368*a17dbc4bSDaniel P. Berrangé g_assert(qdict); 369*a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "value-a"); 370*a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type-a"), ==, "value-a1"); 371*a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42); 372*a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "name"), ==, "fish"); 373*a17dbc4bSDaniel P. Berrangé 374*a17dbc4bSDaniel P. Berrangé qapi_free_TestUnionInUnion(tmp); 375*a17dbc4bSDaniel P. Berrangé 376*a17dbc4bSDaniel P. Berrangé 377*a17dbc4bSDaniel P. Berrangé visitor_reset(data); 378*a17dbc4bSDaniel P. Berrangé tmp = g_new0(TestUnionInUnion, 1); 379*a17dbc4bSDaniel P. Berrangé tmp->type = TEST_UNION_ENUM_VALUE_A; 380*a17dbc4bSDaniel P. Berrangé tmp->u.value_a.type_a = TEST_UNION_ENUMA_VALUE_A2; 381*a17dbc4bSDaniel P. Berrangé tmp->u.value_a.u.value_a2.integer = 1729; 382*a17dbc4bSDaniel P. Berrangé tmp->u.value_a.u.value_a2.size = 87539319; 383*a17dbc4bSDaniel P. Berrangé 384*a17dbc4bSDaniel P. Berrangé visit_type_TestUnionInUnion(data->ov, NULL, &tmp, &error_abort); 385*a17dbc4bSDaniel P. Berrangé qdict = qobject_to(QDict, visitor_get(data)); 386*a17dbc4bSDaniel P. Berrangé g_assert(qdict); 387*a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "value-a"); 388*a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type-a"), ==, "value-a2"); 389*a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1729); 390*a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_int(qdict, "size"), ==, 87539319); 391*a17dbc4bSDaniel P. Berrangé 392*a17dbc4bSDaniel P. Berrangé qapi_free_TestUnionInUnion(tmp); 393*a17dbc4bSDaniel P. Berrangé 394*a17dbc4bSDaniel P. Berrangé 395*a17dbc4bSDaniel P. Berrangé visitor_reset(data); 396*a17dbc4bSDaniel P. Berrangé tmp = g_new0(TestUnionInUnion, 1); 397*a17dbc4bSDaniel P. Berrangé tmp->type = TEST_UNION_ENUM_VALUE_B; 398*a17dbc4bSDaniel P. Berrangé tmp->u.value_b.integer = 1729; 399*a17dbc4bSDaniel P. Berrangé tmp->u.value_b.onoff = true; 400*a17dbc4bSDaniel P. Berrangé 401*a17dbc4bSDaniel P. Berrangé visit_type_TestUnionInUnion(data->ov, NULL, &tmp, &error_abort); 402*a17dbc4bSDaniel P. Berrangé qdict = qobject_to(QDict, visitor_get(data)); 403*a17dbc4bSDaniel P. Berrangé g_assert(qdict); 404*a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "value-b"); 405*a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1729); 406*a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_bool(qdict, "onoff"), ==, true); 407*a17dbc4bSDaniel P. Berrangé 408*a17dbc4bSDaniel P. Berrangé qapi_free_TestUnionInUnion(tmp); 409*a17dbc4bSDaniel P. Berrangé } 410*a17dbc4bSDaniel P. Berrangé 411da668aa1SThomas Huth static void test_visitor_out_alternate(TestOutputVisitorData *data, 412da668aa1SThomas Huth const void *unused) 413da668aa1SThomas Huth { 414da668aa1SThomas Huth UserDefAlternate *tmp; 415da668aa1SThomas Huth QNum *qnum; 416da668aa1SThomas Huth QString *qstr; 417da668aa1SThomas Huth QDict *qdict; 418da668aa1SThomas Huth int64_t val; 419da668aa1SThomas Huth 420da668aa1SThomas Huth tmp = g_new0(UserDefAlternate, 1); 421da668aa1SThomas Huth tmp->type = QTYPE_QNUM; 422da668aa1SThomas Huth tmp->u.i = 42; 423da668aa1SThomas Huth 424da668aa1SThomas Huth visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort); 425da668aa1SThomas Huth qnum = qobject_to(QNum, visitor_get(data)); 426da668aa1SThomas Huth g_assert(qnum); 427da668aa1SThomas Huth g_assert(qnum_get_try_int(qnum, &val)); 428da668aa1SThomas Huth g_assert_cmpint(val, ==, 42); 429da668aa1SThomas Huth 430da668aa1SThomas Huth qapi_free_UserDefAlternate(tmp); 431da668aa1SThomas Huth 432da668aa1SThomas Huth visitor_reset(data); 433da668aa1SThomas Huth tmp = g_new0(UserDefAlternate, 1); 434da668aa1SThomas Huth tmp->type = QTYPE_QSTRING; 435da668aa1SThomas Huth tmp->u.e = ENUM_ONE_VALUE1; 436da668aa1SThomas Huth 437da668aa1SThomas Huth visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort); 438da668aa1SThomas Huth qstr = qobject_to(QString, visitor_get(data)); 439da668aa1SThomas Huth g_assert(qstr); 440da668aa1SThomas Huth g_assert_cmpstr(qstring_get_str(qstr), ==, "value1"); 441da668aa1SThomas Huth 442da668aa1SThomas Huth qapi_free_UserDefAlternate(tmp); 443da668aa1SThomas Huth 444da668aa1SThomas Huth visitor_reset(data); 445da668aa1SThomas Huth tmp = g_new0(UserDefAlternate, 1); 446da668aa1SThomas Huth tmp->type = QTYPE_QNULL; 447da668aa1SThomas Huth tmp->u.n = qnull(); 448da668aa1SThomas Huth 449da668aa1SThomas Huth visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort); 450da668aa1SThomas Huth g_assert_cmpint(qobject_type(visitor_get(data)), ==, QTYPE_QNULL); 451da668aa1SThomas Huth 452da668aa1SThomas Huth qapi_free_UserDefAlternate(tmp); 453da668aa1SThomas Huth 454da668aa1SThomas Huth visitor_reset(data); 455da668aa1SThomas Huth tmp = g_new0(UserDefAlternate, 1); 456da668aa1SThomas Huth tmp->type = QTYPE_QDICT; 457da668aa1SThomas Huth tmp->u.udfu.integer = 1; 458da668aa1SThomas Huth tmp->u.udfu.string = g_strdup("str"); 459da668aa1SThomas Huth tmp->u.udfu.enum1 = ENUM_ONE_VALUE1; 460da668aa1SThomas Huth tmp->u.udfu.u.value1.boolean = true; 461da668aa1SThomas Huth 462da668aa1SThomas Huth visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort); 463da668aa1SThomas Huth qdict = qobject_to(QDict, visitor_get(data)); 464da668aa1SThomas Huth g_assert(qdict); 465da668aa1SThomas Huth g_assert_cmpint(qdict_size(qdict), ==, 4); 466da668aa1SThomas Huth g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1); 467da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str"); 468da668aa1SThomas Huth g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1"); 469da668aa1SThomas Huth g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true); 470da668aa1SThomas Huth 471da668aa1SThomas Huth qapi_free_UserDefAlternate(tmp); 472da668aa1SThomas Huth } 473da668aa1SThomas Huth 474da668aa1SThomas Huth static void test_visitor_out_null(TestOutputVisitorData *data, 475da668aa1SThomas Huth const void *unused) 476da668aa1SThomas Huth { 477da668aa1SThomas Huth QNull *null = NULL; 478da668aa1SThomas Huth QDict *qdict; 479da668aa1SThomas Huth QObject *nil; 480da668aa1SThomas Huth 481da668aa1SThomas Huth visit_start_struct(data->ov, NULL, NULL, 0, &error_abort); 482da668aa1SThomas Huth visit_type_null(data->ov, "a", &null, &error_abort); 483da668aa1SThomas Huth visit_check_struct(data->ov, &error_abort); 484da668aa1SThomas Huth visit_end_struct(data->ov, NULL); 485da668aa1SThomas Huth qdict = qobject_to(QDict, visitor_get(data)); 486da668aa1SThomas Huth g_assert(qdict); 487da668aa1SThomas Huth g_assert_cmpint(qdict_size(qdict), ==, 1); 488da668aa1SThomas Huth nil = qdict_get(qdict, "a"); 489da668aa1SThomas Huth g_assert(nil); 490da668aa1SThomas Huth g_assert(qobject_type(nil) == QTYPE_QNULL); 491da668aa1SThomas Huth } 492da668aa1SThomas Huth 49300e6832fSMarkus Armbruster static void test_visitor_out_list_struct(TestOutputVisitorData *data, 49400e6832fSMarkus Armbruster const void *unused) 495da668aa1SThomas Huth { 49600e6832fSMarkus Armbruster const char *int_member[] = { 49700e6832fSMarkus Armbruster "integer", "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64" }; 49800e6832fSMarkus Armbruster g_autoptr(ArrayStruct) arrs = g_new0(ArrayStruct, 1); 49900e6832fSMarkus Armbruster int i, j; 500da668aa1SThomas Huth QDict *qdict; 501da668aa1SThomas Huth QList *qlist; 50200e6832fSMarkus Armbruster QListEntry *e; 503da668aa1SThomas Huth 50400e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 50500e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->integer, i); 50600e6832fSMarkus Armbruster } 50700e6832fSMarkus Armbruster 50800e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 50900e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->s8, i); 51000e6832fSMarkus Armbruster } 51100e6832fSMarkus Armbruster 51200e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 51300e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->s16, i); 51400e6832fSMarkus Armbruster } 51500e6832fSMarkus Armbruster 51600e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 51700e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->s32, i); 51800e6832fSMarkus Armbruster } 51900e6832fSMarkus Armbruster 52000e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 52100e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->s64, i); 52200e6832fSMarkus Armbruster } 52300e6832fSMarkus Armbruster 52400e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 52500e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->u8, i); 52600e6832fSMarkus Armbruster } 52700e6832fSMarkus Armbruster 52800e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 52900e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->u16, i); 53000e6832fSMarkus Armbruster } 53100e6832fSMarkus Armbruster 53200e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 53300e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->u32, i); 53400e6832fSMarkus Armbruster } 53500e6832fSMarkus Armbruster 53600e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 53700e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->u64, i); 53800e6832fSMarkus Armbruster } 53900e6832fSMarkus Armbruster 54000e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 54100e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->number, (double)i / 3); 54200e6832fSMarkus Armbruster } 54300e6832fSMarkus Armbruster 54400e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 54500e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->boolean, QEMU_IS_ALIGNED(i, 3)); 54600e6832fSMarkus Armbruster } 54700e6832fSMarkus Armbruster 54800e6832fSMarkus Armbruster for (i = 31; i >= 0; i--) { 54900e6832fSMarkus Armbruster QAPI_LIST_PREPEND(arrs->string, g_strdup_printf("%d", i)); 55000e6832fSMarkus Armbruster } 55100e6832fSMarkus Armbruster 55200e6832fSMarkus Armbruster visit_type_ArrayStruct(data->ov, NULL, &arrs, &error_abort); 55300e6832fSMarkus Armbruster 55400e6832fSMarkus Armbruster qdict = qobject_to(QDict, visitor_get(data)); 555da668aa1SThomas Huth g_assert(qdict); 556da668aa1SThomas Huth 55700e6832fSMarkus Armbruster for (i = 0; i < G_N_ELEMENTS(int_member); i++) { 55800e6832fSMarkus Armbruster qlist = qdict_get_qlist(qdict, int_member[i]); 55900e6832fSMarkus Armbruster g_assert(qlist); 56000e6832fSMarkus Armbruster j = 0; 56100e6832fSMarkus Armbruster QLIST_FOREACH_ENTRY(qlist, e) { 56200e6832fSMarkus Armbruster QNum *qvalue = qobject_to(QNum, qlist_entry_obj(e)); 56300e6832fSMarkus Armbruster g_assert(qvalue); 56400e6832fSMarkus Armbruster g_assert_cmpint(qnum_get_int(qvalue), ==, j); 56500e6832fSMarkus Armbruster j++; 566da668aa1SThomas Huth } 567da668aa1SThomas Huth } 56800e6832fSMarkus Armbruster 56900e6832fSMarkus Armbruster qlist = qdict_get_qlist(qdict, "number"); 57000e6832fSMarkus Armbruster g_assert(qlist); 57100e6832fSMarkus Armbruster i = 0; 57200e6832fSMarkus Armbruster QLIST_FOREACH_ENTRY(qlist, e) { 57300e6832fSMarkus Armbruster QNum *qvalue = qobject_to(QNum, qlist_entry_obj(e)); 57400e6832fSMarkus Armbruster char expected[32], actual[32]; 57500e6832fSMarkus Armbruster 57600e6832fSMarkus Armbruster g_assert(qvalue); 57700e6832fSMarkus Armbruster sprintf(expected, "%.6f", (double)i / 3); 57800e6832fSMarkus Armbruster sprintf(actual, "%.6f", qnum_get_double(qvalue)); 57900e6832fSMarkus Armbruster g_assert_cmpstr(actual, ==, expected); 58000e6832fSMarkus Armbruster i++; 58100e6832fSMarkus Armbruster } 58200e6832fSMarkus Armbruster 58300e6832fSMarkus Armbruster qlist = qdict_get_qlist(qdict, "boolean"); 58400e6832fSMarkus Armbruster g_assert(qlist); 58500e6832fSMarkus Armbruster i = 0; 58600e6832fSMarkus Armbruster QLIST_FOREACH_ENTRY(qlist, e) { 58700e6832fSMarkus Armbruster QBool *qvalue = qobject_to(QBool, qlist_entry_obj(e)); 58800e6832fSMarkus Armbruster g_assert(qvalue); 589da668aa1SThomas Huth g_assert_cmpint(qbool_get_bool(qvalue), ==, i % 3 == 0); 59000e6832fSMarkus Armbruster i++; 591da668aa1SThomas Huth } 592da668aa1SThomas Huth 59300e6832fSMarkus Armbruster qlist = qdict_get_qlist(qdict, "string"); 59400e6832fSMarkus Armbruster g_assert(qlist); 59500e6832fSMarkus Armbruster i = 0; 59600e6832fSMarkus Armbruster QLIST_FOREACH_ENTRY(qlist, e) { 59700e6832fSMarkus Armbruster QString *qvalue = qobject_to(QString, qlist_entry_obj(e)); 59800e6832fSMarkus Armbruster char expected[32]; 599da668aa1SThomas Huth 60000e6832fSMarkus Armbruster g_assert(qvalue); 60100e6832fSMarkus Armbruster sprintf(expected, "%d", i); 60200e6832fSMarkus Armbruster g_assert_cmpstr(qstring_get_str(qvalue), ==, expected); 60300e6832fSMarkus Armbruster i++; 604da668aa1SThomas Huth } 605da668aa1SThomas Huth } 606da668aa1SThomas Huth 607da668aa1SThomas Huth static void output_visitor_test_add(const char *testpath, 608da668aa1SThomas Huth TestOutputVisitorData *data, 609da668aa1SThomas Huth void (*test_func)(TestOutputVisitorData *data, const void *user_data)) 610da668aa1SThomas Huth { 611da668aa1SThomas Huth g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup, 612da668aa1SThomas Huth test_func, visitor_output_teardown); 613da668aa1SThomas Huth } 614da668aa1SThomas Huth 615da668aa1SThomas Huth int main(int argc, char **argv) 616da668aa1SThomas Huth { 617da668aa1SThomas Huth TestOutputVisitorData out_visitor_data; 618da668aa1SThomas Huth 619da668aa1SThomas Huth g_test_init(&argc, &argv, NULL); 620da668aa1SThomas Huth 621da668aa1SThomas Huth output_visitor_test_add("/visitor/output/int", 622da668aa1SThomas Huth &out_visitor_data, test_visitor_out_int); 623da668aa1SThomas Huth output_visitor_test_add("/visitor/output/bool", 624da668aa1SThomas Huth &out_visitor_data, test_visitor_out_bool); 625da668aa1SThomas Huth output_visitor_test_add("/visitor/output/number", 626da668aa1SThomas Huth &out_visitor_data, test_visitor_out_number); 627da668aa1SThomas Huth output_visitor_test_add("/visitor/output/string", 628da668aa1SThomas Huth &out_visitor_data, test_visitor_out_string); 629da668aa1SThomas Huth output_visitor_test_add("/visitor/output/no-string", 630da668aa1SThomas Huth &out_visitor_data, test_visitor_out_no_string); 631da668aa1SThomas Huth output_visitor_test_add("/visitor/output/enum", 632da668aa1SThomas Huth &out_visitor_data, test_visitor_out_enum); 633da668aa1SThomas Huth output_visitor_test_add("/visitor/output/struct", 634da668aa1SThomas Huth &out_visitor_data, test_visitor_out_struct); 635da668aa1SThomas Huth output_visitor_test_add("/visitor/output/struct-nested", 636da668aa1SThomas Huth &out_visitor_data, test_visitor_out_struct_nested); 637da668aa1SThomas Huth output_visitor_test_add("/visitor/output/list", 638da668aa1SThomas Huth &out_visitor_data, test_visitor_out_list); 639da668aa1SThomas Huth output_visitor_test_add("/visitor/output/any", 640da668aa1SThomas Huth &out_visitor_data, test_visitor_out_any); 641da668aa1SThomas Huth output_visitor_test_add("/visitor/output/list-qapi-free", 642da668aa1SThomas Huth &out_visitor_data, test_visitor_out_list_qapi_free); 643da668aa1SThomas Huth output_visitor_test_add("/visitor/output/union-flat", 644da668aa1SThomas Huth &out_visitor_data, test_visitor_out_union_flat); 645*a17dbc4bSDaniel P. Berrangé output_visitor_test_add("/visitor/output/union-in-union", 646*a17dbc4bSDaniel P. Berrangé &out_visitor_data, test_visitor_out_union_in_union); 647da668aa1SThomas Huth output_visitor_test_add("/visitor/output/alternate", 648da668aa1SThomas Huth &out_visitor_data, test_visitor_out_alternate); 649da668aa1SThomas Huth output_visitor_test_add("/visitor/output/null", 650da668aa1SThomas Huth &out_visitor_data, test_visitor_out_null); 65100e6832fSMarkus Armbruster output_visitor_test_add("/visitor/output/list_struct", 65200e6832fSMarkus Armbruster &out_visitor_data, test_visitor_out_list_struct); 653da668aa1SThomas Huth 654da668aa1SThomas Huth g_test_run(); 655da668aa1SThomas Huth 656da668aa1SThomas Huth return 0; 657da668aa1SThomas Huth } 658