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
visitor_output_setup(TestOutputVisitorData * data,const void * unused)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
visitor_output_teardown(TestOutputVisitorData * data,const void * unused)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
visitor_get(TestOutputVisitorData * data)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
visitor_reset(TestOutputVisitorData * data)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
test_visitor_out_int(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_bool(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_number(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_string(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_no_string(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_enum(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_struct(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_struct_nested(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_list(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_list_qapi_free(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_any(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_union_flat(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_union_in_union(TestOutputVisitorData * data,const void * unused)355a17dbc4bSDaniel P. Berrangé static void test_visitor_out_union_in_union(TestOutputVisitorData *data,
356a17dbc4bSDaniel P. Berrangé const void *unused)
357a17dbc4bSDaniel P. Berrangé {
358a17dbc4bSDaniel P. Berrangé QDict *qdict;
359a17dbc4bSDaniel P. Berrangé
360a17dbc4bSDaniel P. Berrangé TestUnionInUnion *tmp = g_new0(TestUnionInUnion, 1);
361a17dbc4bSDaniel P. Berrangé tmp->type = TEST_UNION_ENUM_VALUE_A;
362*a25b2312SMarkus Armbruster tmp->u.value_a.type_a = TEST_UNION_ENUM_A_VALUE_A1;
363a17dbc4bSDaniel P. Berrangé tmp->u.value_a.u.value_a1.integer = 42;
364a17dbc4bSDaniel P. Berrangé tmp->u.value_a.u.value_a1.name = g_strdup("fish");
365a17dbc4bSDaniel P. Berrangé
366a17dbc4bSDaniel P. Berrangé visit_type_TestUnionInUnion(data->ov, NULL, &tmp, &error_abort);
367a17dbc4bSDaniel P. Berrangé qdict = qobject_to(QDict, visitor_get(data));
368a17dbc4bSDaniel P. Berrangé g_assert(qdict);
369a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "value-a");
370a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type-a"), ==, "value-a1");
371a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
372a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "name"), ==, "fish");
373a17dbc4bSDaniel P. Berrangé
374a17dbc4bSDaniel P. Berrangé qapi_free_TestUnionInUnion(tmp);
375a17dbc4bSDaniel P. Berrangé
376a17dbc4bSDaniel P. Berrangé
377a17dbc4bSDaniel P. Berrangé visitor_reset(data);
378a17dbc4bSDaniel P. Berrangé tmp = g_new0(TestUnionInUnion, 1);
379a17dbc4bSDaniel P. Berrangé tmp->type = TEST_UNION_ENUM_VALUE_A;
380*a25b2312SMarkus Armbruster tmp->u.value_a.type_a = TEST_UNION_ENUM_A_VALUE_A2;
381a17dbc4bSDaniel P. Berrangé tmp->u.value_a.u.value_a2.integer = 1729;
382a17dbc4bSDaniel P. Berrangé tmp->u.value_a.u.value_a2.size = 87539319;
383a17dbc4bSDaniel P. Berrangé
384a17dbc4bSDaniel P. Berrangé visit_type_TestUnionInUnion(data->ov, NULL, &tmp, &error_abort);
385a17dbc4bSDaniel P. Berrangé qdict = qobject_to(QDict, visitor_get(data));
386a17dbc4bSDaniel P. Berrangé g_assert(qdict);
387a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "value-a");
388a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type-a"), ==, "value-a2");
389a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1729);
390a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_int(qdict, "size"), ==, 87539319);
391a17dbc4bSDaniel P. Berrangé
392a17dbc4bSDaniel P. Berrangé qapi_free_TestUnionInUnion(tmp);
393a17dbc4bSDaniel P. Berrangé
394a17dbc4bSDaniel P. Berrangé
395a17dbc4bSDaniel P. Berrangé visitor_reset(data);
396a17dbc4bSDaniel P. Berrangé tmp = g_new0(TestUnionInUnion, 1);
397a17dbc4bSDaniel P. Berrangé tmp->type = TEST_UNION_ENUM_VALUE_B;
398a17dbc4bSDaniel P. Berrangé tmp->u.value_b.integer = 1729;
399a17dbc4bSDaniel P. Berrangé tmp->u.value_b.onoff = true;
400a17dbc4bSDaniel P. Berrangé
401a17dbc4bSDaniel P. Berrangé visit_type_TestUnionInUnion(data->ov, NULL, &tmp, &error_abort);
402a17dbc4bSDaniel P. Berrangé qdict = qobject_to(QDict, visitor_get(data));
403a17dbc4bSDaniel P. Berrangé g_assert(qdict);
404a17dbc4bSDaniel P. Berrangé g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "value-b");
405a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1729);
406a17dbc4bSDaniel P. Berrangé g_assert_cmpint(qdict_get_bool(qdict, "onoff"), ==, true);
407a17dbc4bSDaniel P. Berrangé
408a17dbc4bSDaniel P. Berrangé qapi_free_TestUnionInUnion(tmp);
409a17dbc4bSDaniel P. Berrangé }
410a17dbc4bSDaniel P. Berrangé
test_visitor_out_alternate(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_null(TestOutputVisitorData * data,const void * unused)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
test_visitor_out_list_struct(TestOutputVisitorData * data,const void * unused)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
output_visitor_test_add(const char * testpath,TestOutputVisitorData * data,void (* test_func)(TestOutputVisitorData * data,const void * user_data))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
main(int argc,char ** argv)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);
645a17dbc4bSDaniel P. Berrangé output_visitor_test_add("/visitor/output/union-in-union",
646a17dbc4bSDaniel 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