xref: /openbmc/qemu/tests/unit/test-qobject-output-visitor.c (revision b8eada54b2ad8a7d98d93d5ab4d3e888c5880097)
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