1 /*
2  * QObject Input Visitor unit-tests.
3  *
4  * Copyright (C) 2011-2016 Red Hat Inc.
5  *
6  * Authors:
7  *  Luiz Capitulino <lcapitulino@redhat.com>
8  *  Paolo Bonzini <pbonzini@redhat.com>
9  *
10  * This work is licensed under the terms of the GNU GPL, version 2 or later.
11  * See the COPYING file in the top-level directory.
12  */
13 
14 #include "qemu/osdep.h"
15 
16 #include "qapi/error.h"
17 #include "qapi/qapi-visit-introspect.h"
18 #include "qapi/qobject-input-visitor.h"
19 #include "test-qapi-visit.h"
20 #include "qapi/qmp/qbool.h"
21 #include "qapi/qmp/qdict.h"
22 #include "qapi/qmp/qnull.h"
23 #include "qapi/qmp/qnum.h"
24 #include "qapi/qmp/qstring.h"
25 #include "qapi/qmp/qjson.h"
26 #include "test-qapi-introspect.h"
27 #include "qapi/qapi-introspect.h"
28 
29 typedef struct TestInputVisitorData {
30     QObject *obj;
31     Visitor *qiv;
32 } TestInputVisitorData;
33 
34 static void visitor_input_teardown(TestInputVisitorData *data,
35                                    const void *unused)
36 {
37     qobject_unref(data->obj);
38     data->obj = NULL;
39 
40     if (data->qiv) {
41         visit_free(data->qiv);
42         data->qiv = NULL;
43     }
44 }
45 
46 /* The various test_init functions are provided instead of a test setup
47    function so that the JSON string used by the tests are kept in the test
48    functions (and not in main()). */
49 
50 static Visitor *test_init_internal(TestInputVisitorData *data, bool keyval,
51                                    QObject *obj)
52 {
53     visitor_input_teardown(data, NULL);
54 
55     data->obj = obj;
56 
57     if (keyval) {
58         data->qiv = qobject_input_visitor_new_keyval(data->obj);
59     } else {
60         data->qiv = qobject_input_visitor_new(data->obj);
61     }
62     g_assert(data->qiv);
63     return data->qiv;
64 }
65 
66 static G_GNUC_PRINTF(3, 4)
67 Visitor *visitor_input_test_init_full(TestInputVisitorData *data,
68                                       bool keyval,
69                                       const char *json_string, ...)
70 {
71     Visitor *v;
72     va_list ap;
73 
74     va_start(ap, json_string);
75     v = test_init_internal(data, keyval,
76                            qobject_from_vjsonf_nofail(json_string, ap));
77     va_end(ap);
78     return v;
79 }
80 
81 static G_GNUC_PRINTF(2, 3)
82 Visitor *visitor_input_test_init(TestInputVisitorData *data,
83                                  const char *json_string, ...)
84 {
85     Visitor *v;
86     va_list ap;
87 
88     va_start(ap, json_string);
89     v = test_init_internal(data, false,
90                            qobject_from_vjsonf_nofail(json_string, ap));
91     va_end(ap);
92     return v;
93 }
94 
95 /* similar to visitor_input_test_init(), but does not expect a string
96  * literal/format json_string argument and so can be used for
97  * programatically generated strings (and we can't pass in programatically
98  * generated strings via %s format parameters since qobject_from_jsonv()
99  * will wrap those in double-quotes and treat the entire object as a
100  * string)
101  */
102 static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
103                                             const char *json_string)
104 {
105     return test_init_internal(data, false,
106                               qobject_from_json(json_string, &error_abort));
107 }
108 
109 static void test_visitor_in_int(TestInputVisitorData *data,
110                                 const void *unused)
111 {
112     int64_t res = 0;
113     double dbl;
114     int value = -42;
115     Visitor *v;
116 
117     v = visitor_input_test_init(data, "%d", value);
118 
119     visit_type_int(v, NULL, &res, &error_abort);
120     g_assert_cmpint(res, ==, value);
121 
122     visit_type_number(v, NULL, &dbl, &error_abort);
123     g_assert_cmpfloat(dbl, ==, -42.0);
124 }
125 
126 static void test_visitor_in_uint(TestInputVisitorData *data,
127                                 const void *unused)
128 {
129     uint64_t res = 0;
130     int64_t i64;
131     double dbl;
132     int value = 42;
133     Visitor *v;
134 
135     v = visitor_input_test_init(data, "%d", value);
136 
137     visit_type_uint64(v, NULL, &res, &error_abort);
138     g_assert_cmpuint(res, ==, (uint64_t)value);
139 
140     visit_type_int(v, NULL, &i64, &error_abort);
141     g_assert_cmpint(i64, ==, value);
142 
143     visit_type_number(v, NULL, &dbl, &error_abort);
144     g_assert_cmpfloat(dbl, ==, value);
145 
146     /* BUG: value between INT64_MIN and -1 accepted modulo 2^64 */
147     v = visitor_input_test_init(data, "%d", -value);
148 
149     visit_type_uint64(v, NULL, &res, &error_abort);
150     g_assert_cmpuint(res, ==, (uint64_t)-value);
151 
152     v = visitor_input_test_init(data, "18446744073709551574");
153 
154     visit_type_uint64(v, NULL, &res, &error_abort);
155     g_assert_cmpuint(res, ==, 18446744073709551574U);
156 
157     visit_type_number(v, NULL, &dbl, &error_abort);
158     g_assert_cmpfloat(dbl, ==, 18446744073709552000.0);
159 }
160 
161 static void test_visitor_in_int_overflow(TestInputVisitorData *data,
162                                          const void *unused)
163 {
164     int64_t res = 0;
165     Error *err = NULL;
166     Visitor *v;
167 
168     /*
169      * This will overflow a QNUM_I64, so should be deserialized into a
170      * QNUM_DOUBLE field instead, leading to an error if we pass it to
171      * visit_type_int().  Confirm this.
172      */
173     v = visitor_input_test_init(data, "%f", DBL_MAX);
174 
175     visit_type_int(v, NULL, &res, &err);
176     error_free_or_abort(&err);
177 }
178 
179 static void test_visitor_in_int_keyval(TestInputVisitorData *data,
180                                        const void *unused)
181 {
182     int64_t res = 0, value = -42;
183     Error *err = NULL;
184     Visitor *v;
185 
186     v = visitor_input_test_init_full(data, true, "%" PRId64, value);
187     visit_type_int(v, NULL, &res, &err);
188     error_free_or_abort(&err);
189 }
190 
191 static void test_visitor_in_int_str_keyval(TestInputVisitorData *data,
192                                            const void *unused)
193 {
194     int64_t res = 0, value = -42;
195     Visitor *v;
196 
197     v = visitor_input_test_init_full(data, true, "\"-42\"");
198 
199     visit_type_int(v, NULL, &res, &error_abort);
200     g_assert_cmpint(res, ==, value);
201 }
202 
203 static void test_visitor_in_int_str_fail(TestInputVisitorData *data,
204                                          const void *unused)
205 {
206     int64_t res = 0;
207     Visitor *v;
208     Error *err = NULL;
209 
210     v = visitor_input_test_init(data, "\"-42\"");
211 
212     visit_type_int(v, NULL, &res, &err);
213     error_free_or_abort(&err);
214 }
215 
216 static void test_visitor_in_bool(TestInputVisitorData *data,
217                                  const void *unused)
218 {
219     bool res = false;
220     Visitor *v;
221 
222     v = visitor_input_test_init(data, "true");
223 
224     visit_type_bool(v, NULL, &res, &error_abort);
225     g_assert_cmpint(res, ==, true);
226 }
227 
228 static void test_visitor_in_bool_keyval(TestInputVisitorData *data,
229                                         const void *unused)
230 {
231     bool res = false;
232     Error *err = NULL;
233     Visitor *v;
234 
235     v = visitor_input_test_init_full(data, true, "true");
236 
237     visit_type_bool(v, NULL, &res, &err);
238     error_free_or_abort(&err);
239 }
240 
241 static void test_visitor_in_bool_str_keyval(TestInputVisitorData *data,
242                                             const void *unused)
243 {
244     bool res = false;
245     Visitor *v;
246 
247     v = visitor_input_test_init_full(data, true, "\"on\"");
248 
249     visit_type_bool(v, NULL, &res, &error_abort);
250     g_assert_cmpint(res, ==, true);
251 }
252 
253 static void test_visitor_in_bool_str_fail(TestInputVisitorData *data,
254                                           const void *unused)
255 {
256     bool res = false;
257     Visitor *v;
258     Error *err = NULL;
259 
260     v = visitor_input_test_init(data, "\"true\"");
261 
262     visit_type_bool(v, NULL, &res, &err);
263     error_free_or_abort(&err);
264 }
265 
266 static void test_visitor_in_number(TestInputVisitorData *data,
267                                    const void *unused)
268 {
269     double res = 0, value = 3.14;
270     Visitor *v;
271 
272     v = visitor_input_test_init(data, "%f", value);
273 
274     visit_type_number(v, NULL, &res, &error_abort);
275     g_assert_cmpfloat(res, ==, value);
276 }
277 
278 static void test_visitor_in_large_number(TestInputVisitorData *data,
279                                          const void *unused)
280 {
281     Error *err = NULL;
282     double res = 0;
283     int64_t i64;
284     uint64_t u64;
285     Visitor *v;
286 
287     v = visitor_input_test_init(data, "-18446744073709551616"); /* -2^64 */
288 
289     visit_type_number(v, NULL, &res, &error_abort);
290     g_assert_cmpfloat(res, ==, -18446744073709552e3);
291 
292     visit_type_int(v, NULL, &i64, &err);
293     error_free_or_abort(&err);
294 
295     visit_type_uint64(v, NULL, &u64, &err);
296     error_free_or_abort(&err);
297 }
298 
299 static void test_visitor_in_number_keyval(TestInputVisitorData *data,
300                                           const void *unused)
301 {
302     double res = 0, value = 3.14;
303     Error *err = NULL;
304     Visitor *v;
305 
306     v = visitor_input_test_init_full(data, true, "%f", value);
307 
308     visit_type_number(v, NULL, &res, &err);
309     error_free_or_abort(&err);
310 }
311 
312 static void test_visitor_in_number_str_keyval(TestInputVisitorData *data,
313                                               const void *unused)
314 {
315     double res = 0, value = 3.14;
316     Visitor *v;
317     Error *err = NULL;
318 
319     v = visitor_input_test_init_full(data, true, "\"3.14\"");
320 
321     visit_type_number(v, NULL, &res, &error_abort);
322     g_assert_cmpfloat(res, ==, value);
323 
324     v = visitor_input_test_init_full(data, true, "\"inf\"");
325 
326     visit_type_number(v, NULL, &res, &err);
327     error_free_or_abort(&err);
328 }
329 
330 static void test_visitor_in_number_str_fail(TestInputVisitorData *data,
331                                             const void *unused)
332 {
333     double res = 0;
334     Visitor *v;
335     Error *err = NULL;
336 
337     v = visitor_input_test_init(data, "\"3.14\"");
338 
339     visit_type_number(v, NULL, &res, &err);
340     error_free_or_abort(&err);
341 }
342 
343 static void test_visitor_in_size_str_keyval(TestInputVisitorData *data,
344                                             const void *unused)
345 {
346     uint64_t res, value = 500 * 1024 * 1024;
347     Visitor *v;
348 
349     v = visitor_input_test_init_full(data, true, "\"500M\"");
350 
351     visit_type_size(v, NULL, &res, &error_abort);
352     g_assert_cmpfloat(res, ==, value);
353 }
354 
355 static void test_visitor_in_size_str_fail(TestInputVisitorData *data,
356                                           const void *unused)
357 {
358     uint64_t res = 0;
359     Visitor *v;
360     Error *err = NULL;
361 
362     v = visitor_input_test_init(data, "\"500M\"");
363 
364     visit_type_size(v, NULL, &res, &err);
365     error_free_or_abort(&err);
366 }
367 
368 static void test_visitor_in_string(TestInputVisitorData *data,
369                                    const void *unused)
370 {
371     char *res = NULL, *value = (char *) "Q E M U";
372     Visitor *v;
373 
374     v = visitor_input_test_init(data, "%s", value);
375 
376     visit_type_str(v, NULL, &res, &error_abort);
377     g_assert_cmpstr(res, ==, value);
378 
379     g_free(res);
380 }
381 
382 static void test_visitor_in_enum(TestInputVisitorData *data,
383                                  const void *unused)
384 {
385     Visitor *v;
386     EnumOne i;
387 
388     for (i = 0; i < ENUM_ONE__MAX; i++) {
389         EnumOne res = -1;
390 
391         v = visitor_input_test_init(data, "%s", EnumOne_str(i));
392 
393         visit_type_EnumOne(v, NULL, &res, &error_abort);
394         g_assert_cmpint(i, ==, res);
395     }
396 }
397 
398 
399 static void test_visitor_in_struct(TestInputVisitorData *data,
400                                    const void *unused)
401 {
402     TestStruct *p = NULL;
403     Visitor *v;
404 
405     v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
406 
407     visit_type_TestStruct(v, NULL, &p, &error_abort);
408     g_assert_cmpint(p->integer, ==, -42);
409     g_assert(p->boolean == true);
410     g_assert_cmpstr(p->string, ==, "foo");
411 
412     g_free(p->string);
413     g_free(p);
414 }
415 
416 static void test_visitor_in_struct_nested(TestInputVisitorData *data,
417                                           const void *unused)
418 {
419     g_autoptr(UserDefTwo) udp = NULL;
420     Visitor *v;
421 
422     v = visitor_input_test_init(data, "{ 'string0': 'string0', "
423                                 "'dict1': { 'string1': 'string1', "
424                                 "'dict2': { 'userdef': { 'integer': 42, "
425                                 "'string': 'string' }, 'string': 'string2'}}}");
426 
427     visit_type_UserDefTwo(v, NULL, &udp, &error_abort);
428 
429     g_assert_cmpstr(udp->string0, ==, "string0");
430     g_assert_cmpstr(udp->dict1->string1, ==, "string1");
431     g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
432     g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
433     g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
434     g_assert(udp->dict1->has_dict3 == false);
435 }
436 
437 static void test_visitor_in_list(TestInputVisitorData *data,
438                                  const void *unused)
439 {
440     UserDefOneList *item, *head = NULL;
441     Visitor *v;
442     int i;
443 
444     v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
445 
446     visit_type_UserDefOneList(v, NULL, &head, &error_abort);
447     g_assert(head != NULL);
448 
449     for (i = 0, item = head; item; item = item->next, i++) {
450         char string[12];
451 
452         snprintf(string, sizeof(string), "string%d", i);
453         g_assert_cmpstr(item->value->string, ==, string);
454         g_assert_cmpint(item->value->integer, ==, 42 + i);
455     }
456 
457     qapi_free_UserDefOneList(head);
458     head = NULL;
459 
460     /* An empty list is valid */
461     v = visitor_input_test_init(data, "[]");
462     visit_type_UserDefOneList(v, NULL, &head, &error_abort);
463     g_assert(!head);
464 }
465 
466 static void test_visitor_in_list_struct(TestInputVisitorData *data,
467                                         const void *unused)
468 {
469     const char *int_member[] = {
470         "integer", "s8", "s16", "s32", "s64", "u8", "u16", "u32", "u64" };
471     g_autoptr(GString) json = g_string_new("");
472     int i, j;
473     const char *sep;
474     g_autoptr(ArrayStruct) arrs = NULL;
475     Visitor *v;
476     intList *int_list;
477     int8List *s8_list;
478     int16List *s16_list;
479     int32List *s32_list;
480     int64List *s64_list;
481     uint8List *u8_list;
482     uint16List *u16_list;
483     uint32List *u32_list;
484     uint64List *u64_list;
485     numberList *num_list;
486     boolList *bool_list;
487     strList *str_list;
488 
489     g_string_append_printf(json, "{");
490 
491     for (i = 0; i < G_N_ELEMENTS(int_member); i++) {
492         g_string_append_printf(json, "'%s': [", int_member[i]);
493         sep = "";
494         for (j = 0; j < 32; j++) {
495             g_string_append_printf(json, "%s%d", sep, j);
496             sep = ", ";
497         }
498         g_string_append_printf(json, "], ");
499     }
500 
501     g_string_append_printf(json, "'number': [");
502     sep = "";
503     for (i = 0; i < 32; i++) {
504         g_string_append_printf(json, "%s%f", sep, (double)i / 3);
505         sep = ", ";
506     }
507     g_string_append_printf(json, "], ");
508 
509     g_string_append_printf(json, "'boolean': [");
510     sep = "";
511     for (i = 0; i < 32; i++) {
512         g_string_append_printf(json, "%s%s",
513                                sep, i % 3 == 0 ? "true" : "false");
514         sep = ", ";
515     }
516     g_string_append_printf(json, "], ");
517 
518     g_string_append_printf(json, "'string': [");
519     sep = "";
520     for (i = 0; i < 32; i++) {
521         g_string_append_printf(json, "%s'%d'", sep, i);
522         sep = ", ";
523     }
524     g_string_append_printf(json, "]");
525 
526     g_string_append_printf(json, "}");
527 
528     v = visitor_input_test_init_raw(data, json->str);
529     visit_type_ArrayStruct(v, NULL, &arrs, &error_abort);
530 
531     i = 0;
532     for (int_list = arrs->integer; int_list; int_list = int_list->next) {
533         g_assert_cmpint(int_list->value, ==, i);
534         i++;
535     }
536 
537     i = 0;
538     for (s8_list = arrs->s8; s8_list; s8_list = s8_list->next) {
539         g_assert_cmpint(s8_list->value, ==, i);
540         i++;
541     }
542 
543     i = 0;
544     for (s16_list = arrs->s16; s16_list; s16_list = s16_list->next) {
545         g_assert_cmpint(s16_list->value, ==, i);
546         i++;
547     }
548 
549     i = 0;
550     for (s32_list = arrs->s32; s32_list; s32_list = s32_list->next) {
551         g_assert_cmpint(s32_list->value, ==, i);
552         i++;
553     }
554 
555     i = 0;
556     for (s64_list = arrs->s64; s64_list; s64_list = s64_list->next) {
557         g_assert_cmpint(s64_list->value, ==, i);
558         i++;
559     }
560 
561     i = 0;
562     for (u8_list = arrs->u8; u8_list; u8_list = u8_list->next) {
563         g_assert_cmpint(u8_list->value, ==, i);
564         i++;
565     }
566 
567     i = 0;
568     for (u16_list = arrs->u16; u16_list; u16_list = u16_list->next) {
569         g_assert_cmpint(u16_list->value, ==, i);
570         i++;
571     }
572 
573     i = 0;
574     for (u32_list = arrs->u32; u32_list; u32_list = u32_list->next) {
575         g_assert_cmpint(u32_list->value, ==, i);
576         i++;
577     }
578 
579     i = 0;
580     for (u64_list = arrs->u64; u64_list; u64_list = u64_list->next) {
581         g_assert_cmpint(u64_list->value, ==, i);
582         i++;
583     }
584 
585     i = 0;
586     for (num_list = arrs->number; num_list; num_list = num_list->next) {
587         char expected[32], actual[32];
588 
589         sprintf(expected, "%.6f", (double)i / 3);
590         sprintf(actual, "%.6f", num_list->value);
591         g_assert_cmpstr(expected, ==, actual);
592         i++;
593     }
594 
595     i = 0;
596     for (bool_list = arrs->boolean; bool_list; bool_list = bool_list->next) {
597         g_assert_cmpint(bool_list->value, ==, i % 3 == 0);
598         i++;
599     }
600 
601     i = 0;
602     for (str_list = arrs->string; str_list; str_list = str_list->next) {
603         char expected[32];
604 
605         sprintf(expected, "%d", i);
606         g_assert_cmpstr(str_list->value, ==, expected);
607         i++;
608     }
609 }
610 
611 static void test_visitor_in_any(TestInputVisitorData *data,
612                                 const void *unused)
613 {
614     QObject *res = NULL;
615     Visitor *v;
616     QNum *qnum;
617     QBool *qbool;
618     QString *qstring;
619     QDict *qdict;
620     QObject *qobj;
621     int64_t val;
622 
623     v = visitor_input_test_init(data, "-42");
624     visit_type_any(v, NULL, &res, &error_abort);
625     qnum = qobject_to(QNum, res);
626     g_assert(qnum);
627     g_assert(qnum_get_try_int(qnum, &val));
628     g_assert_cmpint(val, ==, -42);
629     qobject_unref(res);
630 
631     v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
632     visit_type_any(v, NULL, &res, &error_abort);
633     qdict = qobject_to(QDict, res);
634     g_assert(qdict && qdict_size(qdict) == 3);
635     qobj = qdict_get(qdict, "integer");
636     g_assert(qobj);
637     qnum = qobject_to(QNum, qobj);
638     g_assert(qnum);
639     g_assert(qnum_get_try_int(qnum, &val));
640     g_assert_cmpint(val, ==, -42);
641     qobj = qdict_get(qdict, "boolean");
642     g_assert(qobj);
643     qbool = qobject_to(QBool, qobj);
644     g_assert(qbool);
645     g_assert(qbool_get_bool(qbool) == true);
646     qobj = qdict_get(qdict, "string");
647     g_assert(qobj);
648     qstring = qobject_to(QString, qobj);
649     g_assert(qstring);
650     g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
651     qobject_unref(res);
652 }
653 
654 static void test_visitor_in_null(TestInputVisitorData *data,
655                                  const void *unused)
656 {
657     Visitor *v;
658     Error *err = NULL;
659     QNull *null;
660     char *tmp;
661 
662     /*
663      * FIXME: Since QAPI doesn't know the 'null' type yet, we can't
664      * test visit_type_null() by reading into a QAPI struct then
665      * checking that it was populated correctly.  The best we can do
666      * for now is ensure that we consumed null from the input, proven
667      * by the fact that we can't re-read the key; and that we detect
668      * when input is not null.
669      */
670 
671     v = visitor_input_test_init_full(data, false,
672                                      "{ 'a': null, 'b': '' }");
673     visit_start_struct(v, NULL, NULL, 0, &error_abort);
674     visit_type_null(v, "a", &null, &error_abort);
675     g_assert(qobject_type(QOBJECT(null)) == QTYPE_QNULL);
676     qobject_unref(null);
677     visit_type_null(v, "b", &null, &err);
678     error_free_or_abort(&err);
679     g_assert(!null);
680     visit_type_str(v, "c", &tmp, &err);
681     error_free_or_abort(&err);
682     g_assert(!tmp);
683     visit_check_struct(v, &error_abort);
684     visit_end_struct(v, NULL);
685 }
686 
687 static void test_visitor_in_union_flat(TestInputVisitorData *data,
688                                        const void *unused)
689 {
690     Visitor *v;
691     g_autoptr(UserDefFlatUnion) tmp = NULL;
692     UserDefUnionBase *base;
693 
694     v = visitor_input_test_init(data,
695                                 "{ 'enum1': 'value1', "
696                                 "'integer': 41, "
697                                 "'string': 'str', "
698                                 "'boolean': true }");
699 
700     visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
701     g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
702     g_assert_cmpstr(tmp->string, ==, "str");
703     g_assert_cmpint(tmp->integer, ==, 41);
704     g_assert_cmpint(tmp->u.value1.boolean, ==, true);
705 
706     base = qapi_UserDefFlatUnion_base(tmp);
707     g_assert(&base->enum1 == &tmp->enum1);
708 }
709 
710 static void test_visitor_in_alternate(TestInputVisitorData *data,
711                                       const void *unused)
712 {
713     Visitor *v;
714     UserDefAlternate *tmp;
715     WrapAlternate *wrap;
716 
717     v = visitor_input_test_init(data, "42");
718     visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
719     g_assert_cmpint(tmp->type, ==, QTYPE_QNUM);
720     g_assert_cmpint(tmp->u.i, ==, 42);
721     qapi_free_UserDefAlternate(tmp);
722 
723     v = visitor_input_test_init(data, "'value1'");
724     visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
725     g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
726     g_assert_cmpint(tmp->u.e, ==, ENUM_ONE_VALUE1);
727     qapi_free_UserDefAlternate(tmp);
728 
729     v = visitor_input_test_init(data, "null");
730     visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
731     g_assert_cmpint(tmp->type, ==, QTYPE_QNULL);
732     qapi_free_UserDefAlternate(tmp);
733 
734     v = visitor_input_test_init(data, "{'integer':1, 'string':'str', "
735                                 "'enum1':'value1', 'boolean':true}");
736     visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
737     g_assert_cmpint(tmp->type, ==, QTYPE_QDICT);
738     g_assert_cmpint(tmp->u.udfu.integer, ==, 1);
739     g_assert_cmpstr(tmp->u.udfu.string, ==, "str");
740     g_assert_cmpint(tmp->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
741     g_assert_cmpint(tmp->u.udfu.u.value1.boolean, ==, true);
742     g_assert_cmpint(tmp->u.udfu.u.value1.has_a_b, ==, false);
743     qapi_free_UserDefAlternate(tmp);
744 
745     v = visitor_input_test_init(data, "{ 'alt': 42 }");
746     visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
747     g_assert_cmpint(wrap->alt->type, ==, QTYPE_QNUM);
748     g_assert_cmpint(wrap->alt->u.i, ==, 42);
749     qapi_free_WrapAlternate(wrap);
750 
751     v = visitor_input_test_init(data, "{ 'alt': 'value1' }");
752     visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
753     g_assert_cmpint(wrap->alt->type, ==, QTYPE_QSTRING);
754     g_assert_cmpint(wrap->alt->u.e, ==, ENUM_ONE_VALUE1);
755     qapi_free_WrapAlternate(wrap);
756 
757     v = visitor_input_test_init(data, "{ 'alt': {'integer':1, 'string':'str', "
758                                 "'enum1':'value1', 'boolean':true} }");
759     visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
760     g_assert_cmpint(wrap->alt->type, ==, QTYPE_QDICT);
761     g_assert_cmpint(wrap->alt->u.udfu.integer, ==, 1);
762     g_assert_cmpstr(wrap->alt->u.udfu.string, ==, "str");
763     g_assert_cmpint(wrap->alt->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
764     g_assert_cmpint(wrap->alt->u.udfu.u.value1.boolean, ==, true);
765     g_assert_cmpint(wrap->alt->u.udfu.u.value1.has_a_b, ==, false);
766     qapi_free_WrapAlternate(wrap);
767 }
768 
769 static void test_visitor_in_alternate_number(TestInputVisitorData *data,
770                                              const void *unused)
771 {
772     Visitor *v;
773     Error *err = NULL;
774     AltEnumBool *aeb;
775     AltEnumNum *aen;
776     AltNumEnum *ans;
777     AltEnumInt *asi;
778     AltListInt *ali;
779 
780     /* Parsing an int */
781 
782     v = visitor_input_test_init(data, "42");
783     visit_type_AltEnumBool(v, NULL, &aeb, &err);
784     error_free_or_abort(&err);
785     qapi_free_AltEnumBool(aeb);
786 
787     v = visitor_input_test_init(data, "42");
788     visit_type_AltEnumNum(v, NULL, &aen, &error_abort);
789     g_assert_cmpint(aen->type, ==, QTYPE_QNUM);
790     g_assert_cmpfloat(aen->u.n, ==, 42);
791     qapi_free_AltEnumNum(aen);
792 
793     v = visitor_input_test_init(data, "42");
794     visit_type_AltNumEnum(v, NULL, &ans, &error_abort);
795     g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
796     g_assert_cmpfloat(ans->u.n, ==, 42);
797     qapi_free_AltNumEnum(ans);
798 
799     v = visitor_input_test_init(data, "42");
800     visit_type_AltEnumInt(v, NULL, &asi, &error_abort);
801     g_assert_cmpint(asi->type, ==, QTYPE_QNUM);
802     g_assert_cmpint(asi->u.i, ==, 42);
803     qapi_free_AltEnumInt(asi);
804 
805     v = visitor_input_test_init(data, "42");
806     visit_type_AltListInt(v, NULL, &ali, &error_abort);
807     g_assert_cmpint(ali->type, ==, QTYPE_QNUM);
808     g_assert_cmpint(ali->u.i, ==, 42);
809     qapi_free_AltListInt(ali);
810 
811     /* Parsing a double */
812 
813     v = visitor_input_test_init(data, "42.5");
814     visit_type_AltEnumBool(v, NULL, &aeb, &err);
815     error_free_or_abort(&err);
816     qapi_free_AltEnumBool(aeb);
817 
818     v = visitor_input_test_init(data, "42.5");
819     visit_type_AltEnumNum(v, NULL, &aen, &error_abort);
820     g_assert_cmpint(aen->type, ==, QTYPE_QNUM);
821     g_assert_cmpfloat(aen->u.n, ==, 42.5);
822     qapi_free_AltEnumNum(aen);
823 
824     v = visitor_input_test_init(data, "42.5");
825     visit_type_AltNumEnum(v, NULL, &ans, &error_abort);
826     g_assert_cmpint(ans->type, ==, QTYPE_QNUM);
827     g_assert_cmpfloat(ans->u.n, ==, 42.5);
828     qapi_free_AltNumEnum(ans);
829 
830     v = visitor_input_test_init(data, "42.5");
831     visit_type_AltEnumInt(v, NULL, &asi, &err);
832     error_free_or_abort(&err);
833     qapi_free_AltEnumInt(asi);
834 }
835 
836 static void test_visitor_in_alternate_list(TestInputVisitorData *data,
837                                  const void *unused)
838 {
839     intList *item;
840     Visitor *v;
841     AltListInt *ali;
842     int i;
843 
844     v = visitor_input_test_init(data, "[ 42, 43, 44 ]");
845     visit_type_AltListInt(v, NULL, &ali, &error_abort);
846     g_assert(ali != NULL);
847 
848     g_assert_cmpint(ali->type, ==, QTYPE_QLIST);
849     for (i = 0, item = ali->u.l; item; item = item->next, i++) {
850         g_assert_cmpint(item->value, ==, 42 + i);
851     }
852 
853     qapi_free_AltListInt(ali);
854     ali = NULL;
855 
856     /* An empty list is valid */
857     v = visitor_input_test_init(data, "[]");
858     visit_type_AltListInt(v, NULL, &ali, &error_abort);
859     g_assert(ali != NULL);
860 
861     g_assert_cmpint(ali->type, ==, QTYPE_QLIST);
862     g_assert(!ali->u.l);
863     qapi_free_AltListInt(ali);
864     ali = NULL;
865 }
866 
867 static void input_visitor_test_add(const char *testpath,
868                                    const void *user_data,
869                                    void (*test_func)(TestInputVisitorData *data,
870                                                      const void *user_data))
871 {
872     g_test_add(testpath, TestInputVisitorData, user_data, NULL, test_func,
873                visitor_input_teardown);
874 }
875 
876 static void test_visitor_in_errors(TestInputVisitorData *data,
877                                    const void *unused)
878 {
879     TestStruct *p = NULL;
880     Error *err = NULL;
881     Visitor *v;
882     strList *q = NULL;
883     UserDefTwo *r = NULL;
884     WrapAlternate *s = NULL;
885 
886     v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
887                                 "'string': -42 }");
888 
889     visit_type_TestStruct(v, NULL, &p, &err);
890     error_free_or_abort(&err);
891     g_assert(!p);
892 
893     v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
894     visit_type_strList(v, NULL, &q, &err);
895     error_free_or_abort(&err);
896     assert(!q);
897 
898     v = visitor_input_test_init(data, "{ 'str':'hi' }");
899     visit_type_UserDefTwo(v, NULL, &r, &err);
900     error_free_or_abort(&err);
901     assert(!r);
902 
903     v = visitor_input_test_init(data, "{ }");
904     visit_type_WrapAlternate(v, NULL, &s, &err);
905     error_free_or_abort(&err);
906     assert(!s);
907 }
908 
909 static void test_visitor_in_wrong_type(TestInputVisitorData *data,
910                                        const void *unused)
911 {
912     TestStruct *p = NULL;
913     Visitor *v;
914     strList *q = NULL;
915     int64_t i;
916     Error *err = NULL;
917 
918     /* Make sure arrays and structs cannot be confused */
919 
920     v = visitor_input_test_init(data, "[]");
921     visit_type_TestStruct(v, NULL, &p, &err);
922     error_free_or_abort(&err);
923     g_assert(!p);
924 
925     v = visitor_input_test_init(data, "{}");
926     visit_type_strList(v, NULL, &q, &err);
927     error_free_or_abort(&err);
928     assert(!q);
929 
930     /* Make sure primitives and struct cannot be confused */
931 
932     v = visitor_input_test_init(data, "1");
933     visit_type_TestStruct(v, NULL, &p, &err);
934     error_free_or_abort(&err);
935     g_assert(!p);
936 
937     v = visitor_input_test_init(data, "{}");
938     visit_type_int(v, NULL, &i, &err);
939     error_free_or_abort(&err);
940 
941     /* Make sure primitives and arrays cannot be confused */
942 
943     v = visitor_input_test_init(data, "1");
944     visit_type_strList(v, NULL, &q, &err);
945     error_free_or_abort(&err);
946     assert(!q);
947 
948     v = visitor_input_test_init(data, "[]");
949     visit_type_int(v, NULL, &i, &err);
950     error_free_or_abort(&err);
951 }
952 
953 static void test_visitor_in_fail_struct(TestInputVisitorData *data,
954                                         const void *unused)
955 {
956     TestStruct *p = NULL;
957     Error *err = NULL;
958     Visitor *v;
959 
960     v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
961 
962     visit_type_TestStruct(v, NULL, &p, &err);
963     error_free_or_abort(&err);
964     g_assert(!p);
965 }
966 
967 static void test_visitor_in_fail_struct_nested(TestInputVisitorData *data,
968                                                const void *unused)
969 {
970     UserDefTwo *udp = NULL;
971     Error *err = NULL;
972     Visitor *v;
973 
974     v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
975 
976     visit_type_UserDefTwo(v, NULL, &udp, &err);
977     error_free_or_abort(&err);
978     g_assert(!udp);
979 }
980 
981 static void test_visitor_in_fail_struct_in_list(TestInputVisitorData *data,
982                                                 const void *unused)
983 {
984     UserDefOneList *head = NULL;
985     Error *err = NULL;
986     Visitor *v;
987 
988     v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
989 
990     visit_type_UserDefOneList(v, NULL, &head, &err);
991     error_free_or_abort(&err);
992     g_assert(!head);
993 }
994 
995 static void test_visitor_in_fail_struct_missing(TestInputVisitorData *data,
996                                                 const void *unused)
997 {
998     Error *err = NULL;
999     Visitor *v;
1000     QObject *any;
1001     QNull *null;
1002     GenericAlternate *alt;
1003     bool present;
1004     int en;
1005     int64_t i64;
1006     uint32_t u32;
1007     int8_t i8;
1008     char *str;
1009     double dbl;
1010 
1011     v = visitor_input_test_init(data, "{ 'sub': [ {} ] }");
1012     visit_start_struct(v, NULL, NULL, 0, &error_abort);
1013     visit_start_struct(v, "struct", NULL, 0, &err);
1014     error_free_or_abort(&err);
1015     visit_start_list(v, "list", NULL, 0, &err);
1016     error_free_or_abort(&err);
1017     visit_start_alternate(v, "alternate", &alt, sizeof(*alt), &err);
1018     error_free_or_abort(&err);
1019     visit_optional(v, "optional", &present);
1020     g_assert(!present);
1021     visit_type_enum(v, "enum", &en, &EnumOne_lookup, &err);
1022     error_free_or_abort(&err);
1023     visit_type_int(v, "i64", &i64, &err);
1024     error_free_or_abort(&err);
1025     visit_type_uint32(v, "u32", &u32, &err);
1026     error_free_or_abort(&err);
1027     visit_type_int8(v, "i8", &i8, &err);
1028     error_free_or_abort(&err);
1029     visit_type_str(v, "i8", &str, &err);
1030     error_free_or_abort(&err);
1031     visit_type_number(v, "dbl", &dbl, &err);
1032     error_free_or_abort(&err);
1033     visit_type_any(v, "any", &any, &err);
1034     error_free_or_abort(&err);
1035     visit_type_null(v, "null", &null, &err);
1036     error_free_or_abort(&err);
1037     visit_start_list(v, "sub", NULL, 0, &error_abort);
1038     visit_start_struct(v, NULL, NULL, 0, &error_abort);
1039     visit_type_int(v, "i64", &i64, &err);
1040     error_free_or_abort(&err);
1041     visit_end_struct(v, NULL);
1042     visit_end_list(v, NULL);
1043     visit_end_struct(v, NULL);
1044 }
1045 
1046 static void test_visitor_in_fail_list(TestInputVisitorData *data,
1047                                       const void *unused)
1048 {
1049     int64_t i64 = -1;
1050     Error *err = NULL;
1051     Visitor *v;
1052 
1053     /* Unvisited list tail */
1054 
1055     v = visitor_input_test_init(data, "[ 1, 2, 3 ]");
1056 
1057     visit_start_list(v, NULL, NULL, 0, &error_abort);
1058     visit_type_int(v, NULL, &i64, &error_abort);
1059     g_assert_cmpint(i64, ==, 1);
1060     visit_type_int(v, NULL, &i64, &error_abort);
1061     g_assert_cmpint(i64, ==, 2);
1062     visit_check_list(v, &err);
1063     error_free_or_abort(&err);
1064     visit_end_list(v, NULL);
1065 
1066     /* Visit beyond end of list */
1067     v = visitor_input_test_init(data, "[]");
1068 
1069     visit_start_list(v, NULL, NULL, 0, &error_abort);
1070     visit_type_int(v, NULL, &i64, &err);
1071     error_free_or_abort(&err);
1072     visit_end_list(v, NULL);
1073 }
1074 
1075 static void test_visitor_in_fail_list_nested(TestInputVisitorData *data,
1076                                              const void *unused)
1077 {
1078     int64_t i64 = -1;
1079     Error *err = NULL;
1080     Visitor *v;
1081 
1082     /* Unvisited nested list tail */
1083 
1084     v = visitor_input_test_init(data, "[ 0, [ 1, 2, 3 ] ]");
1085 
1086     visit_start_list(v, NULL, NULL, 0, &error_abort);
1087     visit_type_int(v, NULL, &i64, &error_abort);
1088     g_assert_cmpint(i64, ==, 0);
1089     visit_start_list(v, NULL, NULL, 0, &error_abort);
1090     visit_type_int(v, NULL, &i64, &error_abort);
1091     g_assert_cmpint(i64, ==, 1);
1092     visit_check_list(v, &err);
1093     error_free_or_abort(&err);
1094     visit_end_list(v, NULL);
1095     visit_check_list(v, &error_abort);
1096     visit_end_list(v, NULL);
1097 }
1098 
1099 static void test_visitor_in_fail_union_flat(TestInputVisitorData *data,
1100                                             const void *unused)
1101 {
1102     UserDefFlatUnion *tmp = NULL;
1103     Error *err = NULL;
1104     Visitor *v;
1105 
1106     v = visitor_input_test_init(data, "{ 'enum1': 'value2', 'string': 'c', 'integer': 41, 'boolean': true }");
1107 
1108     visit_type_UserDefFlatUnion(v, NULL, &tmp, &err);
1109     error_free_or_abort(&err);
1110     g_assert(!tmp);
1111 }
1112 
1113 static void test_visitor_in_fail_union_flat_no_discrim(TestInputVisitorData *data,
1114                                                        const void *unused)
1115 {
1116     UserDefFlatUnion2 *tmp = NULL;
1117     Error *err = NULL;
1118     Visitor *v;
1119 
1120     /* test situation where discriminator field ('enum1' here) is missing */
1121     v = visitor_input_test_init(data, "{ 'integer': 42, 'string': 'c', 'string1': 'd', 'string2': 'e' }");
1122 
1123     visit_type_UserDefFlatUnion2(v, NULL, &tmp, &err);
1124     error_free_or_abort(&err);
1125     g_assert(!tmp);
1126 }
1127 
1128 static void test_visitor_in_fail_alternate(TestInputVisitorData *data,
1129                                            const void *unused)
1130 {
1131     UserDefAlternate *tmp;
1132     Visitor *v;
1133     Error *err = NULL;
1134 
1135     v = visitor_input_test_init(data, "3.14");
1136 
1137     visit_type_UserDefAlternate(v, NULL, &tmp, &err);
1138     error_free_or_abort(&err);
1139     g_assert(!tmp);
1140 }
1141 
1142 static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data,
1143                                               const QLitObject *qlit)
1144 {
1145     g_autoptr(SchemaInfoList) schema = NULL;
1146     QObject *obj = qobject_from_qlit(qlit);
1147     Visitor *v;
1148 
1149     v = qobject_input_visitor_new(obj);
1150 
1151     visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
1152     g_assert(schema);
1153 
1154     qobject_unref(obj);
1155     visit_free(v);
1156 }
1157 
1158 static void test_visitor_in_qmp_introspect(TestInputVisitorData *data,
1159                                            const void *unused)
1160 {
1161     do_test_visitor_in_qmp_introspect(data, &test_qmp_schema_qlit);
1162 }
1163 
1164 int main(int argc, char **argv)
1165 {
1166     g_test_init(&argc, &argv, NULL);
1167 
1168     input_visitor_test_add("/visitor/input/int",
1169                            NULL, test_visitor_in_int);
1170     input_visitor_test_add("/visitor/input/uint",
1171                            NULL, test_visitor_in_uint);
1172     input_visitor_test_add("/visitor/input/int_overflow",
1173                            NULL, test_visitor_in_int_overflow);
1174     input_visitor_test_add("/visitor/input/int_keyval",
1175                            NULL, test_visitor_in_int_keyval);
1176     input_visitor_test_add("/visitor/input/int_str_keyval",
1177                            NULL, test_visitor_in_int_str_keyval);
1178     input_visitor_test_add("/visitor/input/int_str_fail",
1179                            NULL, test_visitor_in_int_str_fail);
1180     input_visitor_test_add("/visitor/input/bool",
1181                            NULL, test_visitor_in_bool);
1182     input_visitor_test_add("/visitor/input/bool_keyval",
1183                            NULL, test_visitor_in_bool_keyval);
1184     input_visitor_test_add("/visitor/input/bool_str_keyval",
1185                            NULL, test_visitor_in_bool_str_keyval);
1186     input_visitor_test_add("/visitor/input/bool_str_fail",
1187                            NULL, test_visitor_in_bool_str_fail);
1188     input_visitor_test_add("/visitor/input/number",
1189                            NULL, test_visitor_in_number);
1190     input_visitor_test_add("/visitor/input/large_number",
1191                            NULL, test_visitor_in_large_number);
1192     input_visitor_test_add("/visitor/input/number_keyval",
1193                            NULL, test_visitor_in_number_keyval);
1194     input_visitor_test_add("/visitor/input/number_str_keyval",
1195                            NULL, test_visitor_in_number_str_keyval);
1196     input_visitor_test_add("/visitor/input/number_str_fail",
1197                            NULL, test_visitor_in_number_str_fail);
1198     input_visitor_test_add("/visitor/input/size_str_keyval",
1199                            NULL, test_visitor_in_size_str_keyval);
1200     input_visitor_test_add("/visitor/input/size_str_fail",
1201                            NULL, test_visitor_in_size_str_fail);
1202     input_visitor_test_add("/visitor/input/string",
1203                            NULL, test_visitor_in_string);
1204     input_visitor_test_add("/visitor/input/enum",
1205                            NULL, test_visitor_in_enum);
1206     input_visitor_test_add("/visitor/input/struct",
1207                            NULL, test_visitor_in_struct);
1208     input_visitor_test_add("/visitor/input/struct-nested",
1209                            NULL, test_visitor_in_struct_nested);
1210     input_visitor_test_add("/visitor/input/list2",
1211                            NULL, test_visitor_in_list_struct);
1212     input_visitor_test_add("/visitor/input/list",
1213                            NULL, test_visitor_in_list);
1214     input_visitor_test_add("/visitor/input/any",
1215                            NULL, test_visitor_in_any);
1216     input_visitor_test_add("/visitor/input/null",
1217                            NULL, test_visitor_in_null);
1218     input_visitor_test_add("/visitor/input/union-flat",
1219                            NULL, test_visitor_in_union_flat);
1220     input_visitor_test_add("/visitor/input/alternate",
1221                            NULL, test_visitor_in_alternate);
1222     input_visitor_test_add("/visitor/input/errors",
1223                            NULL, test_visitor_in_errors);
1224     input_visitor_test_add("/visitor/input/wrong-type",
1225                            NULL, test_visitor_in_wrong_type);
1226     input_visitor_test_add("/visitor/input/alternate-number",
1227                            NULL, test_visitor_in_alternate_number);
1228     input_visitor_test_add("/visitor/input/alternate-list",
1229                            NULL, test_visitor_in_alternate_list);
1230     input_visitor_test_add("/visitor/input/fail/struct",
1231                            NULL, test_visitor_in_fail_struct);
1232     input_visitor_test_add("/visitor/input/fail/struct-nested",
1233                            NULL, test_visitor_in_fail_struct_nested);
1234     input_visitor_test_add("/visitor/input/fail/struct-in-list",
1235                            NULL, test_visitor_in_fail_struct_in_list);
1236     input_visitor_test_add("/visitor/input/fail/struct-missing",
1237                            NULL, test_visitor_in_fail_struct_missing);
1238     input_visitor_test_add("/visitor/input/fail/list",
1239                            NULL, test_visitor_in_fail_list);
1240     input_visitor_test_add("/visitor/input/fail/list-nested",
1241                            NULL, test_visitor_in_fail_list_nested);
1242     input_visitor_test_add("/visitor/input/fail/union-flat",
1243                            NULL, test_visitor_in_fail_union_flat);
1244     input_visitor_test_add("/visitor/input/fail/union-flat-no-discriminator",
1245                            NULL, test_visitor_in_fail_union_flat_no_discrim);
1246     input_visitor_test_add("/visitor/input/fail/alternate",
1247                            NULL, test_visitor_in_fail_alternate);
1248     input_visitor_test_add("/visitor/input/qapi-introspect",
1249                            NULL, test_visitor_in_qmp_introspect);
1250 
1251     g_test_run();
1252 
1253     return 0;
1254 }
1255