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