xref: /qemu/tests/unit/test-qobject-input-visitor.c (revision b3db211f3c80bb996a704d665fe275619f728bd4)
1d88f5fd1SLuiz Capitulino /*
2*b3db211fSDaniel P. Berrange  * QObject Input Visitor unit-tests.
3d88f5fd1SLuiz Capitulino  *
468d07839SEric Blake  * Copyright (C) 2011-2016 Red Hat Inc.
5d88f5fd1SLuiz Capitulino  *
6d88f5fd1SLuiz Capitulino  * Authors:
7d88f5fd1SLuiz Capitulino  *  Luiz Capitulino <lcapitulino@redhat.com>
8d88f5fd1SLuiz Capitulino  *
9d88f5fd1SLuiz Capitulino  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10d88f5fd1SLuiz Capitulino  * See the COPYING file in the top-level directory.
11d88f5fd1SLuiz Capitulino  */
12d88f5fd1SLuiz Capitulino 
13681c28a3SPeter Maydell #include "qemu/osdep.h"
14d88f5fd1SLuiz Capitulino 
1579ee7df8SPaolo Bonzini #include "qemu-common.h"
16da34e65cSMarkus Armbruster #include "qapi/error.h"
17*b3db211fSDaniel P. Berrange #include "qapi/qobject-input-visitor.h"
18d88f5fd1SLuiz Capitulino #include "test-qapi-types.h"
19d88f5fd1SLuiz Capitulino #include "test-qapi-visit.h"
207b1b5d19SPaolo Bonzini #include "qapi/qmp/types.h"
21c7eb39cbSEric Blake #include "qapi/qmp/qjson.h"
22d88f5fd1SLuiz Capitulino 
23d88f5fd1SLuiz Capitulino typedef struct TestInputVisitorData {
24d88f5fd1SLuiz Capitulino     QObject *obj;
25b70ce101SEric Blake     Visitor *qiv;
26d88f5fd1SLuiz Capitulino } TestInputVisitorData;
27d88f5fd1SLuiz Capitulino 
28d88f5fd1SLuiz Capitulino static void visitor_input_teardown(TestInputVisitorData *data,
29d88f5fd1SLuiz Capitulino                                    const void *unused)
30d88f5fd1SLuiz Capitulino {
31d88f5fd1SLuiz Capitulino     qobject_decref(data->obj);
32d88f5fd1SLuiz Capitulino     data->obj = NULL;
33d88f5fd1SLuiz Capitulino 
34d88f5fd1SLuiz Capitulino     if (data->qiv) {
35b70ce101SEric Blake         visit_free(data->qiv);
36d88f5fd1SLuiz Capitulino         data->qiv = NULL;
37d88f5fd1SLuiz Capitulino     }
38d88f5fd1SLuiz Capitulino }
39d88f5fd1SLuiz Capitulino 
400920a171SEric Blake /* The various test_init functions are provided instead of a test setup
410920a171SEric Blake    function so that the JSON string used by the tests are kept in the test
420920a171SEric Blake    functions (and not in main()). */
430920a171SEric Blake static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
440920a171SEric Blake                                                  const char *json_string,
450920a171SEric Blake                                                  va_list *ap)
460920a171SEric Blake {
47b18f1141SEric Blake     visitor_input_teardown(data, NULL);
48b18f1141SEric Blake 
490920a171SEric Blake     data->obj = qobject_from_jsonv(json_string, ap);
500920a171SEric Blake     g_assert(data->obj);
510920a171SEric Blake 
52fc471c18SEric Blake     data->qiv = qmp_input_visitor_new(data->obj, false);
530920a171SEric Blake     g_assert(data->qiv);
54b70ce101SEric Blake     return data->qiv;
550920a171SEric Blake }
560920a171SEric Blake 
57aba2107aSStefan Weil static GCC_FMT_ATTR(2, 3)
58aba2107aSStefan Weil Visitor *visitor_input_test_init(TestInputVisitorData *data,
59d88f5fd1SLuiz Capitulino                                  const char *json_string, ...)
60d88f5fd1SLuiz Capitulino {
61d88f5fd1SLuiz Capitulino     Visitor *v;
62d88f5fd1SLuiz Capitulino     va_list ap;
63d88f5fd1SLuiz Capitulino 
64d88f5fd1SLuiz Capitulino     va_start(ap, json_string);
650920a171SEric Blake     v = visitor_input_test_init_internal(data, json_string, &ap);
66d88f5fd1SLuiz Capitulino     va_end(ap);
67d88f5fd1SLuiz Capitulino     return v;
68d88f5fd1SLuiz Capitulino }
69d88f5fd1SLuiz Capitulino 
70199e0f17SMichael Roth /* similar to visitor_input_test_init(), but does not expect a string
71199e0f17SMichael Roth  * literal/format json_string argument and so can be used for
72199e0f17SMichael Roth  * programatically generated strings (and we can't pass in programatically
73199e0f17SMichael Roth  * generated strings via %s format parameters since qobject_from_jsonv()
74199e0f17SMichael Roth  * will wrap those in double-quotes and treat the entire object as a
75199e0f17SMichael Roth  * string)
76199e0f17SMichael Roth  */
77199e0f17SMichael Roth static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
78199e0f17SMichael Roth                                             const char *json_string)
79199e0f17SMichael Roth {
800920a171SEric Blake     return visitor_input_test_init_internal(data, json_string, NULL);
81199e0f17SMichael Roth }
82199e0f17SMichael Roth 
83d88f5fd1SLuiz Capitulino static void test_visitor_in_int(TestInputVisitorData *data,
84d88f5fd1SLuiz Capitulino                                 const void *unused)
85d88f5fd1SLuiz Capitulino {
86d88f5fd1SLuiz Capitulino     int64_t res = 0, value = -42;
87d88f5fd1SLuiz Capitulino     Visitor *v;
88d88f5fd1SLuiz Capitulino 
89aba2107aSStefan Weil     v = visitor_input_test_init(data, "%" PRId64, value);
90d88f5fd1SLuiz Capitulino 
9151e72bc1SEric Blake     visit_type_int(v, NULL, &res, &error_abort);
92d88f5fd1SLuiz Capitulino     g_assert_cmpint(res, ==, value);
93d88f5fd1SLuiz Capitulino }
94d88f5fd1SLuiz Capitulino 
95e92cfa0dSMichael Roth static void test_visitor_in_int_overflow(TestInputVisitorData *data,
96e92cfa0dSMichael Roth                                          const void *unused)
97e92cfa0dSMichael Roth {
98e92cfa0dSMichael Roth     int64_t res = 0;
99e940f543SMarkus Armbruster     Error *err = NULL;
100e92cfa0dSMichael Roth     Visitor *v;
101e92cfa0dSMichael Roth 
102e92cfa0dSMichael Roth     /* this will overflow a Qint/int64, so should be deserialized into
103e92cfa0dSMichael Roth      * a QFloat/double field instead, leading to an error if we pass it
104e92cfa0dSMichael Roth      * to visit_type_int. confirm this.
105e92cfa0dSMichael Roth      */
106e92cfa0dSMichael Roth     v = visitor_input_test_init(data, "%f", DBL_MAX);
107e92cfa0dSMichael Roth 
10851e72bc1SEric Blake     visit_type_int(v, NULL, &res, &err);
109a12a5a1aSEric Blake     error_free_or_abort(&err);
110e92cfa0dSMichael Roth }
111e92cfa0dSMichael Roth 
112d88f5fd1SLuiz Capitulino static void test_visitor_in_bool(TestInputVisitorData *data,
113d88f5fd1SLuiz Capitulino                                  const void *unused)
114d88f5fd1SLuiz Capitulino {
115d88f5fd1SLuiz Capitulino     bool res = false;
116d88f5fd1SLuiz Capitulino     Visitor *v;
117d88f5fd1SLuiz Capitulino 
118d88f5fd1SLuiz Capitulino     v = visitor_input_test_init(data, "true");
119d88f5fd1SLuiz Capitulino 
12051e72bc1SEric Blake     visit_type_bool(v, NULL, &res, &error_abort);
121d88f5fd1SLuiz Capitulino     g_assert_cmpint(res, ==, true);
122d88f5fd1SLuiz Capitulino }
123d88f5fd1SLuiz Capitulino 
124d88f5fd1SLuiz Capitulino static void test_visitor_in_number(TestInputVisitorData *data,
125d88f5fd1SLuiz Capitulino                                    const void *unused)
126d88f5fd1SLuiz Capitulino {
127d88f5fd1SLuiz Capitulino     double res = 0, value = 3.14;
128d88f5fd1SLuiz Capitulino     Visitor *v;
129d88f5fd1SLuiz Capitulino 
130d88f5fd1SLuiz Capitulino     v = visitor_input_test_init(data, "%f", value);
131d88f5fd1SLuiz Capitulino 
13251e72bc1SEric Blake     visit_type_number(v, NULL, &res, &error_abort);
133d88f5fd1SLuiz Capitulino     g_assert_cmpfloat(res, ==, value);
134d88f5fd1SLuiz Capitulino }
135d88f5fd1SLuiz Capitulino 
136d88f5fd1SLuiz Capitulino static void test_visitor_in_string(TestInputVisitorData *data,
137d88f5fd1SLuiz Capitulino                                    const void *unused)
138d88f5fd1SLuiz Capitulino {
139d88f5fd1SLuiz Capitulino     char *res = NULL, *value = (char *) "Q E M U";
140d88f5fd1SLuiz Capitulino     Visitor *v;
141d88f5fd1SLuiz Capitulino 
142d88f5fd1SLuiz Capitulino     v = visitor_input_test_init(data, "%s", value);
143d88f5fd1SLuiz Capitulino 
14451e72bc1SEric Blake     visit_type_str(v, NULL, &res, &error_abort);
145d88f5fd1SLuiz Capitulino     g_assert_cmpstr(res, ==, value);
146d88f5fd1SLuiz Capitulino 
147d88f5fd1SLuiz Capitulino     g_free(res);
148d88f5fd1SLuiz Capitulino }
149d88f5fd1SLuiz Capitulino 
150d88f5fd1SLuiz Capitulino static void test_visitor_in_enum(TestInputVisitorData *data,
151d88f5fd1SLuiz Capitulino                                  const void *unused)
152d88f5fd1SLuiz Capitulino {
153d88f5fd1SLuiz Capitulino     Visitor *v;
154d88f5fd1SLuiz Capitulino     EnumOne i;
155d88f5fd1SLuiz Capitulino 
156d88f5fd1SLuiz Capitulino     for (i = 0; EnumOne_lookup[i]; i++) {
157d88f5fd1SLuiz Capitulino         EnumOne res = -1;
158d88f5fd1SLuiz Capitulino 
159d88f5fd1SLuiz Capitulino         v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
160d88f5fd1SLuiz Capitulino 
16151e72bc1SEric Blake         visit_type_EnumOne(v, NULL, &res, &error_abort);
162d88f5fd1SLuiz Capitulino         g_assert_cmpint(i, ==, res);
163d88f5fd1SLuiz Capitulino     }
164d88f5fd1SLuiz Capitulino }
165d88f5fd1SLuiz Capitulino 
166d88f5fd1SLuiz Capitulino 
167d88f5fd1SLuiz Capitulino static void test_visitor_in_struct(TestInputVisitorData *data,
168d88f5fd1SLuiz Capitulino                                    const void *unused)
169d88f5fd1SLuiz Capitulino {
170d88f5fd1SLuiz Capitulino     TestStruct *p = NULL;
171d88f5fd1SLuiz Capitulino     Visitor *v;
172d88f5fd1SLuiz Capitulino 
173d88f5fd1SLuiz Capitulino     v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
174d88f5fd1SLuiz Capitulino 
17551e72bc1SEric Blake     visit_type_TestStruct(v, NULL, &p, &error_abort);
176d88f5fd1SLuiz Capitulino     g_assert_cmpint(p->integer, ==, -42);
177d88f5fd1SLuiz Capitulino     g_assert(p->boolean == true);
178d88f5fd1SLuiz Capitulino     g_assert_cmpstr(p->string, ==, "foo");
179d88f5fd1SLuiz Capitulino 
180d88f5fd1SLuiz Capitulino     g_free(p->string);
181d88f5fd1SLuiz Capitulino     g_free(p);
182d88f5fd1SLuiz Capitulino }
183d88f5fd1SLuiz Capitulino 
184d88f5fd1SLuiz Capitulino static void test_visitor_in_struct_nested(TestInputVisitorData *data,
185d88f5fd1SLuiz Capitulino                                           const void *unused)
186d88f5fd1SLuiz Capitulino {
187b6fcf32dSEric Blake     UserDefTwo *udp = NULL;
188d88f5fd1SLuiz Capitulino     Visitor *v;
189d88f5fd1SLuiz Capitulino 
190b6fcf32dSEric Blake     v = visitor_input_test_init(data, "{ 'string0': 'string0', "
191b6fcf32dSEric Blake                                 "'dict1': { 'string1': 'string1', "
192b6fcf32dSEric Blake                                 "'dict2': { 'userdef': { 'integer': 42, "
193b6fcf32dSEric Blake                                 "'string': 'string' }, 'string': 'string2'}}}");
194d88f5fd1SLuiz Capitulino 
19551e72bc1SEric Blake     visit_type_UserDefTwo(v, NULL, &udp, &error_abort);
196d88f5fd1SLuiz Capitulino 
197b18f1141SEric Blake     g_assert_cmpstr(udp->string0, ==, "string0");
198b18f1141SEric Blake     g_assert_cmpstr(udp->dict1->string1, ==, "string1");
199ddf21908SEric Blake     g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
200b18f1141SEric Blake     g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
201b18f1141SEric Blake     g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
2026446a592SEric Blake     g_assert(udp->dict1->has_dict3 == false);
203d88f5fd1SLuiz Capitulino 
204b18f1141SEric Blake     qapi_free_UserDefTwo(udp);
205d88f5fd1SLuiz Capitulino }
206d88f5fd1SLuiz Capitulino 
207d88f5fd1SLuiz Capitulino static void test_visitor_in_list(TestInputVisitorData *data,
208d88f5fd1SLuiz Capitulino                                  const void *unused)
209d88f5fd1SLuiz Capitulino {
210d88f5fd1SLuiz Capitulino     UserDefOneList *item, *head = NULL;
211d88f5fd1SLuiz Capitulino     Visitor *v;
212d88f5fd1SLuiz Capitulino     int i;
213d88f5fd1SLuiz Capitulino 
214d88f5fd1SLuiz Capitulino     v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
215d88f5fd1SLuiz Capitulino 
21651e72bc1SEric Blake     visit_type_UserDefOneList(v, NULL, &head, &error_abort);
217d88f5fd1SLuiz Capitulino     g_assert(head != NULL);
218d88f5fd1SLuiz Capitulino 
219d88f5fd1SLuiz Capitulino     for (i = 0, item = head; item; item = item->next, i++) {
220d88f5fd1SLuiz Capitulino         char string[12];
221d88f5fd1SLuiz Capitulino 
222d88f5fd1SLuiz Capitulino         snprintf(string, sizeof(string), "string%d", i);
223d88f5fd1SLuiz Capitulino         g_assert_cmpstr(item->value->string, ==, string);
224ddf21908SEric Blake         g_assert_cmpint(item->value->integer, ==, 42 + i);
225d88f5fd1SLuiz Capitulino     }
226d88f5fd1SLuiz Capitulino 
227d88f5fd1SLuiz Capitulino     qapi_free_UserDefOneList(head);
2282533377cSEric Blake     head = NULL;
2292533377cSEric Blake 
2302533377cSEric Blake     /* An empty list is valid */
2312533377cSEric Blake     v = visitor_input_test_init(data, "[]");
23251e72bc1SEric Blake     visit_type_UserDefOneList(v, NULL, &head, &error_abort);
2332533377cSEric Blake     g_assert(!head);
234d88f5fd1SLuiz Capitulino }
235d88f5fd1SLuiz Capitulino 
23628770e05SMarkus Armbruster static void test_visitor_in_any(TestInputVisitorData *data,
23728770e05SMarkus Armbruster                                 const void *unused)
23828770e05SMarkus Armbruster {
23928770e05SMarkus Armbruster     QObject *res = NULL;
24028770e05SMarkus Armbruster     Visitor *v;
24128770e05SMarkus Armbruster     QInt *qint;
24228770e05SMarkus Armbruster     QBool *qbool;
24328770e05SMarkus Armbruster     QString *qstring;
24428770e05SMarkus Armbruster     QDict *qdict;
24528770e05SMarkus Armbruster     QObject *qobj;
24628770e05SMarkus Armbruster 
24728770e05SMarkus Armbruster     v = visitor_input_test_init(data, "-42");
24851e72bc1SEric Blake     visit_type_any(v, NULL, &res, &error_abort);
24928770e05SMarkus Armbruster     qint = qobject_to_qint(res);
25028770e05SMarkus Armbruster     g_assert(qint);
25128770e05SMarkus Armbruster     g_assert_cmpint(qint_get_int(qint), ==, -42);
25228770e05SMarkus Armbruster     qobject_decref(res);
25328770e05SMarkus Armbruster 
25428770e05SMarkus Armbruster     v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
25551e72bc1SEric Blake     visit_type_any(v, NULL, &res, &error_abort);
25628770e05SMarkus Armbruster     qdict = qobject_to_qdict(res);
25728770e05SMarkus Armbruster     g_assert(qdict && qdict_size(qdict) == 3);
25828770e05SMarkus Armbruster     qobj = qdict_get(qdict, "integer");
25928770e05SMarkus Armbruster     g_assert(qobj);
26028770e05SMarkus Armbruster     qint = qobject_to_qint(qobj);
26128770e05SMarkus Armbruster     g_assert(qint);
26228770e05SMarkus Armbruster     g_assert_cmpint(qint_get_int(qint), ==, -42);
26328770e05SMarkus Armbruster     qobj = qdict_get(qdict, "boolean");
26428770e05SMarkus Armbruster     g_assert(qobj);
26528770e05SMarkus Armbruster     qbool = qobject_to_qbool(qobj);
26628770e05SMarkus Armbruster     g_assert(qbool);
26728770e05SMarkus Armbruster     g_assert(qbool_get_bool(qbool) == true);
26828770e05SMarkus Armbruster     qobj = qdict_get(qdict, "string");
26928770e05SMarkus Armbruster     g_assert(qobj);
27028770e05SMarkus Armbruster     qstring = qobject_to_qstring(qobj);
27128770e05SMarkus Armbruster     g_assert(qstring);
27228770e05SMarkus Armbruster     g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
27328770e05SMarkus Armbruster     qobject_decref(res);
27428770e05SMarkus Armbruster }
27528770e05SMarkus Armbruster 
2763df016f1SEric Blake static void test_visitor_in_null(TestInputVisitorData *data,
2773df016f1SEric Blake                                  const void *unused)
2783df016f1SEric Blake {
2793df016f1SEric Blake     Visitor *v;
2803df016f1SEric Blake     Error *err = NULL;
2813df016f1SEric Blake     char *tmp;
2823df016f1SEric Blake 
2833df016f1SEric Blake     /*
2843df016f1SEric Blake      * FIXME: Since QAPI doesn't know the 'null' type yet, we can't
2853df016f1SEric Blake      * test visit_type_null() by reading into a QAPI struct then
2863df016f1SEric Blake      * checking that it was populated correctly.  The best we can do
2873df016f1SEric Blake      * for now is ensure that we consumed null from the input, proven
2883df016f1SEric Blake      * by the fact that we can't re-read the key; and that we detect
2893df016f1SEric Blake      * when input is not null.
2903df016f1SEric Blake      */
2913df016f1SEric Blake 
2923df016f1SEric Blake     v = visitor_input_test_init(data, "{ 'a': null, 'b': '' }");
2933df016f1SEric Blake     visit_start_struct(v, NULL, NULL, 0, &error_abort);
2943df016f1SEric Blake     visit_type_null(v, "a", &error_abort);
2953df016f1SEric Blake     visit_type_str(v, "a", &tmp, &err);
2963df016f1SEric Blake     g_assert(!tmp);
2973df016f1SEric Blake     error_free_or_abort(&err);
2983df016f1SEric Blake     visit_type_null(v, "b", &err);
2993df016f1SEric Blake     error_free_or_abort(&err);
30015c2f669SEric Blake     visit_check_struct(v, &error_abort);
3011158bb2aSEric Blake     visit_end_struct(v, NULL);
3023df016f1SEric Blake }
3033df016f1SEric Blake 
3042fc00432SMarkus Armbruster static void test_visitor_in_union_flat(TestInputVisitorData *data,
3052fc00432SMarkus Armbruster                                        const void *unused)
3062fc00432SMarkus Armbruster {
3072fc00432SMarkus Armbruster     Visitor *v;
3082fc00432SMarkus Armbruster     UserDefFlatUnion *tmp;
30930594fe1SEric Blake     UserDefUnionBase *base;
3102fc00432SMarkus Armbruster 
3115223070cSWenchao Xia     v = visitor_input_test_init(data,
3125223070cSWenchao Xia                                 "{ 'enum1': 'value1', "
313441cbac0SMarkus Armbruster                                 "'integer': 41, "
3145223070cSWenchao Xia                                 "'string': 'str', "
3155223070cSWenchao Xia                                 "'boolean': true }");
3162fc00432SMarkus Armbruster 
31751e72bc1SEric Blake     visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
3180f61af3eSMarkus Armbruster     g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
3195223070cSWenchao Xia     g_assert_cmpstr(tmp->string, ==, "str");
320441cbac0SMarkus Armbruster     g_assert_cmpint(tmp->integer, ==, 41);
321544a3731SEric Blake     g_assert_cmpint(tmp->u.value1.boolean, ==, true);
32230594fe1SEric Blake 
32330594fe1SEric Blake     base = qapi_UserDefFlatUnion_base(tmp);
32430594fe1SEric Blake     g_assert(&base->enum1 == &tmp->enum1);
32530594fe1SEric Blake 
3262fc00432SMarkus Armbruster     qapi_free_UserDefFlatUnion(tmp);
3272fc00432SMarkus Armbruster }
3282fc00432SMarkus Armbruster 
329ab045267SEric Blake static void test_visitor_in_alternate(TestInputVisitorData *data,
3302c38b600SMarkus Armbruster                                       const void *unused)
3312c38b600SMarkus Armbruster {
3322c38b600SMarkus Armbruster     Visitor *v;
3332c38b600SMarkus Armbruster     Error *err = NULL;
334ab045267SEric Blake     UserDefAlternate *tmp;
33568d07839SEric Blake     WrapAlternate *wrap;
3362c38b600SMarkus Armbruster 
3372c38b600SMarkus Armbruster     v = visitor_input_test_init(data, "42");
33851e72bc1SEric Blake     visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
3390426d53cSEric Blake     g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
340c363acefSEric Blake     g_assert_cmpint(tmp->u.i, ==, 42);
341ab045267SEric Blake     qapi_free_UserDefAlternate(tmp);
3429c51b441SEric Blake 
3439c51b441SEric Blake     v = visitor_input_test_init(data, "'string'");
34451e72bc1SEric Blake     visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
3450426d53cSEric Blake     g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
346c363acefSEric Blake     g_assert_cmpstr(tmp->u.s, ==, "string");
3479c51b441SEric Blake     qapi_free_UserDefAlternate(tmp);
3489c51b441SEric Blake 
34968d07839SEric Blake     v = visitor_input_test_init(data, "{'integer':1, 'string':'str', "
35068d07839SEric Blake                                 "'enum1':'value1', 'boolean':true}");
35168d07839SEric Blake     visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
35268d07839SEric Blake     g_assert_cmpint(tmp->type, ==, QTYPE_QDICT);
353becceedcSEric Blake     g_assert_cmpint(tmp->u.udfu.integer, ==, 1);
354becceedcSEric Blake     g_assert_cmpstr(tmp->u.udfu.string, ==, "str");
355becceedcSEric Blake     g_assert_cmpint(tmp->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
356544a3731SEric Blake     g_assert_cmpint(tmp->u.udfu.u.value1.boolean, ==, true);
357544a3731SEric Blake     g_assert_cmpint(tmp->u.udfu.u.value1.has_a_b, ==, false);
35868d07839SEric Blake     qapi_free_UserDefAlternate(tmp);
35968d07839SEric Blake 
3609c51b441SEric Blake     v = visitor_input_test_init(data, "false");
36151e72bc1SEric Blake     visit_type_UserDefAlternate(v, NULL, &tmp, &err);
362a12a5a1aSEric Blake     error_free_or_abort(&err);
3639c51b441SEric Blake     qapi_free_UserDefAlternate(tmp);
36468d07839SEric Blake 
36568d07839SEric Blake     v = visitor_input_test_init(data, "{ 'alt': 42 }");
36668d07839SEric Blake     visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
36768d07839SEric Blake     g_assert_cmpint(wrap->alt->type, ==, QTYPE_QINT);
36868d07839SEric Blake     g_assert_cmpint(wrap->alt->u.i, ==, 42);
36968d07839SEric Blake     qapi_free_WrapAlternate(wrap);
37068d07839SEric Blake 
37168d07839SEric Blake     v = visitor_input_test_init(data, "{ 'alt': 'string' }");
37268d07839SEric Blake     visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
37368d07839SEric Blake     g_assert_cmpint(wrap->alt->type, ==, QTYPE_QSTRING);
37468d07839SEric Blake     g_assert_cmpstr(wrap->alt->u.s, ==, "string");
37568d07839SEric Blake     qapi_free_WrapAlternate(wrap);
37668d07839SEric Blake 
37768d07839SEric Blake     v = visitor_input_test_init(data, "{ 'alt': {'integer':1, 'string':'str', "
37868d07839SEric Blake                                 "'enum1':'value1', 'boolean':true} }");
37968d07839SEric Blake     visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
38068d07839SEric Blake     g_assert_cmpint(wrap->alt->type, ==, QTYPE_QDICT);
381becceedcSEric Blake     g_assert_cmpint(wrap->alt->u.udfu.integer, ==, 1);
382becceedcSEric Blake     g_assert_cmpstr(wrap->alt->u.udfu.string, ==, "str");
383becceedcSEric Blake     g_assert_cmpint(wrap->alt->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
384544a3731SEric Blake     g_assert_cmpint(wrap->alt->u.udfu.u.value1.boolean, ==, true);
385544a3731SEric Blake     g_assert_cmpint(wrap->alt->u.udfu.u.value1.has_a_b, ==, false);
38668d07839SEric Blake     qapi_free_WrapAlternate(wrap);
3879c51b441SEric Blake }
3889c51b441SEric Blake 
3899c51b441SEric Blake static void test_visitor_in_alternate_number(TestInputVisitorData *data,
3909c51b441SEric Blake                                              const void *unused)
3919c51b441SEric Blake {
3929c51b441SEric Blake     Visitor *v;
3939c51b441SEric Blake     Error *err = NULL;
3949c51b441SEric Blake     AltStrBool *asb;
3959c51b441SEric Blake     AltStrNum *asn;
3969c51b441SEric Blake     AltNumStr *ans;
3979c51b441SEric Blake     AltStrInt *asi;
3989c51b441SEric Blake     AltIntNum *ain;
3999c51b441SEric Blake     AltNumInt *ani;
4009c51b441SEric Blake 
4019c51b441SEric Blake     /* Parsing an int */
4029c51b441SEric Blake 
4039c51b441SEric Blake     v = visitor_input_test_init(data, "42");
40451e72bc1SEric Blake     visit_type_AltStrBool(v, NULL, &asb, &err);
405a12a5a1aSEric Blake     error_free_or_abort(&err);
4069c51b441SEric Blake     qapi_free_AltStrBool(asb);
4079c51b441SEric Blake 
4089c51b441SEric Blake     v = visitor_input_test_init(data, "42");
40951e72bc1SEric Blake     visit_type_AltStrNum(v, NULL, &asn, &error_abort);
410d00341afSEric Blake     g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
411d00341afSEric Blake     g_assert_cmpfloat(asn->u.n, ==, 42);
4129c51b441SEric Blake     qapi_free_AltStrNum(asn);
4139c51b441SEric Blake 
4149c51b441SEric Blake     v = visitor_input_test_init(data, "42");
41551e72bc1SEric Blake     visit_type_AltNumStr(v, NULL, &ans, &error_abort);
416d00341afSEric Blake     g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
417d00341afSEric Blake     g_assert_cmpfloat(ans->u.n, ==, 42);
4189c51b441SEric Blake     qapi_free_AltNumStr(ans);
4199c51b441SEric Blake 
4209c51b441SEric Blake     v = visitor_input_test_init(data, "42");
42151e72bc1SEric Blake     visit_type_AltStrInt(v, NULL, &asi, &error_abort);
4220426d53cSEric Blake     g_assert_cmpint(asi->type, ==, QTYPE_QINT);
423c363acefSEric Blake     g_assert_cmpint(asi->u.i, ==, 42);
4249c51b441SEric Blake     qapi_free_AltStrInt(asi);
4259c51b441SEric Blake 
4269c51b441SEric Blake     v = visitor_input_test_init(data, "42");
42751e72bc1SEric Blake     visit_type_AltIntNum(v, NULL, &ain, &error_abort);
4280426d53cSEric Blake     g_assert_cmpint(ain->type, ==, QTYPE_QINT);
429c363acefSEric Blake     g_assert_cmpint(ain->u.i, ==, 42);
4309c51b441SEric Blake     qapi_free_AltIntNum(ain);
4319c51b441SEric Blake 
4329c51b441SEric Blake     v = visitor_input_test_init(data, "42");
43351e72bc1SEric Blake     visit_type_AltNumInt(v, NULL, &ani, &error_abort);
4340426d53cSEric Blake     g_assert_cmpint(ani->type, ==, QTYPE_QINT);
435c363acefSEric Blake     g_assert_cmpint(ani->u.i, ==, 42);
4369c51b441SEric Blake     qapi_free_AltNumInt(ani);
4379c51b441SEric Blake 
4389c51b441SEric Blake     /* Parsing a double */
4399c51b441SEric Blake 
4409c51b441SEric Blake     v = visitor_input_test_init(data, "42.5");
44151e72bc1SEric Blake     visit_type_AltStrBool(v, NULL, &asb, &err);
442a12a5a1aSEric Blake     error_free_or_abort(&err);
4439c51b441SEric Blake     qapi_free_AltStrBool(asb);
4449c51b441SEric Blake 
4459c51b441SEric Blake     v = visitor_input_test_init(data, "42.5");
44651e72bc1SEric Blake     visit_type_AltStrNum(v, NULL, &asn, &error_abort);
4470426d53cSEric Blake     g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
448c363acefSEric Blake     g_assert_cmpfloat(asn->u.n, ==, 42.5);
4499c51b441SEric Blake     qapi_free_AltStrNum(asn);
4509c51b441SEric Blake 
4519c51b441SEric Blake     v = visitor_input_test_init(data, "42.5");
45251e72bc1SEric Blake     visit_type_AltNumStr(v, NULL, &ans, &error_abort);
4530426d53cSEric Blake     g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
454c363acefSEric Blake     g_assert_cmpfloat(ans->u.n, ==, 42.5);
4559c51b441SEric Blake     qapi_free_AltNumStr(ans);
4569c51b441SEric Blake 
4579c51b441SEric Blake     v = visitor_input_test_init(data, "42.5");
45851e72bc1SEric Blake     visit_type_AltStrInt(v, NULL, &asi, &err);
459a12a5a1aSEric Blake     error_free_or_abort(&err);
4609c51b441SEric Blake     qapi_free_AltStrInt(asi);
4619c51b441SEric Blake 
4629c51b441SEric Blake     v = visitor_input_test_init(data, "42.5");
46351e72bc1SEric Blake     visit_type_AltIntNum(v, NULL, &ain, &error_abort);
4640426d53cSEric Blake     g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT);
465c363acefSEric Blake     g_assert_cmpfloat(ain->u.n, ==, 42.5);
4669c51b441SEric Blake     qapi_free_AltIntNum(ain);
4679c51b441SEric Blake 
4689c51b441SEric Blake     v = visitor_input_test_init(data, "42.5");
46951e72bc1SEric Blake     visit_type_AltNumInt(v, NULL, &ani, &error_abort);
4700426d53cSEric Blake     g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT);
471c363acefSEric Blake     g_assert_cmpfloat(ani->u.n, ==, 42.5);
4729c51b441SEric Blake     qapi_free_AltNumInt(ani);
4732c38b600SMarkus Armbruster }
4742c38b600SMarkus Armbruster 
475199e0f17SMichael Roth static void test_native_list_integer_helper(TestInputVisitorData *data,
476199e0f17SMichael Roth                                             const void *unused,
477199e0f17SMichael Roth                                             UserDefNativeListUnionKind kind)
478199e0f17SMichael Roth {
479199e0f17SMichael Roth     UserDefNativeListUnion *cvalue = NULL;
480199e0f17SMichael Roth     Visitor *v;
481199e0f17SMichael Roth     GString *gstr_list = g_string_new("");
482199e0f17SMichael Roth     GString *gstr_union = g_string_new("");
483199e0f17SMichael Roth     int i;
484199e0f17SMichael Roth 
485199e0f17SMichael Roth     for (i = 0; i < 32; i++) {
486199e0f17SMichael Roth         g_string_append_printf(gstr_list, "%d", i);
487199e0f17SMichael Roth         if (i != 31) {
488199e0f17SMichael Roth             g_string_append(gstr_list, ", ");
489199e0f17SMichael Roth         }
490199e0f17SMichael Roth     }
491199e0f17SMichael Roth     g_string_append_printf(gstr_union,  "{ 'type': '%s', 'data': [ %s ] }",
492199e0f17SMichael Roth                            UserDefNativeListUnionKind_lookup[kind],
493199e0f17SMichael Roth                            gstr_list->str);
494199e0f17SMichael Roth     v = visitor_input_test_init_raw(data,  gstr_union->str);
495199e0f17SMichael Roth 
49651e72bc1SEric Blake     visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
497199e0f17SMichael Roth     g_assert(cvalue != NULL);
498c363acefSEric Blake     g_assert_cmpint(cvalue->type, ==, kind);
499199e0f17SMichael Roth 
500199e0f17SMichael Roth     switch (kind) {
501199e0f17SMichael Roth     case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
502199e0f17SMichael Roth         intList *elem = NULL;
50332bafa8fSEric Blake         for (i = 0, elem = cvalue->u.integer.data;
50432bafa8fSEric Blake              elem; elem = elem->next, i++) {
505199e0f17SMichael Roth             g_assert_cmpint(elem->value, ==, i);
506199e0f17SMichael Roth         }
507199e0f17SMichael Roth         break;
508199e0f17SMichael Roth     }
509199e0f17SMichael Roth     case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
510199e0f17SMichael Roth         int8List *elem = NULL;
51132bafa8fSEric Blake         for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) {
512199e0f17SMichael Roth             g_assert_cmpint(elem->value, ==, i);
513199e0f17SMichael Roth         }
514199e0f17SMichael Roth         break;
515199e0f17SMichael Roth     }
516199e0f17SMichael Roth     case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
517199e0f17SMichael Roth         int16List *elem = NULL;
51832bafa8fSEric Blake         for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) {
519199e0f17SMichael Roth             g_assert_cmpint(elem->value, ==, i);
520199e0f17SMichael Roth         }
521199e0f17SMichael Roth         break;
522199e0f17SMichael Roth     }
523199e0f17SMichael Roth     case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
524199e0f17SMichael Roth         int32List *elem = NULL;
52532bafa8fSEric Blake         for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) {
526199e0f17SMichael Roth             g_assert_cmpint(elem->value, ==, i);
527199e0f17SMichael Roth         }
528199e0f17SMichael Roth         break;
529199e0f17SMichael Roth     }
530199e0f17SMichael Roth     case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
531199e0f17SMichael Roth         int64List *elem = NULL;
53232bafa8fSEric Blake         for (i = 0, elem = cvalue->u.s64.data; elem; elem = elem->next, i++) {
533199e0f17SMichael Roth             g_assert_cmpint(elem->value, ==, i);
534199e0f17SMichael Roth         }
535199e0f17SMichael Roth         break;
536199e0f17SMichael Roth     }
537199e0f17SMichael Roth     case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
538199e0f17SMichael Roth         uint8List *elem = NULL;
53932bafa8fSEric Blake         for (i = 0, elem = cvalue->u.u8.data; elem; elem = elem->next, i++) {
540199e0f17SMichael Roth             g_assert_cmpint(elem->value, ==, i);
541199e0f17SMichael Roth         }
542199e0f17SMichael Roth         break;
543199e0f17SMichael Roth     }
544199e0f17SMichael Roth     case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
545199e0f17SMichael Roth         uint16List *elem = NULL;
54632bafa8fSEric Blake         for (i = 0, elem = cvalue->u.u16.data; elem; elem = elem->next, i++) {
547199e0f17SMichael Roth             g_assert_cmpint(elem->value, ==, i);
548199e0f17SMichael Roth         }
549199e0f17SMichael Roth         break;
550199e0f17SMichael Roth     }
551199e0f17SMichael Roth     case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
552199e0f17SMichael Roth         uint32List *elem = NULL;
55332bafa8fSEric Blake         for (i = 0, elem = cvalue->u.u32.data; elem; elem = elem->next, i++) {
554199e0f17SMichael Roth             g_assert_cmpint(elem->value, ==, i);
555199e0f17SMichael Roth         }
556199e0f17SMichael Roth         break;
557199e0f17SMichael Roth     }
558199e0f17SMichael Roth     case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
559199e0f17SMichael Roth         uint64List *elem = NULL;
56032bafa8fSEric Blake         for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) {
561199e0f17SMichael Roth             g_assert_cmpint(elem->value, ==, i);
562199e0f17SMichael Roth         }
563199e0f17SMichael Roth         break;
564199e0f17SMichael Roth     }
565199e0f17SMichael Roth     default:
566dfc6f865SStefan Weil         g_assert_not_reached();
567199e0f17SMichael Roth     }
568199e0f17SMichael Roth 
569199e0f17SMichael Roth     g_string_free(gstr_union, true);
570199e0f17SMichael Roth     g_string_free(gstr_list, true);
571199e0f17SMichael Roth     qapi_free_UserDefNativeListUnion(cvalue);
572199e0f17SMichael Roth }
573199e0f17SMichael Roth 
574199e0f17SMichael Roth static void test_visitor_in_native_list_int(TestInputVisitorData *data,
575199e0f17SMichael Roth                                             const void *unused)
576199e0f17SMichael Roth {
577199e0f17SMichael Roth     test_native_list_integer_helper(data, unused,
578199e0f17SMichael Roth                                     USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
579199e0f17SMichael Roth }
580199e0f17SMichael Roth 
581199e0f17SMichael Roth static void test_visitor_in_native_list_int8(TestInputVisitorData *data,
582199e0f17SMichael Roth                                              const void *unused)
583199e0f17SMichael Roth {
584199e0f17SMichael Roth     test_native_list_integer_helper(data, unused,
585199e0f17SMichael Roth                                     USER_DEF_NATIVE_LIST_UNION_KIND_S8);
586199e0f17SMichael Roth }
587199e0f17SMichael Roth 
588199e0f17SMichael Roth static void test_visitor_in_native_list_int16(TestInputVisitorData *data,
589199e0f17SMichael Roth                                               const void *unused)
590199e0f17SMichael Roth {
591199e0f17SMichael Roth     test_native_list_integer_helper(data, unused,
592199e0f17SMichael Roth                                     USER_DEF_NATIVE_LIST_UNION_KIND_S16);
593199e0f17SMichael Roth }
594199e0f17SMichael Roth 
595199e0f17SMichael Roth static void test_visitor_in_native_list_int32(TestInputVisitorData *data,
596199e0f17SMichael Roth                                               const void *unused)
597199e0f17SMichael Roth {
598199e0f17SMichael Roth     test_native_list_integer_helper(data, unused,
599199e0f17SMichael Roth                                     USER_DEF_NATIVE_LIST_UNION_KIND_S32);
600199e0f17SMichael Roth }
601199e0f17SMichael Roth 
602199e0f17SMichael Roth static void test_visitor_in_native_list_int64(TestInputVisitorData *data,
603199e0f17SMichael Roth                                               const void *unused)
604199e0f17SMichael Roth {
605199e0f17SMichael Roth     test_native_list_integer_helper(data, unused,
606199e0f17SMichael Roth                                     USER_DEF_NATIVE_LIST_UNION_KIND_S64);
607199e0f17SMichael Roth }
608199e0f17SMichael Roth 
609199e0f17SMichael Roth static void test_visitor_in_native_list_uint8(TestInputVisitorData *data,
610199e0f17SMichael Roth                                              const void *unused)
611199e0f17SMichael Roth {
612199e0f17SMichael Roth     test_native_list_integer_helper(data, unused,
613199e0f17SMichael Roth                                     USER_DEF_NATIVE_LIST_UNION_KIND_U8);
614199e0f17SMichael Roth }
615199e0f17SMichael Roth 
616199e0f17SMichael Roth static void test_visitor_in_native_list_uint16(TestInputVisitorData *data,
617199e0f17SMichael Roth                                                const void *unused)
618199e0f17SMichael Roth {
619199e0f17SMichael Roth     test_native_list_integer_helper(data, unused,
620199e0f17SMichael Roth                                     USER_DEF_NATIVE_LIST_UNION_KIND_U16);
621199e0f17SMichael Roth }
622199e0f17SMichael Roth 
623199e0f17SMichael Roth static void test_visitor_in_native_list_uint32(TestInputVisitorData *data,
624199e0f17SMichael Roth                                                const void *unused)
625199e0f17SMichael Roth {
626199e0f17SMichael Roth     test_native_list_integer_helper(data, unused,
627199e0f17SMichael Roth                                     USER_DEF_NATIVE_LIST_UNION_KIND_U32);
628199e0f17SMichael Roth }
629199e0f17SMichael Roth 
630199e0f17SMichael Roth static void test_visitor_in_native_list_uint64(TestInputVisitorData *data,
631199e0f17SMichael Roth                                                const void *unused)
632199e0f17SMichael Roth {
633199e0f17SMichael Roth     test_native_list_integer_helper(data, unused,
634199e0f17SMichael Roth                                     USER_DEF_NATIVE_LIST_UNION_KIND_U64);
635199e0f17SMichael Roth }
636199e0f17SMichael Roth 
637199e0f17SMichael Roth static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
638199e0f17SMichael Roth                                             const void *unused)
639199e0f17SMichael Roth {
640199e0f17SMichael Roth     UserDefNativeListUnion *cvalue = NULL;
641199e0f17SMichael Roth     boolList *elem = NULL;
642199e0f17SMichael Roth     Visitor *v;
643199e0f17SMichael Roth     GString *gstr_list = g_string_new("");
644199e0f17SMichael Roth     GString *gstr_union = g_string_new("");
645199e0f17SMichael Roth     int i;
646199e0f17SMichael Roth 
647199e0f17SMichael Roth     for (i = 0; i < 32; i++) {
648199e0f17SMichael Roth         g_string_append_printf(gstr_list, "%s",
649199e0f17SMichael Roth                                (i % 3 == 0) ? "true" : "false");
650199e0f17SMichael Roth         if (i != 31) {
651199e0f17SMichael Roth             g_string_append(gstr_list, ", ");
652199e0f17SMichael Roth         }
653199e0f17SMichael Roth     }
654199e0f17SMichael Roth     g_string_append_printf(gstr_union,  "{ 'type': 'boolean', 'data': [ %s ] }",
655199e0f17SMichael Roth                            gstr_list->str);
656199e0f17SMichael Roth     v = visitor_input_test_init_raw(data,  gstr_union->str);
657199e0f17SMichael Roth 
65851e72bc1SEric Blake     visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
659199e0f17SMichael Roth     g_assert(cvalue != NULL);
660c363acefSEric Blake     g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
661199e0f17SMichael Roth 
66232bafa8fSEric Blake     for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next, i++) {
663199e0f17SMichael Roth         g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
664199e0f17SMichael Roth     }
665199e0f17SMichael Roth 
666199e0f17SMichael Roth     g_string_free(gstr_union, true);
667199e0f17SMichael Roth     g_string_free(gstr_list, true);
668199e0f17SMichael Roth     qapi_free_UserDefNativeListUnion(cvalue);
669199e0f17SMichael Roth }
670199e0f17SMichael Roth 
671199e0f17SMichael Roth static void test_visitor_in_native_list_string(TestInputVisitorData *data,
672199e0f17SMichael Roth                                                const void *unused)
673199e0f17SMichael Roth {
674199e0f17SMichael Roth     UserDefNativeListUnion *cvalue = NULL;
675199e0f17SMichael Roth     strList *elem = NULL;
676199e0f17SMichael Roth     Visitor *v;
677199e0f17SMichael Roth     GString *gstr_list = g_string_new("");
678199e0f17SMichael Roth     GString *gstr_union = g_string_new("");
679199e0f17SMichael Roth     int i;
680199e0f17SMichael Roth 
681199e0f17SMichael Roth     for (i = 0; i < 32; i++) {
682199e0f17SMichael Roth         g_string_append_printf(gstr_list, "'%d'", i);
683199e0f17SMichael Roth         if (i != 31) {
684199e0f17SMichael Roth             g_string_append(gstr_list, ", ");
685199e0f17SMichael Roth         }
686199e0f17SMichael Roth     }
687199e0f17SMichael Roth     g_string_append_printf(gstr_union,  "{ 'type': 'string', 'data': [ %s ] }",
688199e0f17SMichael Roth                            gstr_list->str);
689199e0f17SMichael Roth     v = visitor_input_test_init_raw(data,  gstr_union->str);
690199e0f17SMichael Roth 
69151e72bc1SEric Blake     visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
692199e0f17SMichael Roth     g_assert(cvalue != NULL);
693c363acefSEric Blake     g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
694199e0f17SMichael Roth 
69532bafa8fSEric Blake     for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) {
696199e0f17SMichael Roth         gchar str[8];
697199e0f17SMichael Roth         sprintf(str, "%d", i);
698199e0f17SMichael Roth         g_assert_cmpstr(elem->value, ==, str);
699199e0f17SMichael Roth     }
700199e0f17SMichael Roth 
701199e0f17SMichael Roth     g_string_free(gstr_union, true);
702199e0f17SMichael Roth     g_string_free(gstr_list, true);
703199e0f17SMichael Roth     qapi_free_UserDefNativeListUnion(cvalue);
704199e0f17SMichael Roth }
705199e0f17SMichael Roth 
706199e0f17SMichael Roth #define DOUBLE_STR_MAX 16
707199e0f17SMichael Roth 
708199e0f17SMichael Roth static void test_visitor_in_native_list_number(TestInputVisitorData *data,
709199e0f17SMichael Roth                                                const void *unused)
710199e0f17SMichael Roth {
711199e0f17SMichael Roth     UserDefNativeListUnion *cvalue = NULL;
712199e0f17SMichael Roth     numberList *elem = NULL;
713199e0f17SMichael Roth     Visitor *v;
714199e0f17SMichael Roth     GString *gstr_list = g_string_new("");
715199e0f17SMichael Roth     GString *gstr_union = g_string_new("");
716199e0f17SMichael Roth     int i;
717199e0f17SMichael Roth 
718199e0f17SMichael Roth     for (i = 0; i < 32; i++) {
719199e0f17SMichael Roth         g_string_append_printf(gstr_list, "%f", (double)i / 3);
720199e0f17SMichael Roth         if (i != 31) {
721199e0f17SMichael Roth             g_string_append(gstr_list, ", ");
722199e0f17SMichael Roth         }
723199e0f17SMichael Roth     }
724199e0f17SMichael Roth     g_string_append_printf(gstr_union,  "{ 'type': 'number', 'data': [ %s ] }",
725199e0f17SMichael Roth                            gstr_list->str);
726199e0f17SMichael Roth     v = visitor_input_test_init_raw(data,  gstr_union->str);
727199e0f17SMichael Roth 
72851e72bc1SEric Blake     visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
729199e0f17SMichael Roth     g_assert(cvalue != NULL);
730c363acefSEric Blake     g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
731199e0f17SMichael Roth 
73232bafa8fSEric Blake     for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next, i++) {
733199e0f17SMichael Roth         GString *double_expected = g_string_new("");
734199e0f17SMichael Roth         GString *double_actual = g_string_new("");
735199e0f17SMichael Roth 
736199e0f17SMichael Roth         g_string_printf(double_expected, "%.6f", (double)i / 3);
737199e0f17SMichael Roth         g_string_printf(double_actual, "%.6f", elem->value);
738199e0f17SMichael Roth         g_assert_cmpstr(double_expected->str, ==, double_actual->str);
739199e0f17SMichael Roth 
740199e0f17SMichael Roth         g_string_free(double_expected, true);
741199e0f17SMichael Roth         g_string_free(double_actual, true);
742199e0f17SMichael Roth     }
743199e0f17SMichael Roth 
744199e0f17SMichael Roth     g_string_free(gstr_union, true);
745199e0f17SMichael Roth     g_string_free(gstr_list, true);
746199e0f17SMichael Roth     qapi_free_UserDefNativeListUnion(cvalue);
747199e0f17SMichael Roth }
748199e0f17SMichael Roth 
749d88f5fd1SLuiz Capitulino static void input_visitor_test_add(const char *testpath,
750d88f5fd1SLuiz Capitulino                                    TestInputVisitorData *data,
751d88f5fd1SLuiz Capitulino                                    void (*test_func)(TestInputVisitorData *data, const void *user_data))
752d88f5fd1SLuiz Capitulino {
753d88f5fd1SLuiz Capitulino     g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
754d88f5fd1SLuiz Capitulino                visitor_input_teardown);
755d88f5fd1SLuiz Capitulino }
756d88f5fd1SLuiz Capitulino 
7573dcf71f6SPaolo Bonzini static void test_visitor_in_errors(TestInputVisitorData *data,
7583dcf71f6SPaolo Bonzini                                    const void *unused)
7593dcf71f6SPaolo Bonzini {
7603dcf71f6SPaolo Bonzini     TestStruct *p = NULL;
761e940f543SMarkus Armbruster     Error *err = NULL;
7623dcf71f6SPaolo Bonzini     Visitor *v;
763dd5ee2c2SEric Blake     strList *q = NULL;
7649b4e38feSEric Blake     UserDefTwo *r = NULL;
7659b4e38feSEric Blake     WrapAlternate *s = NULL;
7663dcf71f6SPaolo Bonzini 
767dd5ee2c2SEric Blake     v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
768dd5ee2c2SEric Blake                                 "'string': -42 }");
7693dcf71f6SPaolo Bonzini 
77051e72bc1SEric Blake     visit_type_TestStruct(v, NULL, &p, &err);
771a12a5a1aSEric Blake     error_free_or_abort(&err);
77268ab47e4SEric Blake     g_assert(!p);
773dd5ee2c2SEric Blake 
774dd5ee2c2SEric Blake     v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
77551e72bc1SEric Blake     visit_type_strList(v, NULL, &q, &err);
776dd5ee2c2SEric Blake     error_free_or_abort(&err);
77768ab47e4SEric Blake     assert(!q);
7789b4e38feSEric Blake 
7799b4e38feSEric Blake     v = visitor_input_test_init(data, "{ 'str':'hi' }");
7809b4e38feSEric Blake     visit_type_UserDefTwo(v, NULL, &r, &err);
7819b4e38feSEric Blake     error_free_or_abort(&err);
7829b4e38feSEric Blake     assert(!r);
7839b4e38feSEric Blake 
7849b4e38feSEric Blake     v = visitor_input_test_init(data, "{ }");
7859b4e38feSEric Blake     visit_type_WrapAlternate(v, NULL, &s, &err);
7869b4e38feSEric Blake     error_free_or_abort(&err);
7879b4e38feSEric Blake     assert(!s);
7883dcf71f6SPaolo Bonzini }
7893dcf71f6SPaolo Bonzini 
7902533377cSEric Blake static void test_visitor_in_wrong_type(TestInputVisitorData *data,
7912533377cSEric Blake                                        const void *unused)
7922533377cSEric Blake {
7932533377cSEric Blake     TestStruct *p = NULL;
7942533377cSEric Blake     Visitor *v;
7952533377cSEric Blake     strList *q = NULL;
7962533377cSEric Blake     int64_t i;
7972533377cSEric Blake     Error *err = NULL;
7982533377cSEric Blake 
7992533377cSEric Blake     /* Make sure arrays and structs cannot be confused */
8002533377cSEric Blake 
8012533377cSEric Blake     v = visitor_input_test_init(data, "[]");
80251e72bc1SEric Blake     visit_type_TestStruct(v, NULL, &p, &err);
8032533377cSEric Blake     error_free_or_abort(&err);
8042533377cSEric Blake     g_assert(!p);
8052533377cSEric Blake 
8062533377cSEric Blake     v = visitor_input_test_init(data, "{}");
80751e72bc1SEric Blake     visit_type_strList(v, NULL, &q, &err);
8082533377cSEric Blake     error_free_or_abort(&err);
8092533377cSEric Blake     assert(!q);
8102533377cSEric Blake 
8112533377cSEric Blake     /* Make sure primitives and struct cannot be confused */
8122533377cSEric Blake 
8132533377cSEric Blake     v = visitor_input_test_init(data, "1");
81451e72bc1SEric Blake     visit_type_TestStruct(v, NULL, &p, &err);
8152533377cSEric Blake     error_free_or_abort(&err);
8162533377cSEric Blake     g_assert(!p);
8172533377cSEric Blake 
8182533377cSEric Blake     v = visitor_input_test_init(data, "{}");
81951e72bc1SEric Blake     visit_type_int(v, NULL, &i, &err);
8202533377cSEric Blake     error_free_or_abort(&err);
8212533377cSEric Blake 
8222533377cSEric Blake     /* Make sure primitives and arrays cannot be confused */
8232533377cSEric Blake 
8242533377cSEric Blake     v = visitor_input_test_init(data, "1");
82551e72bc1SEric Blake     visit_type_strList(v, NULL, &q, &err);
8262533377cSEric Blake     error_free_or_abort(&err);
8272533377cSEric Blake     assert(!q);
8282533377cSEric Blake 
8292533377cSEric Blake     v = visitor_input_test_init(data, "[]");
83051e72bc1SEric Blake     visit_type_int(v, NULL, &i, &err);
8312533377cSEric Blake     error_free_or_abort(&err);
8322533377cSEric Blake }
8332533377cSEric Blake 
834d88f5fd1SLuiz Capitulino int main(int argc, char **argv)
835d88f5fd1SLuiz Capitulino {
836d88f5fd1SLuiz Capitulino     TestInputVisitorData in_visitor_data;
837d88f5fd1SLuiz Capitulino 
838d88f5fd1SLuiz Capitulino     g_test_init(&argc, &argv, NULL);
839d88f5fd1SLuiz Capitulino 
840d88f5fd1SLuiz Capitulino     input_visitor_test_add("/visitor/input/int",
841d88f5fd1SLuiz Capitulino                            &in_visitor_data, test_visitor_in_int);
842e92cfa0dSMichael Roth     input_visitor_test_add("/visitor/input/int_overflow",
843e92cfa0dSMichael Roth                            &in_visitor_data, test_visitor_in_int_overflow);
844d88f5fd1SLuiz Capitulino     input_visitor_test_add("/visitor/input/bool",
845d88f5fd1SLuiz Capitulino                            &in_visitor_data, test_visitor_in_bool);
846d88f5fd1SLuiz Capitulino     input_visitor_test_add("/visitor/input/number",
847d88f5fd1SLuiz Capitulino                            &in_visitor_data, test_visitor_in_number);
848d88f5fd1SLuiz Capitulino     input_visitor_test_add("/visitor/input/string",
849d88f5fd1SLuiz Capitulino                            &in_visitor_data, test_visitor_in_string);
850d88f5fd1SLuiz Capitulino     input_visitor_test_add("/visitor/input/enum",
851d88f5fd1SLuiz Capitulino                            &in_visitor_data, test_visitor_in_enum);
852d88f5fd1SLuiz Capitulino     input_visitor_test_add("/visitor/input/struct",
853d88f5fd1SLuiz Capitulino                            &in_visitor_data, test_visitor_in_struct);
854d88f5fd1SLuiz Capitulino     input_visitor_test_add("/visitor/input/struct-nested",
855d88f5fd1SLuiz Capitulino                            &in_visitor_data, test_visitor_in_struct_nested);
856d88f5fd1SLuiz Capitulino     input_visitor_test_add("/visitor/input/list",
857d88f5fd1SLuiz Capitulino                            &in_visitor_data, test_visitor_in_list);
85828770e05SMarkus Armbruster     input_visitor_test_add("/visitor/input/any",
85928770e05SMarkus Armbruster                            &in_visitor_data, test_visitor_in_any);
8603df016f1SEric Blake     input_visitor_test_add("/visitor/input/null",
8613df016f1SEric Blake                            &in_visitor_data, test_visitor_in_null);
8622fc00432SMarkus Armbruster     input_visitor_test_add("/visitor/input/union-flat",
8632fc00432SMarkus Armbruster                            &in_visitor_data, test_visitor_in_union_flat);
864ab045267SEric Blake     input_visitor_test_add("/visitor/input/alternate",
865ab045267SEric Blake                            &in_visitor_data, test_visitor_in_alternate);
8663dcf71f6SPaolo Bonzini     input_visitor_test_add("/visitor/input/errors",
8673dcf71f6SPaolo Bonzini                            &in_visitor_data, test_visitor_in_errors);
8682533377cSEric Blake     input_visitor_test_add("/visitor/input/wrong-type",
8692533377cSEric Blake                            &in_visitor_data, test_visitor_in_wrong_type);
8709c51b441SEric Blake     input_visitor_test_add("/visitor/input/alternate-number",
8719c51b441SEric Blake                            &in_visitor_data, test_visitor_in_alternate_number);
872199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/int",
873199e0f17SMichael Roth                            &in_visitor_data,
874199e0f17SMichael Roth                            test_visitor_in_native_list_int);
875199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/int8",
876199e0f17SMichael Roth                            &in_visitor_data,
877199e0f17SMichael Roth                            test_visitor_in_native_list_int8);
878199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/int16",
879199e0f17SMichael Roth                            &in_visitor_data,
880199e0f17SMichael Roth                            test_visitor_in_native_list_int16);
881199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/int32",
882199e0f17SMichael Roth                            &in_visitor_data,
883199e0f17SMichael Roth                            test_visitor_in_native_list_int32);
884199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/int64",
885199e0f17SMichael Roth                            &in_visitor_data,
886199e0f17SMichael Roth                            test_visitor_in_native_list_int64);
887199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/uint8",
888199e0f17SMichael Roth                            &in_visitor_data,
889199e0f17SMichael Roth                            test_visitor_in_native_list_uint8);
890199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/uint16",
891199e0f17SMichael Roth                            &in_visitor_data,
892199e0f17SMichael Roth                            test_visitor_in_native_list_uint16);
893199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/uint32",
894199e0f17SMichael Roth                            &in_visitor_data,
895199e0f17SMichael Roth                            test_visitor_in_native_list_uint32);
896199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/uint64",
897805017b7SEric Blake                            &in_visitor_data,
898805017b7SEric Blake                            test_visitor_in_native_list_uint64);
899199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/bool",
900199e0f17SMichael Roth                            &in_visitor_data, test_visitor_in_native_list_bool);
901199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/str",
902805017b7SEric Blake                            &in_visitor_data,
903805017b7SEric Blake                            test_visitor_in_native_list_string);
904199e0f17SMichael Roth     input_visitor_test_add("/visitor/input/native_list/number",
905805017b7SEric Blake                            &in_visitor_data,
906805017b7SEric Blake                            test_visitor_in_native_list_number);
907d88f5fd1SLuiz Capitulino 
908d88f5fd1SLuiz Capitulino     g_test_run();
909d88f5fd1SLuiz Capitulino 
910d88f5fd1SLuiz Capitulino     return 0;
911d88f5fd1SLuiz Capitulino }
912