xref: /openbmc/qemu/tests/unit/test-qobject-output-visitor.c (revision 00e6832f419529645f45f93ccccb3778d51e9d0a)
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 "qemu-common.h"
16da668aa1SThomas Huth #include "qapi/error.h"
17da668aa1SThomas Huth #include "qapi/qobject-output-visitor.h"
18da668aa1SThomas Huth #include "test-qapi-visit.h"
19da668aa1SThomas Huth #include "qapi/qmp/qbool.h"
20da668aa1SThomas Huth #include "qapi/qmp/qdict.h"
21da668aa1SThomas Huth #include "qapi/qmp/qlist.h"
22da668aa1SThomas Huth #include "qapi/qmp/qnull.h"
23da668aa1SThomas Huth #include "qapi/qmp/qnum.h"
24da668aa1SThomas Huth #include "qapi/qmp/qstring.h"
25da668aa1SThomas Huth 
26da668aa1SThomas Huth typedef struct TestOutputVisitorData {
27da668aa1SThomas Huth     Visitor *ov;
28da668aa1SThomas Huth     QObject *obj;
29da668aa1SThomas Huth } TestOutputVisitorData;
30da668aa1SThomas Huth 
31da668aa1SThomas Huth static void visitor_output_setup(TestOutputVisitorData *data,
32da668aa1SThomas Huth                                  const void *unused)
33da668aa1SThomas Huth {
34da668aa1SThomas Huth     data->ov = qobject_output_visitor_new(&data->obj);
35da668aa1SThomas Huth     g_assert(data->ov);
36da668aa1SThomas Huth }
37da668aa1SThomas Huth 
38da668aa1SThomas Huth static void visitor_output_teardown(TestOutputVisitorData *data,
39da668aa1SThomas Huth                                     const void *unused)
40da668aa1SThomas Huth {
41da668aa1SThomas Huth     visit_free(data->ov);
42da668aa1SThomas Huth     data->ov = NULL;
43da668aa1SThomas Huth     qobject_unref(data->obj);
44da668aa1SThomas Huth     data->obj = NULL;
45da668aa1SThomas Huth }
46da668aa1SThomas Huth 
47da668aa1SThomas Huth static QObject *visitor_get(TestOutputVisitorData *data)
48da668aa1SThomas Huth {
49da668aa1SThomas Huth     visit_complete(data->ov, &data->obj);
50da668aa1SThomas Huth     g_assert(data->obj);
51da668aa1SThomas Huth     return data->obj;
52da668aa1SThomas Huth }
53da668aa1SThomas Huth 
54da668aa1SThomas Huth static void visitor_reset(TestOutputVisitorData *data)
55da668aa1SThomas Huth {
56da668aa1SThomas Huth     visitor_output_teardown(data, NULL);
57da668aa1SThomas Huth     visitor_output_setup(data, NULL);
58da668aa1SThomas Huth }
59da668aa1SThomas Huth 
60da668aa1SThomas Huth static void test_visitor_out_int(TestOutputVisitorData *data,
61da668aa1SThomas Huth                                  const void *unused)
62da668aa1SThomas Huth {
63da668aa1SThomas Huth     int64_t value = -42;
64da668aa1SThomas Huth     int64_t val;
65da668aa1SThomas Huth     QNum *qnum;
66da668aa1SThomas Huth 
67da668aa1SThomas Huth     visit_type_int(data->ov, NULL, &value, &error_abort);
68da668aa1SThomas Huth 
69da668aa1SThomas Huth     qnum = qobject_to(QNum, visitor_get(data));
70da668aa1SThomas Huth     g_assert(qnum);
71da668aa1SThomas Huth     g_assert(qnum_get_try_int(qnum, &val));
72da668aa1SThomas Huth     g_assert_cmpint(val, ==, value);
73da668aa1SThomas Huth }
74da668aa1SThomas Huth 
75da668aa1SThomas Huth static void test_visitor_out_bool(TestOutputVisitorData *data,
76da668aa1SThomas Huth                                   const void *unused)
77da668aa1SThomas Huth {
78da668aa1SThomas Huth     bool value = true;
79da668aa1SThomas Huth     QBool *qbool;
80da668aa1SThomas Huth 
81da668aa1SThomas Huth     visit_type_bool(data->ov, NULL, &value, &error_abort);
82da668aa1SThomas Huth 
83da668aa1SThomas Huth     qbool = qobject_to(QBool, visitor_get(data));
84da668aa1SThomas Huth     g_assert(qbool);
85da668aa1SThomas Huth     g_assert(qbool_get_bool(qbool) == value);
86da668aa1SThomas Huth }
87da668aa1SThomas Huth 
88da668aa1SThomas Huth static void test_visitor_out_number(TestOutputVisitorData *data,
89da668aa1SThomas Huth                                     const void *unused)
90da668aa1SThomas Huth {
91da668aa1SThomas Huth     double value = 3.14;
92da668aa1SThomas Huth     QNum *qnum;
93da668aa1SThomas Huth 
94da668aa1SThomas Huth     visit_type_number(data->ov, NULL, &value, &error_abort);
95da668aa1SThomas Huth 
96da668aa1SThomas Huth     qnum = qobject_to(QNum, visitor_get(data));
97da668aa1SThomas Huth     g_assert(qnum);
98da668aa1SThomas Huth     g_assert(qnum_get_double(qnum) == value);
99da668aa1SThomas Huth }
100da668aa1SThomas Huth 
101da668aa1SThomas Huth static void test_visitor_out_string(TestOutputVisitorData *data,
102da668aa1SThomas Huth                                     const void *unused)
103da668aa1SThomas Huth {
104da668aa1SThomas Huth     char *string = (char *) "Q E M U";
105da668aa1SThomas Huth     QString *qstr;
106da668aa1SThomas Huth 
107da668aa1SThomas Huth     visit_type_str(data->ov, NULL, &string, &error_abort);
108da668aa1SThomas Huth 
109da668aa1SThomas Huth     qstr = qobject_to(QString, visitor_get(data));
110da668aa1SThomas Huth     g_assert(qstr);
111da668aa1SThomas Huth     g_assert_cmpstr(qstring_get_str(qstr), ==, string);
112da668aa1SThomas Huth }
113da668aa1SThomas Huth 
114da668aa1SThomas Huth static void test_visitor_out_no_string(TestOutputVisitorData *data,
115da668aa1SThomas Huth                                        const void *unused)
116da668aa1SThomas Huth {
117da668aa1SThomas Huth     char *string = NULL;
118da668aa1SThomas Huth     QString *qstr;
119da668aa1SThomas Huth 
120da668aa1SThomas Huth     /* A null string should return "" */
121da668aa1SThomas Huth     visit_type_str(data->ov, NULL, &string, &error_abort);
122da668aa1SThomas Huth 
123da668aa1SThomas Huth     qstr = qobject_to(QString, visitor_get(data));
124da668aa1SThomas Huth     g_assert(qstr);
125da668aa1SThomas Huth     g_assert_cmpstr(qstring_get_str(qstr), ==, "");
126da668aa1SThomas Huth }
127da668aa1SThomas Huth 
128da668aa1SThomas Huth static void test_visitor_out_enum(TestOutputVisitorData *data,
129da668aa1SThomas Huth                                   const void *unused)
130da668aa1SThomas Huth {
131da668aa1SThomas Huth     EnumOne i;
132da668aa1SThomas Huth     QString *qstr;
133da668aa1SThomas Huth 
134da668aa1SThomas Huth     for (i = 0; i < ENUM_ONE__MAX; i++) {
135da668aa1SThomas Huth         visit_type_EnumOne(data->ov, "unused", &i, &error_abort);
136da668aa1SThomas Huth 
137da668aa1SThomas Huth         qstr = qobject_to(QString, visitor_get(data));
138da668aa1SThomas Huth         g_assert(qstr);
139da668aa1SThomas Huth         g_assert_cmpstr(qstring_get_str(qstr), ==, EnumOne_str(i));
140da668aa1SThomas Huth         visitor_reset(data);
141da668aa1SThomas Huth     }
142da668aa1SThomas Huth }
143da668aa1SThomas Huth 
144da668aa1SThomas Huth static void test_visitor_out_struct(TestOutputVisitorData *data,
145da668aa1SThomas Huth                                     const void *unused)
146da668aa1SThomas Huth {
147da668aa1SThomas Huth     TestStruct test_struct = { .integer = 42,
148da668aa1SThomas Huth                                .boolean = false,
149da668aa1SThomas Huth                                .string = (char *) "foo"};
150da668aa1SThomas Huth     TestStruct *p = &test_struct;
151da668aa1SThomas Huth     QDict *qdict;
152da668aa1SThomas Huth 
153da668aa1SThomas Huth     visit_type_TestStruct(data->ov, NULL, &p, &error_abort);
154da668aa1SThomas Huth 
155da668aa1SThomas Huth     qdict = qobject_to(QDict, visitor_get(data));
156da668aa1SThomas Huth     g_assert(qdict);
157da668aa1SThomas Huth     g_assert_cmpint(qdict_size(qdict), ==, 3);
158da668aa1SThomas Huth     g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
159da668aa1SThomas Huth     g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, false);
160da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
161da668aa1SThomas Huth }
162da668aa1SThomas Huth 
163da668aa1SThomas Huth static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
164da668aa1SThomas Huth                                            const void *unused)
165da668aa1SThomas Huth {
166da668aa1SThomas Huth     int64_t value = 42;
167da668aa1SThomas Huth     UserDefTwo *ud2;
168da668aa1SThomas Huth     QDict *qdict, *dict1, *dict2, *dict3, *userdef;
169da668aa1SThomas Huth     const char *string = "user def string";
170da668aa1SThomas Huth     const char *strings[] = { "forty two", "forty three", "forty four",
171da668aa1SThomas Huth                               "forty five" };
172da668aa1SThomas Huth 
173da668aa1SThomas Huth     ud2 = g_malloc0(sizeof(*ud2));
174da668aa1SThomas Huth     ud2->string0 = g_strdup(strings[0]);
175da668aa1SThomas Huth 
176da668aa1SThomas Huth     ud2->dict1 = g_malloc0(sizeof(*ud2->dict1));
177da668aa1SThomas Huth     ud2->dict1->string1 = g_strdup(strings[1]);
178da668aa1SThomas Huth 
179da668aa1SThomas Huth     ud2->dict1->dict2 = g_malloc0(sizeof(*ud2->dict1->dict2));
180da668aa1SThomas Huth     ud2->dict1->dict2->userdef = g_new0(UserDefOne, 1);
181da668aa1SThomas Huth     ud2->dict1->dict2->userdef->string = g_strdup(string);
182da668aa1SThomas Huth     ud2->dict1->dict2->userdef->integer = value;
183da668aa1SThomas Huth     ud2->dict1->dict2->string = g_strdup(strings[2]);
184da668aa1SThomas Huth 
185da668aa1SThomas Huth     ud2->dict1->dict3 = g_malloc0(sizeof(*ud2->dict1->dict3));
186da668aa1SThomas Huth     ud2->dict1->has_dict3 = true;
187da668aa1SThomas Huth     ud2->dict1->dict3->userdef = g_new0(UserDefOne, 1);
188da668aa1SThomas Huth     ud2->dict1->dict3->userdef->string = g_strdup(string);
189da668aa1SThomas Huth     ud2->dict1->dict3->userdef->integer = value;
190da668aa1SThomas Huth     ud2->dict1->dict3->string = g_strdup(strings[3]);
191da668aa1SThomas Huth 
192da668aa1SThomas Huth     visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);
193da668aa1SThomas Huth 
194da668aa1SThomas Huth     qdict = qobject_to(QDict, visitor_get(data));
195da668aa1SThomas Huth     g_assert(qdict);
196da668aa1SThomas Huth     g_assert_cmpint(qdict_size(qdict), ==, 2);
197da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
198da668aa1SThomas Huth 
199da668aa1SThomas Huth     dict1 = qdict_get_qdict(qdict, "dict1");
200da668aa1SThomas Huth     g_assert_cmpint(qdict_size(dict1), ==, 3);
201da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
202da668aa1SThomas Huth 
203da668aa1SThomas Huth     dict2 = qdict_get_qdict(dict1, "dict2");
204da668aa1SThomas Huth     g_assert_cmpint(qdict_size(dict2), ==, 2);
205da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(dict2, "string"), ==, strings[2]);
206da668aa1SThomas Huth     userdef = qdict_get_qdict(dict2, "userdef");
207da668aa1SThomas Huth     g_assert_cmpint(qdict_size(userdef), ==, 2);
208da668aa1SThomas Huth     g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
209da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
210da668aa1SThomas Huth 
211da668aa1SThomas Huth     dict3 = qdict_get_qdict(dict1, "dict3");
212da668aa1SThomas Huth     g_assert_cmpint(qdict_size(dict3), ==, 2);
213da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(dict3, "string"), ==, strings[3]);
214da668aa1SThomas Huth     userdef = qdict_get_qdict(dict3, "userdef");
215da668aa1SThomas Huth     g_assert_cmpint(qdict_size(userdef), ==, 2);
216da668aa1SThomas Huth     g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
217da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
218da668aa1SThomas Huth 
219da668aa1SThomas Huth     qapi_free_UserDefTwo(ud2);
220da668aa1SThomas Huth }
221da668aa1SThomas Huth 
222da668aa1SThomas Huth static void test_visitor_out_list(TestOutputVisitorData *data,
223da668aa1SThomas Huth                                   const void *unused)
224da668aa1SThomas Huth {
225da668aa1SThomas Huth     const char *value_str = "list value";
226da668aa1SThomas Huth     TestStruct *value;
227da668aa1SThomas Huth     TestStructList *head = NULL;
228da668aa1SThomas Huth     const int max_items = 10;
229da668aa1SThomas Huth     bool value_bool = true;
230da668aa1SThomas Huth     int value_int = 10;
231da668aa1SThomas Huth     QListEntry *entry;
232da668aa1SThomas Huth     QList *qlist;
233da668aa1SThomas Huth     int i;
234da668aa1SThomas Huth 
235da668aa1SThomas Huth     /* Build the list in reverse order... */
236da668aa1SThomas Huth     for (i = 0; i < max_items; i++) {
237da668aa1SThomas Huth         value = g_malloc0(sizeof(*value));
238da668aa1SThomas Huth         value->integer = value_int + (max_items - i - 1);
239da668aa1SThomas Huth         value->boolean = value_bool;
240da668aa1SThomas Huth         value->string = g_strdup(value_str);
241da668aa1SThomas Huth 
242da668aa1SThomas Huth         QAPI_LIST_PREPEND(head, value);
243da668aa1SThomas Huth     }
244da668aa1SThomas Huth 
245da668aa1SThomas Huth     visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
246da668aa1SThomas Huth 
247da668aa1SThomas Huth     qlist = qobject_to(QList, visitor_get(data));
248da668aa1SThomas Huth     g_assert(qlist);
249da668aa1SThomas Huth     g_assert(!qlist_empty(qlist));
250da668aa1SThomas Huth 
251da668aa1SThomas Huth     /* ...and ensure that the visitor sees it in order */
252da668aa1SThomas Huth     i = 0;
253da668aa1SThomas Huth     QLIST_FOREACH_ENTRY(qlist, entry) {
254da668aa1SThomas Huth         QDict *qdict;
255da668aa1SThomas Huth 
256da668aa1SThomas Huth         qdict = qobject_to(QDict, entry->value);
257da668aa1SThomas Huth         g_assert(qdict);
258da668aa1SThomas Huth         g_assert_cmpint(qdict_size(qdict), ==, 3);
259da668aa1SThomas Huth         g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int + i);
260da668aa1SThomas Huth         g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
261da668aa1SThomas Huth         g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
262da668aa1SThomas Huth         i++;
263da668aa1SThomas Huth     }
264da668aa1SThomas Huth     g_assert_cmpint(i, ==, max_items);
265da668aa1SThomas Huth 
266da668aa1SThomas Huth     qapi_free_TestStructList(head);
267da668aa1SThomas Huth }
268da668aa1SThomas Huth 
269da668aa1SThomas Huth static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
270da668aa1SThomas Huth                                             const void *unused)
271da668aa1SThomas Huth {
272da668aa1SThomas Huth     UserDefTwo *value;
273da668aa1SThomas Huth     UserDefTwoList *head = NULL;
274da668aa1SThomas Huth     const char string[] = "foo bar";
275da668aa1SThomas Huth     int i, max_count = 1024;
276da668aa1SThomas Huth 
277da668aa1SThomas Huth     for (i = 0; i < max_count; i++) {
278da668aa1SThomas Huth         value = g_malloc0(sizeof(*value));
279da668aa1SThomas Huth 
280da668aa1SThomas Huth         value->string0 = g_strdup(string);
281da668aa1SThomas Huth         value->dict1 = g_new0(UserDefTwoDict, 1);
282da668aa1SThomas Huth         value->dict1->string1 = g_strdup(string);
283da668aa1SThomas Huth         value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
284da668aa1SThomas Huth         value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
285da668aa1SThomas Huth         value->dict1->dict2->userdef->string = g_strdup(string);
286da668aa1SThomas Huth         value->dict1->dict2->userdef->integer = 42;
287da668aa1SThomas Huth         value->dict1->dict2->string = g_strdup(string);
288da668aa1SThomas Huth         value->dict1->has_dict3 = false;
289da668aa1SThomas Huth 
290da668aa1SThomas Huth         QAPI_LIST_PREPEND(head, value);
291da668aa1SThomas Huth     }
292da668aa1SThomas Huth 
293da668aa1SThomas Huth     qapi_free_UserDefTwoList(head);
294da668aa1SThomas Huth }
295da668aa1SThomas Huth 
296da668aa1SThomas Huth static void test_visitor_out_any(TestOutputVisitorData *data,
297da668aa1SThomas Huth                                  const void *unused)
298da668aa1SThomas Huth {
299da668aa1SThomas Huth     QObject *qobj;
300da668aa1SThomas Huth     QNum *qnum;
301da668aa1SThomas Huth     QBool *qbool;
302da668aa1SThomas Huth     QString *qstring;
303da668aa1SThomas Huth     QDict *qdict;
304da668aa1SThomas Huth     int64_t val;
305da668aa1SThomas Huth 
306da668aa1SThomas Huth     qobj = QOBJECT(qnum_from_int(-42));
307da668aa1SThomas Huth     visit_type_any(data->ov, NULL, &qobj, &error_abort);
308da668aa1SThomas Huth     qnum = qobject_to(QNum, visitor_get(data));
309da668aa1SThomas Huth     g_assert(qnum);
310da668aa1SThomas Huth     g_assert(qnum_get_try_int(qnum, &val));
311da668aa1SThomas Huth     g_assert_cmpint(val, ==, -42);
312da668aa1SThomas Huth     qobject_unref(qobj);
313da668aa1SThomas Huth 
314da668aa1SThomas Huth     visitor_reset(data);
315da668aa1SThomas Huth     qdict = qdict_new();
316da668aa1SThomas Huth     qdict_put_int(qdict, "integer", -42);
317da668aa1SThomas Huth     qdict_put_bool(qdict, "boolean", true);
318da668aa1SThomas Huth     qdict_put_str(qdict, "string", "foo");
319da668aa1SThomas Huth     qobj = QOBJECT(qdict);
320da668aa1SThomas Huth     visit_type_any(data->ov, NULL, &qobj, &error_abort);
321da668aa1SThomas Huth     qobject_unref(qobj);
322da668aa1SThomas Huth     qdict = qobject_to(QDict, visitor_get(data));
323da668aa1SThomas Huth     g_assert(qdict);
324da668aa1SThomas Huth     qnum = qobject_to(QNum, qdict_get(qdict, "integer"));
325da668aa1SThomas Huth     g_assert(qnum);
326da668aa1SThomas Huth     g_assert(qnum_get_try_int(qnum, &val));
327da668aa1SThomas Huth     g_assert_cmpint(val, ==, -42);
328da668aa1SThomas Huth     qbool = qobject_to(QBool, qdict_get(qdict, "boolean"));
329da668aa1SThomas Huth     g_assert(qbool);
330da668aa1SThomas Huth     g_assert(qbool_get_bool(qbool) == true);
331da668aa1SThomas Huth     qstring = qobject_to(QString, qdict_get(qdict, "string"));
332da668aa1SThomas Huth     g_assert(qstring);
333da668aa1SThomas Huth     g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
334da668aa1SThomas Huth }
335da668aa1SThomas Huth 
336da668aa1SThomas Huth static void test_visitor_out_union_flat(TestOutputVisitorData *data,
337da668aa1SThomas Huth                                         const void *unused)
338da668aa1SThomas Huth {
339da668aa1SThomas Huth     QDict *qdict;
340da668aa1SThomas Huth 
341da668aa1SThomas Huth     UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion));
342da668aa1SThomas Huth     tmp->enum1 = ENUM_ONE_VALUE1;
343da668aa1SThomas Huth     tmp->string = g_strdup("str");
344da668aa1SThomas Huth     tmp->integer = 41;
345da668aa1SThomas Huth     tmp->u.value1.boolean = true;
346da668aa1SThomas Huth 
347da668aa1SThomas Huth     visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort);
348da668aa1SThomas Huth     qdict = qobject_to(QDict, visitor_get(data));
349da668aa1SThomas Huth     g_assert(qdict);
350da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
351da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
352da668aa1SThomas Huth     g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41);
353da668aa1SThomas Huth     g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
354da668aa1SThomas Huth 
355da668aa1SThomas Huth     qapi_free_UserDefFlatUnion(tmp);
356da668aa1SThomas Huth }
357da668aa1SThomas Huth 
358da668aa1SThomas Huth static void test_visitor_out_alternate(TestOutputVisitorData *data,
359da668aa1SThomas Huth                                        const void *unused)
360da668aa1SThomas Huth {
361da668aa1SThomas Huth     UserDefAlternate *tmp;
362da668aa1SThomas Huth     QNum *qnum;
363da668aa1SThomas Huth     QString *qstr;
364da668aa1SThomas Huth     QDict *qdict;
365da668aa1SThomas Huth     int64_t val;
366da668aa1SThomas Huth 
367da668aa1SThomas Huth     tmp = g_new0(UserDefAlternate, 1);
368da668aa1SThomas Huth     tmp->type = QTYPE_QNUM;
369da668aa1SThomas Huth     tmp->u.i = 42;
370da668aa1SThomas Huth 
371da668aa1SThomas Huth     visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
372da668aa1SThomas Huth     qnum = qobject_to(QNum, visitor_get(data));
373da668aa1SThomas Huth     g_assert(qnum);
374da668aa1SThomas Huth     g_assert(qnum_get_try_int(qnum, &val));
375da668aa1SThomas Huth     g_assert_cmpint(val, ==, 42);
376da668aa1SThomas Huth 
377da668aa1SThomas Huth     qapi_free_UserDefAlternate(tmp);
378da668aa1SThomas Huth 
379da668aa1SThomas Huth     visitor_reset(data);
380da668aa1SThomas Huth     tmp = g_new0(UserDefAlternate, 1);
381da668aa1SThomas Huth     tmp->type = QTYPE_QSTRING;
382da668aa1SThomas Huth     tmp->u.e = ENUM_ONE_VALUE1;
383da668aa1SThomas Huth 
384da668aa1SThomas Huth     visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
385da668aa1SThomas Huth     qstr = qobject_to(QString, visitor_get(data));
386da668aa1SThomas Huth     g_assert(qstr);
387da668aa1SThomas Huth     g_assert_cmpstr(qstring_get_str(qstr), ==, "value1");
388da668aa1SThomas Huth 
389da668aa1SThomas Huth     qapi_free_UserDefAlternate(tmp);
390da668aa1SThomas Huth 
391da668aa1SThomas Huth     visitor_reset(data);
392da668aa1SThomas Huth     tmp = g_new0(UserDefAlternate, 1);
393da668aa1SThomas Huth     tmp->type = QTYPE_QNULL;
394da668aa1SThomas Huth     tmp->u.n = qnull();
395da668aa1SThomas Huth 
396da668aa1SThomas Huth     visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
397da668aa1SThomas Huth     g_assert_cmpint(qobject_type(visitor_get(data)), ==, QTYPE_QNULL);
398da668aa1SThomas Huth 
399da668aa1SThomas Huth     qapi_free_UserDefAlternate(tmp);
400da668aa1SThomas Huth 
401da668aa1SThomas Huth     visitor_reset(data);
402da668aa1SThomas Huth     tmp = g_new0(UserDefAlternate, 1);
403da668aa1SThomas Huth     tmp->type = QTYPE_QDICT;
404da668aa1SThomas Huth     tmp->u.udfu.integer = 1;
405da668aa1SThomas Huth     tmp->u.udfu.string = g_strdup("str");
406da668aa1SThomas Huth     tmp->u.udfu.enum1 = ENUM_ONE_VALUE1;
407da668aa1SThomas Huth     tmp->u.udfu.u.value1.boolean = true;
408da668aa1SThomas Huth 
409da668aa1SThomas Huth     visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
410da668aa1SThomas Huth     qdict = qobject_to(QDict, visitor_get(data));
411da668aa1SThomas Huth     g_assert(qdict);
412da668aa1SThomas Huth     g_assert_cmpint(qdict_size(qdict), ==, 4);
413da668aa1SThomas Huth     g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1);
414da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
415da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
416da668aa1SThomas Huth     g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
417da668aa1SThomas Huth 
418da668aa1SThomas Huth     qapi_free_UserDefAlternate(tmp);
419da668aa1SThomas Huth }
420da668aa1SThomas Huth 
421da668aa1SThomas Huth static void test_visitor_out_null(TestOutputVisitorData *data,
422da668aa1SThomas Huth                                   const void *unused)
423da668aa1SThomas Huth {
424da668aa1SThomas Huth     QNull *null = NULL;
425da668aa1SThomas Huth     QDict *qdict;
426da668aa1SThomas Huth     QObject *nil;
427da668aa1SThomas Huth 
428da668aa1SThomas Huth     visit_start_struct(data->ov, NULL, NULL, 0, &error_abort);
429da668aa1SThomas Huth     visit_type_null(data->ov, "a", &null, &error_abort);
430da668aa1SThomas Huth     visit_check_struct(data->ov, &error_abort);
431da668aa1SThomas Huth     visit_end_struct(data->ov, NULL);
432da668aa1SThomas Huth     qdict = qobject_to(QDict, visitor_get(data));
433da668aa1SThomas Huth     g_assert(qdict);
434da668aa1SThomas Huth     g_assert_cmpint(qdict_size(qdict), ==, 1);
435da668aa1SThomas Huth     nil = qdict_get(qdict, "a");
436da668aa1SThomas Huth     g_assert(nil);
437da668aa1SThomas Huth     g_assert(qobject_type(nil) == QTYPE_QNULL);
438da668aa1SThomas Huth }
439da668aa1SThomas Huth 
440*00e6832fSMarkus Armbruster static void test_visitor_out_list_struct(TestOutputVisitorData *data,
441*00e6832fSMarkus Armbruster                                          const void *unused)
442da668aa1SThomas Huth {
443*00e6832fSMarkus Armbruster     const char *int_member[] = {
444*00e6832fSMarkus Armbruster         "integer", "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64" };
445*00e6832fSMarkus Armbruster     g_autoptr(ArrayStruct) arrs = g_new0(ArrayStruct, 1);
446*00e6832fSMarkus Armbruster     int i, j;
447da668aa1SThomas Huth     QDict *qdict;
448da668aa1SThomas Huth     QList *qlist;
449*00e6832fSMarkus Armbruster     QListEntry *e;
450da668aa1SThomas Huth 
451*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
452*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->integer, i);
453*00e6832fSMarkus Armbruster     }
454*00e6832fSMarkus Armbruster 
455*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
456*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->s8, i);
457*00e6832fSMarkus Armbruster     }
458*00e6832fSMarkus Armbruster 
459*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
460*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->s16, i);
461*00e6832fSMarkus Armbruster     }
462*00e6832fSMarkus Armbruster 
463*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
464*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->s32, i);
465*00e6832fSMarkus Armbruster     }
466*00e6832fSMarkus Armbruster 
467*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
468*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->s64, i);
469*00e6832fSMarkus Armbruster     }
470*00e6832fSMarkus Armbruster 
471*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
472*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->u8, i);
473*00e6832fSMarkus Armbruster     }
474*00e6832fSMarkus Armbruster 
475*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
476*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->u16, i);
477*00e6832fSMarkus Armbruster     }
478*00e6832fSMarkus Armbruster 
479*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
480*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->u32, i);
481*00e6832fSMarkus Armbruster     }
482*00e6832fSMarkus Armbruster 
483*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
484*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->u64, i);
485*00e6832fSMarkus Armbruster     }
486*00e6832fSMarkus Armbruster 
487*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
488*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->number, (double)i / 3);
489*00e6832fSMarkus Armbruster     }
490*00e6832fSMarkus Armbruster 
491*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
492*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->boolean, QEMU_IS_ALIGNED(i, 3));
493*00e6832fSMarkus Armbruster     }
494*00e6832fSMarkus Armbruster 
495*00e6832fSMarkus Armbruster     for (i = 31; i >= 0; i--) {
496*00e6832fSMarkus Armbruster         QAPI_LIST_PREPEND(arrs->string, g_strdup_printf("%d", i));
497*00e6832fSMarkus Armbruster     }
498*00e6832fSMarkus Armbruster 
499*00e6832fSMarkus Armbruster     visit_type_ArrayStruct(data->ov, NULL, &arrs, &error_abort);
500*00e6832fSMarkus Armbruster 
501*00e6832fSMarkus Armbruster     qdict = qobject_to(QDict, visitor_get(data));
502da668aa1SThomas Huth     g_assert(qdict);
503da668aa1SThomas Huth 
504*00e6832fSMarkus Armbruster     for (i = 0; i < G_N_ELEMENTS(int_member); i++) {
505*00e6832fSMarkus Armbruster         qlist = qdict_get_qlist(qdict, int_member[i]);
506*00e6832fSMarkus Armbruster         g_assert(qlist);
507*00e6832fSMarkus Armbruster         j = 0;
508*00e6832fSMarkus Armbruster         QLIST_FOREACH_ENTRY(qlist, e) {
509*00e6832fSMarkus Armbruster             QNum *qvalue = qobject_to(QNum, qlist_entry_obj(e));
510*00e6832fSMarkus Armbruster             g_assert(qvalue);
511*00e6832fSMarkus Armbruster             g_assert_cmpint(qnum_get_int(qvalue), ==, j);
512*00e6832fSMarkus Armbruster             j++;
513da668aa1SThomas Huth         }
514da668aa1SThomas Huth     }
515*00e6832fSMarkus Armbruster 
516*00e6832fSMarkus Armbruster     qlist = qdict_get_qlist(qdict, "number");
517*00e6832fSMarkus Armbruster     g_assert(qlist);
518*00e6832fSMarkus Armbruster     i = 0;
519*00e6832fSMarkus Armbruster     QLIST_FOREACH_ENTRY(qlist, e) {
520*00e6832fSMarkus Armbruster         QNum *qvalue = qobject_to(QNum, qlist_entry_obj(e));
521*00e6832fSMarkus Armbruster         char expected[32], actual[32];
522*00e6832fSMarkus Armbruster 
523*00e6832fSMarkus Armbruster         g_assert(qvalue);
524*00e6832fSMarkus Armbruster         sprintf(expected, "%.6f", (double)i / 3);
525*00e6832fSMarkus Armbruster         sprintf(actual, "%.6f", qnum_get_double(qvalue));
526*00e6832fSMarkus Armbruster         g_assert_cmpstr(actual, ==, expected);
527*00e6832fSMarkus Armbruster         i++;
528*00e6832fSMarkus Armbruster     }
529*00e6832fSMarkus Armbruster 
530*00e6832fSMarkus Armbruster     qlist = qdict_get_qlist(qdict, "boolean");
531*00e6832fSMarkus Armbruster     g_assert(qlist);
532*00e6832fSMarkus Armbruster     i = 0;
533*00e6832fSMarkus Armbruster     QLIST_FOREACH_ENTRY(qlist, e) {
534*00e6832fSMarkus Armbruster         QBool *qvalue = qobject_to(QBool, qlist_entry_obj(e));
535*00e6832fSMarkus Armbruster         g_assert(qvalue);
536da668aa1SThomas Huth         g_assert_cmpint(qbool_get_bool(qvalue), ==, i % 3 == 0);
537*00e6832fSMarkus Armbruster         i++;
538da668aa1SThomas Huth     }
539da668aa1SThomas Huth 
540*00e6832fSMarkus Armbruster     qlist = qdict_get_qlist(qdict, "string");
541*00e6832fSMarkus Armbruster     g_assert(qlist);
542*00e6832fSMarkus Armbruster     i = 0;
543*00e6832fSMarkus Armbruster     QLIST_FOREACH_ENTRY(qlist, e) {
544*00e6832fSMarkus Armbruster         QString *qvalue = qobject_to(QString, qlist_entry_obj(e));
545*00e6832fSMarkus Armbruster         char expected[32];
546da668aa1SThomas Huth 
547*00e6832fSMarkus Armbruster         g_assert(qvalue);
548*00e6832fSMarkus Armbruster         sprintf(expected, "%d", i);
549*00e6832fSMarkus Armbruster         g_assert_cmpstr(qstring_get_str(qvalue), ==, expected);
550*00e6832fSMarkus Armbruster         i++;
551da668aa1SThomas Huth     }
552da668aa1SThomas Huth }
553da668aa1SThomas Huth 
554da668aa1SThomas Huth static void output_visitor_test_add(const char *testpath,
555da668aa1SThomas Huth                                     TestOutputVisitorData *data,
556da668aa1SThomas Huth                                     void (*test_func)(TestOutputVisitorData *data, const void *user_data))
557da668aa1SThomas Huth {
558da668aa1SThomas Huth     g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
559da668aa1SThomas Huth                test_func, visitor_output_teardown);
560da668aa1SThomas Huth }
561da668aa1SThomas Huth 
562da668aa1SThomas Huth int main(int argc, char **argv)
563da668aa1SThomas Huth {
564da668aa1SThomas Huth     TestOutputVisitorData out_visitor_data;
565da668aa1SThomas Huth 
566da668aa1SThomas Huth     g_test_init(&argc, &argv, NULL);
567da668aa1SThomas Huth 
568da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/int",
569da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_int);
570da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/bool",
571da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_bool);
572da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/number",
573da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_number);
574da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/string",
575da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_string);
576da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/no-string",
577da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_no_string);
578da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/enum",
579da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_enum);
580da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/struct",
581da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_struct);
582da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/struct-nested",
583da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_struct_nested);
584da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/list",
585da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_list);
586da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/any",
587da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_any);
588da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/list-qapi-free",
589da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_list_qapi_free);
590da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/union-flat",
591da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_union_flat);
592da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/alternate",
593da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_alternate);
594da668aa1SThomas Huth     output_visitor_test_add("/visitor/output/null",
595da668aa1SThomas Huth                             &out_visitor_data, test_visitor_out_null);
596*00e6832fSMarkus Armbruster     output_visitor_test_add("/visitor/output/list_struct",
597*00e6832fSMarkus Armbruster                             &out_visitor_data, test_visitor_out_list_struct);
598da668aa1SThomas Huth 
599da668aa1SThomas Huth     g_test_run();
600da668aa1SThomas Huth 
601da668aa1SThomas Huth     return 0;
602da668aa1SThomas Huth }
603