]> git.proxmox.com Git - mirror_qemu.git/blob - tests/test-qobject-input-visitor.c
test-qobject-input-visitor: Use strict visitor
[mirror_qemu.git] / tests / test-qobject-input-visitor.c
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 *
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
11 */
12
13 #include "qemu/osdep.h"
14
15 #include "qemu-common.h"
16 #include "qapi/error.h"
17 #include "qapi/qobject-input-visitor.h"
18 #include "test-qapi-types.h"
19 #include "test-qapi-visit.h"
20 #include "qapi/qmp/types.h"
21 #include "qapi/qmp/qjson.h"
22
23 typedef struct TestInputVisitorData {
24 QObject *obj;
25 Visitor *qiv;
26 } TestInputVisitorData;
27
28 static void visitor_input_teardown(TestInputVisitorData *data,
29 const void *unused)
30 {
31 qobject_decref(data->obj);
32 data->obj = NULL;
33
34 if (data->qiv) {
35 visit_free(data->qiv);
36 data->qiv = NULL;
37 }
38 }
39
40 /* The various test_init functions are provided instead of a test setup
41 function so that the JSON string used by the tests are kept in the test
42 functions (and not in main()). */
43 static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
44 const char *json_string,
45 va_list *ap)
46 {
47 visitor_input_teardown(data, NULL);
48
49 data->obj = qobject_from_jsonv(json_string, ap);
50 g_assert(data->obj);
51
52 data->qiv = qobject_input_visitor_new(data->obj, true);
53 g_assert(data->qiv);
54 return data->qiv;
55 }
56
57 static GCC_FMT_ATTR(2, 3)
58 Visitor *visitor_input_test_init(TestInputVisitorData *data,
59 const char *json_string, ...)
60 {
61 Visitor *v;
62 va_list ap;
63
64 va_start(ap, json_string);
65 v = visitor_input_test_init_internal(data, json_string, &ap);
66 va_end(ap);
67 return v;
68 }
69
70 /* similar to visitor_input_test_init(), but does not expect a string
71 * literal/format json_string argument and so can be used for
72 * programatically generated strings (and we can't pass in programatically
73 * generated strings via %s format parameters since qobject_from_jsonv()
74 * will wrap those in double-quotes and treat the entire object as a
75 * string)
76 */
77 static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
78 const char *json_string)
79 {
80 return visitor_input_test_init_internal(data, json_string, NULL);
81 }
82
83 static void test_visitor_in_int(TestInputVisitorData *data,
84 const void *unused)
85 {
86 int64_t res = 0;
87 int value = -42;
88 Visitor *v;
89
90 v = visitor_input_test_init(data, "%d", value);
91
92 visit_type_int(v, NULL, &res, &error_abort);
93 g_assert_cmpint(res, ==, value);
94 }
95
96 static void test_visitor_in_int_overflow(TestInputVisitorData *data,
97 const void *unused)
98 {
99 int64_t res = 0;
100 Error *err = NULL;
101 Visitor *v;
102
103 /* this will overflow a Qint/int64, so should be deserialized into
104 * a QFloat/double field instead, leading to an error if we pass it
105 * to visit_type_int. confirm this.
106 */
107 v = visitor_input_test_init(data, "%f", DBL_MAX);
108
109 visit_type_int(v, NULL, &res, &err);
110 error_free_or_abort(&err);
111 }
112
113 static void test_visitor_in_bool(TestInputVisitorData *data,
114 const void *unused)
115 {
116 bool res = false;
117 Visitor *v;
118
119 v = visitor_input_test_init(data, "true");
120
121 visit_type_bool(v, NULL, &res, &error_abort);
122 g_assert_cmpint(res, ==, true);
123 }
124
125 static void test_visitor_in_number(TestInputVisitorData *data,
126 const void *unused)
127 {
128 double res = 0, value = 3.14;
129 Visitor *v;
130
131 v = visitor_input_test_init(data, "%f", value);
132
133 visit_type_number(v, NULL, &res, &error_abort);
134 g_assert_cmpfloat(res, ==, value);
135 }
136
137 static void test_visitor_in_string(TestInputVisitorData *data,
138 const void *unused)
139 {
140 char *res = NULL, *value = (char *) "Q E M U";
141 Visitor *v;
142
143 v = visitor_input_test_init(data, "%s", value);
144
145 visit_type_str(v, NULL, &res, &error_abort);
146 g_assert_cmpstr(res, ==, value);
147
148 g_free(res);
149 }
150
151 static void test_visitor_in_enum(TestInputVisitorData *data,
152 const void *unused)
153 {
154 Visitor *v;
155 EnumOne i;
156
157 for (i = 0; EnumOne_lookup[i]; i++) {
158 EnumOne res = -1;
159
160 v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
161
162 visit_type_EnumOne(v, NULL, &res, &error_abort);
163 g_assert_cmpint(i, ==, res);
164 }
165 }
166
167
168 static void test_visitor_in_struct(TestInputVisitorData *data,
169 const void *unused)
170 {
171 TestStruct *p = NULL;
172 Visitor *v;
173
174 v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
175
176 visit_type_TestStruct(v, NULL, &p, &error_abort);
177 g_assert_cmpint(p->integer, ==, -42);
178 g_assert(p->boolean == true);
179 g_assert_cmpstr(p->string, ==, "foo");
180
181 g_free(p->string);
182 g_free(p);
183 }
184
185 static void test_visitor_in_struct_nested(TestInputVisitorData *data,
186 const void *unused)
187 {
188 UserDefTwo *udp = NULL;
189 Visitor *v;
190
191 v = visitor_input_test_init(data, "{ 'string0': 'string0', "
192 "'dict1': { 'string1': 'string1', "
193 "'dict2': { 'userdef': { 'integer': 42, "
194 "'string': 'string' }, 'string': 'string2'}}}");
195
196 visit_type_UserDefTwo(v, NULL, &udp, &error_abort);
197
198 g_assert_cmpstr(udp->string0, ==, "string0");
199 g_assert_cmpstr(udp->dict1->string1, ==, "string1");
200 g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
201 g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
202 g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
203 g_assert(udp->dict1->has_dict3 == false);
204
205 qapi_free_UserDefTwo(udp);
206 }
207
208 static void test_visitor_in_list(TestInputVisitorData *data,
209 const void *unused)
210 {
211 UserDefOneList *item, *head = NULL;
212 Visitor *v;
213 int i;
214
215 v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
216
217 visit_type_UserDefOneList(v, NULL, &head, &error_abort);
218 g_assert(head != NULL);
219
220 for (i = 0, item = head; item; item = item->next, i++) {
221 char string[12];
222
223 snprintf(string, sizeof(string), "string%d", i);
224 g_assert_cmpstr(item->value->string, ==, string);
225 g_assert_cmpint(item->value->integer, ==, 42 + i);
226 }
227
228 qapi_free_UserDefOneList(head);
229 head = NULL;
230
231 /* An empty list is valid */
232 v = visitor_input_test_init(data, "[]");
233 visit_type_UserDefOneList(v, NULL, &head, &error_abort);
234 g_assert(!head);
235 }
236
237 static void test_visitor_in_any(TestInputVisitorData *data,
238 const void *unused)
239 {
240 QObject *res = NULL;
241 Visitor *v;
242 QInt *qint;
243 QBool *qbool;
244 QString *qstring;
245 QDict *qdict;
246 QObject *qobj;
247
248 v = visitor_input_test_init(data, "-42");
249 visit_type_any(v, NULL, &res, &error_abort);
250 qint = qobject_to_qint(res);
251 g_assert(qint);
252 g_assert_cmpint(qint_get_int(qint), ==, -42);
253 qobject_decref(res);
254
255 v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
256 visit_type_any(v, NULL, &res, &error_abort);
257 qdict = qobject_to_qdict(res);
258 g_assert(qdict && qdict_size(qdict) == 3);
259 qobj = qdict_get(qdict, "integer");
260 g_assert(qobj);
261 qint = qobject_to_qint(qobj);
262 g_assert(qint);
263 g_assert_cmpint(qint_get_int(qint), ==, -42);
264 qobj = qdict_get(qdict, "boolean");
265 g_assert(qobj);
266 qbool = qobject_to_qbool(qobj);
267 g_assert(qbool);
268 g_assert(qbool_get_bool(qbool) == true);
269 qobj = qdict_get(qdict, "string");
270 g_assert(qobj);
271 qstring = qobject_to_qstring(qobj);
272 g_assert(qstring);
273 g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
274 qobject_decref(res);
275 }
276
277 static void test_visitor_in_null(TestInputVisitorData *data,
278 const void *unused)
279 {
280 Visitor *v;
281 Error *err = NULL;
282 char *tmp;
283
284 /*
285 * FIXME: Since QAPI doesn't know the 'null' type yet, we can't
286 * test visit_type_null() by reading into a QAPI struct then
287 * checking that it was populated correctly. The best we can do
288 * for now is ensure that we consumed null from the input, proven
289 * by the fact that we can't re-read the key; and that we detect
290 * when input is not null.
291 */
292
293 v = visitor_input_test_init(data, "{ 'a': null, 'b': '', 'c': null }");
294 visit_start_struct(v, NULL, NULL, 0, &error_abort);
295 visit_type_null(v, "a", &error_abort);
296 visit_type_null(v, "b", &err);
297 error_free_or_abort(&err);
298 visit_type_str(v, "c", &tmp, &err);
299 g_assert(!tmp);
300 error_free_or_abort(&err);
301 visit_check_struct(v, &error_abort);
302 visit_end_struct(v, NULL);
303 }
304
305 static void test_visitor_in_union_flat(TestInputVisitorData *data,
306 const void *unused)
307 {
308 Visitor *v;
309 UserDefFlatUnion *tmp;
310 UserDefUnionBase *base;
311
312 v = visitor_input_test_init(data,
313 "{ 'enum1': 'value1', "
314 "'integer': 41, "
315 "'string': 'str', "
316 "'boolean': true }");
317
318 visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
319 g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
320 g_assert_cmpstr(tmp->string, ==, "str");
321 g_assert_cmpint(tmp->integer, ==, 41);
322 g_assert_cmpint(tmp->u.value1.boolean, ==, true);
323
324 base = qapi_UserDefFlatUnion_base(tmp);
325 g_assert(&base->enum1 == &tmp->enum1);
326
327 qapi_free_UserDefFlatUnion(tmp);
328 }
329
330 static void test_visitor_in_alternate(TestInputVisitorData *data,
331 const void *unused)
332 {
333 Visitor *v;
334 Error *err = NULL;
335 UserDefAlternate *tmp;
336 WrapAlternate *wrap;
337
338 v = visitor_input_test_init(data, "42");
339 visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
340 g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
341 g_assert_cmpint(tmp->u.i, ==, 42);
342 qapi_free_UserDefAlternate(tmp);
343
344 v = visitor_input_test_init(data, "'string'");
345 visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
346 g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
347 g_assert_cmpstr(tmp->u.s, ==, "string");
348 qapi_free_UserDefAlternate(tmp);
349
350 v = visitor_input_test_init(data, "{'integer':1, 'string':'str', "
351 "'enum1':'value1', 'boolean':true}");
352 visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
353 g_assert_cmpint(tmp->type, ==, QTYPE_QDICT);
354 g_assert_cmpint(tmp->u.udfu.integer, ==, 1);
355 g_assert_cmpstr(tmp->u.udfu.string, ==, "str");
356 g_assert_cmpint(tmp->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
357 g_assert_cmpint(tmp->u.udfu.u.value1.boolean, ==, true);
358 g_assert_cmpint(tmp->u.udfu.u.value1.has_a_b, ==, false);
359 qapi_free_UserDefAlternate(tmp);
360
361 v = visitor_input_test_init(data, "false");
362 visit_type_UserDefAlternate(v, NULL, &tmp, &err);
363 error_free_or_abort(&err);
364 qapi_free_UserDefAlternate(tmp);
365
366 v = visitor_input_test_init(data, "{ 'alt': 42 }");
367 visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
368 g_assert_cmpint(wrap->alt->type, ==, QTYPE_QINT);
369 g_assert_cmpint(wrap->alt->u.i, ==, 42);
370 qapi_free_WrapAlternate(wrap);
371
372 v = visitor_input_test_init(data, "{ 'alt': 'string' }");
373 visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
374 g_assert_cmpint(wrap->alt->type, ==, QTYPE_QSTRING);
375 g_assert_cmpstr(wrap->alt->u.s, ==, "string");
376 qapi_free_WrapAlternate(wrap);
377
378 v = visitor_input_test_init(data, "{ 'alt': {'integer':1, 'string':'str', "
379 "'enum1':'value1', 'boolean':true} }");
380 visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
381 g_assert_cmpint(wrap->alt->type, ==, QTYPE_QDICT);
382 g_assert_cmpint(wrap->alt->u.udfu.integer, ==, 1);
383 g_assert_cmpstr(wrap->alt->u.udfu.string, ==, "str");
384 g_assert_cmpint(wrap->alt->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
385 g_assert_cmpint(wrap->alt->u.udfu.u.value1.boolean, ==, true);
386 g_assert_cmpint(wrap->alt->u.udfu.u.value1.has_a_b, ==, false);
387 qapi_free_WrapAlternate(wrap);
388 }
389
390 static void test_visitor_in_alternate_number(TestInputVisitorData *data,
391 const void *unused)
392 {
393 Visitor *v;
394 Error *err = NULL;
395 AltStrBool *asb;
396 AltStrNum *asn;
397 AltNumStr *ans;
398 AltStrInt *asi;
399 AltIntNum *ain;
400 AltNumInt *ani;
401
402 /* Parsing an int */
403
404 v = visitor_input_test_init(data, "42");
405 visit_type_AltStrBool(v, NULL, &asb, &err);
406 error_free_or_abort(&err);
407 qapi_free_AltStrBool(asb);
408
409 v = visitor_input_test_init(data, "42");
410 visit_type_AltStrNum(v, NULL, &asn, &error_abort);
411 g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
412 g_assert_cmpfloat(asn->u.n, ==, 42);
413 qapi_free_AltStrNum(asn);
414
415 v = visitor_input_test_init(data, "42");
416 visit_type_AltNumStr(v, NULL, &ans, &error_abort);
417 g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
418 g_assert_cmpfloat(ans->u.n, ==, 42);
419 qapi_free_AltNumStr(ans);
420
421 v = visitor_input_test_init(data, "42");
422 visit_type_AltStrInt(v, NULL, &asi, &error_abort);
423 g_assert_cmpint(asi->type, ==, QTYPE_QINT);
424 g_assert_cmpint(asi->u.i, ==, 42);
425 qapi_free_AltStrInt(asi);
426
427 v = visitor_input_test_init(data, "42");
428 visit_type_AltIntNum(v, NULL, &ain, &error_abort);
429 g_assert_cmpint(ain->type, ==, QTYPE_QINT);
430 g_assert_cmpint(ain->u.i, ==, 42);
431 qapi_free_AltIntNum(ain);
432
433 v = visitor_input_test_init(data, "42");
434 visit_type_AltNumInt(v, NULL, &ani, &error_abort);
435 g_assert_cmpint(ani->type, ==, QTYPE_QINT);
436 g_assert_cmpint(ani->u.i, ==, 42);
437 qapi_free_AltNumInt(ani);
438
439 /* Parsing a double */
440
441 v = visitor_input_test_init(data, "42.5");
442 visit_type_AltStrBool(v, NULL, &asb, &err);
443 error_free_or_abort(&err);
444 qapi_free_AltStrBool(asb);
445
446 v = visitor_input_test_init(data, "42.5");
447 visit_type_AltStrNum(v, NULL, &asn, &error_abort);
448 g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
449 g_assert_cmpfloat(asn->u.n, ==, 42.5);
450 qapi_free_AltStrNum(asn);
451
452 v = visitor_input_test_init(data, "42.5");
453 visit_type_AltNumStr(v, NULL, &ans, &error_abort);
454 g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
455 g_assert_cmpfloat(ans->u.n, ==, 42.5);
456 qapi_free_AltNumStr(ans);
457
458 v = visitor_input_test_init(data, "42.5");
459 visit_type_AltStrInt(v, NULL, &asi, &err);
460 error_free_or_abort(&err);
461 qapi_free_AltStrInt(asi);
462
463 v = visitor_input_test_init(data, "42.5");
464 visit_type_AltIntNum(v, NULL, &ain, &error_abort);
465 g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT);
466 g_assert_cmpfloat(ain->u.n, ==, 42.5);
467 qapi_free_AltIntNum(ain);
468
469 v = visitor_input_test_init(data, "42.5");
470 visit_type_AltNumInt(v, NULL, &ani, &error_abort);
471 g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT);
472 g_assert_cmpfloat(ani->u.n, ==, 42.5);
473 qapi_free_AltNumInt(ani);
474 }
475
476 static void test_native_list_integer_helper(TestInputVisitorData *data,
477 const void *unused,
478 UserDefNativeListUnionKind kind)
479 {
480 UserDefNativeListUnion *cvalue = NULL;
481 Visitor *v;
482 GString *gstr_list = g_string_new("");
483 GString *gstr_union = g_string_new("");
484 int i;
485
486 for (i = 0; i < 32; i++) {
487 g_string_append_printf(gstr_list, "%d", i);
488 if (i != 31) {
489 g_string_append(gstr_list, ", ");
490 }
491 }
492 g_string_append_printf(gstr_union, "{ 'type': '%s', 'data': [ %s ] }",
493 UserDefNativeListUnionKind_lookup[kind],
494 gstr_list->str);
495 v = visitor_input_test_init_raw(data, gstr_union->str);
496
497 visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
498 g_assert(cvalue != NULL);
499 g_assert_cmpint(cvalue->type, ==, kind);
500
501 switch (kind) {
502 case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
503 intList *elem = NULL;
504 for (i = 0, elem = cvalue->u.integer.data;
505 elem; elem = elem->next, i++) {
506 g_assert_cmpint(elem->value, ==, i);
507 }
508 break;
509 }
510 case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
511 int8List *elem = NULL;
512 for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) {
513 g_assert_cmpint(elem->value, ==, i);
514 }
515 break;
516 }
517 case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
518 int16List *elem = NULL;
519 for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) {
520 g_assert_cmpint(elem->value, ==, i);
521 }
522 break;
523 }
524 case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
525 int32List *elem = NULL;
526 for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) {
527 g_assert_cmpint(elem->value, ==, i);
528 }
529 break;
530 }
531 case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
532 int64List *elem = NULL;
533 for (i = 0, elem = cvalue->u.s64.data; elem; elem = elem->next, i++) {
534 g_assert_cmpint(elem->value, ==, i);
535 }
536 break;
537 }
538 case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
539 uint8List *elem = NULL;
540 for (i = 0, elem = cvalue->u.u8.data; elem; elem = elem->next, i++) {
541 g_assert_cmpint(elem->value, ==, i);
542 }
543 break;
544 }
545 case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
546 uint16List *elem = NULL;
547 for (i = 0, elem = cvalue->u.u16.data; elem; elem = elem->next, i++) {
548 g_assert_cmpint(elem->value, ==, i);
549 }
550 break;
551 }
552 case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
553 uint32List *elem = NULL;
554 for (i = 0, elem = cvalue->u.u32.data; elem; elem = elem->next, i++) {
555 g_assert_cmpint(elem->value, ==, i);
556 }
557 break;
558 }
559 case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
560 uint64List *elem = NULL;
561 for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) {
562 g_assert_cmpint(elem->value, ==, i);
563 }
564 break;
565 }
566 default:
567 g_assert_not_reached();
568 }
569
570 g_string_free(gstr_union, true);
571 g_string_free(gstr_list, true);
572 qapi_free_UserDefNativeListUnion(cvalue);
573 }
574
575 static void test_visitor_in_native_list_int(TestInputVisitorData *data,
576 const void *unused)
577 {
578 test_native_list_integer_helper(data, unused,
579 USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER);
580 }
581
582 static void test_visitor_in_native_list_int8(TestInputVisitorData *data,
583 const void *unused)
584 {
585 test_native_list_integer_helper(data, unused,
586 USER_DEF_NATIVE_LIST_UNION_KIND_S8);
587 }
588
589 static void test_visitor_in_native_list_int16(TestInputVisitorData *data,
590 const void *unused)
591 {
592 test_native_list_integer_helper(data, unused,
593 USER_DEF_NATIVE_LIST_UNION_KIND_S16);
594 }
595
596 static void test_visitor_in_native_list_int32(TestInputVisitorData *data,
597 const void *unused)
598 {
599 test_native_list_integer_helper(data, unused,
600 USER_DEF_NATIVE_LIST_UNION_KIND_S32);
601 }
602
603 static void test_visitor_in_native_list_int64(TestInputVisitorData *data,
604 const void *unused)
605 {
606 test_native_list_integer_helper(data, unused,
607 USER_DEF_NATIVE_LIST_UNION_KIND_S64);
608 }
609
610 static void test_visitor_in_native_list_uint8(TestInputVisitorData *data,
611 const void *unused)
612 {
613 test_native_list_integer_helper(data, unused,
614 USER_DEF_NATIVE_LIST_UNION_KIND_U8);
615 }
616
617 static void test_visitor_in_native_list_uint16(TestInputVisitorData *data,
618 const void *unused)
619 {
620 test_native_list_integer_helper(data, unused,
621 USER_DEF_NATIVE_LIST_UNION_KIND_U16);
622 }
623
624 static void test_visitor_in_native_list_uint32(TestInputVisitorData *data,
625 const void *unused)
626 {
627 test_native_list_integer_helper(data, unused,
628 USER_DEF_NATIVE_LIST_UNION_KIND_U32);
629 }
630
631 static void test_visitor_in_native_list_uint64(TestInputVisitorData *data,
632 const void *unused)
633 {
634 test_native_list_integer_helper(data, unused,
635 USER_DEF_NATIVE_LIST_UNION_KIND_U64);
636 }
637
638 static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
639 const void *unused)
640 {
641 UserDefNativeListUnion *cvalue = NULL;
642 boolList *elem = NULL;
643 Visitor *v;
644 GString *gstr_list = g_string_new("");
645 GString *gstr_union = g_string_new("");
646 int i;
647
648 for (i = 0; i < 32; i++) {
649 g_string_append_printf(gstr_list, "%s",
650 (i % 3 == 0) ? "true" : "false");
651 if (i != 31) {
652 g_string_append(gstr_list, ", ");
653 }
654 }
655 g_string_append_printf(gstr_union, "{ 'type': 'boolean', 'data': [ %s ] }",
656 gstr_list->str);
657 v = visitor_input_test_init_raw(data, gstr_union->str);
658
659 visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
660 g_assert(cvalue != NULL);
661 g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
662
663 for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next, i++) {
664 g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
665 }
666
667 g_string_free(gstr_union, true);
668 g_string_free(gstr_list, true);
669 qapi_free_UserDefNativeListUnion(cvalue);
670 }
671
672 static void test_visitor_in_native_list_string(TestInputVisitorData *data,
673 const void *unused)
674 {
675 UserDefNativeListUnion *cvalue = NULL;
676 strList *elem = NULL;
677 Visitor *v;
678 GString *gstr_list = g_string_new("");
679 GString *gstr_union = g_string_new("");
680 int i;
681
682 for (i = 0; i < 32; i++) {
683 g_string_append_printf(gstr_list, "'%d'", i);
684 if (i != 31) {
685 g_string_append(gstr_list, ", ");
686 }
687 }
688 g_string_append_printf(gstr_union, "{ 'type': 'string', 'data': [ %s ] }",
689 gstr_list->str);
690 v = visitor_input_test_init_raw(data, gstr_union->str);
691
692 visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
693 g_assert(cvalue != NULL);
694 g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
695
696 for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) {
697 gchar str[8];
698 sprintf(str, "%d", i);
699 g_assert_cmpstr(elem->value, ==, str);
700 }
701
702 g_string_free(gstr_union, true);
703 g_string_free(gstr_list, true);
704 qapi_free_UserDefNativeListUnion(cvalue);
705 }
706
707 #define DOUBLE_STR_MAX 16
708
709 static void test_visitor_in_native_list_number(TestInputVisitorData *data,
710 const void *unused)
711 {
712 UserDefNativeListUnion *cvalue = NULL;
713 numberList *elem = NULL;
714 Visitor *v;
715 GString *gstr_list = g_string_new("");
716 GString *gstr_union = g_string_new("");
717 int i;
718
719 for (i = 0; i < 32; i++) {
720 g_string_append_printf(gstr_list, "%f", (double)i / 3);
721 if (i != 31) {
722 g_string_append(gstr_list, ", ");
723 }
724 }
725 g_string_append_printf(gstr_union, "{ 'type': 'number', 'data': [ %s ] }",
726 gstr_list->str);
727 v = visitor_input_test_init_raw(data, gstr_union->str);
728
729 visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
730 g_assert(cvalue != NULL);
731 g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
732
733 for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next, i++) {
734 GString *double_expected = g_string_new("");
735 GString *double_actual = g_string_new("");
736
737 g_string_printf(double_expected, "%.6f", (double)i / 3);
738 g_string_printf(double_actual, "%.6f", elem->value);
739 g_assert_cmpstr(double_expected->str, ==, double_actual->str);
740
741 g_string_free(double_expected, true);
742 g_string_free(double_actual, true);
743 }
744
745 g_string_free(gstr_union, true);
746 g_string_free(gstr_list, true);
747 qapi_free_UserDefNativeListUnion(cvalue);
748 }
749
750 static void input_visitor_test_add(const char *testpath,
751 const void *user_data,
752 void (*test_func)(TestInputVisitorData *data,
753 const void *user_data))
754 {
755 g_test_add(testpath, TestInputVisitorData, user_data, NULL, test_func,
756 visitor_input_teardown);
757 }
758
759 static void test_visitor_in_errors(TestInputVisitorData *data,
760 const void *unused)
761 {
762 TestStruct *p = NULL;
763 Error *err = NULL;
764 Visitor *v;
765 strList *q = NULL;
766 UserDefTwo *r = NULL;
767 WrapAlternate *s = NULL;
768
769 v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
770 "'string': -42 }");
771
772 visit_type_TestStruct(v, NULL, &p, &err);
773 error_free_or_abort(&err);
774 g_assert(!p);
775
776 v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
777 visit_type_strList(v, NULL, &q, &err);
778 error_free_or_abort(&err);
779 assert(!q);
780
781 v = visitor_input_test_init(data, "{ 'str':'hi' }");
782 visit_type_UserDefTwo(v, NULL, &r, &err);
783 error_free_or_abort(&err);
784 assert(!r);
785
786 v = visitor_input_test_init(data, "{ }");
787 visit_type_WrapAlternate(v, NULL, &s, &err);
788 error_free_or_abort(&err);
789 assert(!s);
790 }
791
792 static void test_visitor_in_wrong_type(TestInputVisitorData *data,
793 const void *unused)
794 {
795 TestStruct *p = NULL;
796 Visitor *v;
797 strList *q = NULL;
798 int64_t i;
799 Error *err = NULL;
800
801 /* Make sure arrays and structs cannot be confused */
802
803 v = visitor_input_test_init(data, "[]");
804 visit_type_TestStruct(v, NULL, &p, &err);
805 error_free_or_abort(&err);
806 g_assert(!p);
807
808 v = visitor_input_test_init(data, "{}");
809 visit_type_strList(v, NULL, &q, &err);
810 error_free_or_abort(&err);
811 assert(!q);
812
813 /* Make sure primitives and struct cannot be confused */
814
815 v = visitor_input_test_init(data, "1");
816 visit_type_TestStruct(v, NULL, &p, &err);
817 error_free_or_abort(&err);
818 g_assert(!p);
819
820 v = visitor_input_test_init(data, "{}");
821 visit_type_int(v, NULL, &i, &err);
822 error_free_or_abort(&err);
823
824 /* Make sure primitives and arrays cannot be confused */
825
826 v = visitor_input_test_init(data, "1");
827 visit_type_strList(v, NULL, &q, &err);
828 error_free_or_abort(&err);
829 assert(!q);
830
831 v = visitor_input_test_init(data, "[]");
832 visit_type_int(v, NULL, &i, &err);
833 error_free_or_abort(&err);
834 }
835
836 int main(int argc, char **argv)
837 {
838 g_test_init(&argc, &argv, NULL);
839
840 input_visitor_test_add("/visitor/input/int",
841 NULL, test_visitor_in_int);
842 input_visitor_test_add("/visitor/input/int_overflow",
843 NULL, test_visitor_in_int_overflow);
844 input_visitor_test_add("/visitor/input/bool",
845 NULL, test_visitor_in_bool);
846 input_visitor_test_add("/visitor/input/number",
847 NULL, test_visitor_in_number);
848 input_visitor_test_add("/visitor/input/string",
849 NULL, test_visitor_in_string);
850 input_visitor_test_add("/visitor/input/enum",
851 NULL, test_visitor_in_enum);
852 input_visitor_test_add("/visitor/input/struct",
853 NULL, test_visitor_in_struct);
854 input_visitor_test_add("/visitor/input/struct-nested",
855 NULL, test_visitor_in_struct_nested);
856 input_visitor_test_add("/visitor/input/list",
857 NULL, test_visitor_in_list);
858 input_visitor_test_add("/visitor/input/any",
859 NULL, test_visitor_in_any);
860 input_visitor_test_add("/visitor/input/null",
861 NULL, test_visitor_in_null);
862 input_visitor_test_add("/visitor/input/union-flat",
863 NULL, test_visitor_in_union_flat);
864 input_visitor_test_add("/visitor/input/alternate",
865 NULL, test_visitor_in_alternate);
866 input_visitor_test_add("/visitor/input/errors",
867 NULL, test_visitor_in_errors);
868 input_visitor_test_add("/visitor/input/wrong-type",
869 NULL, test_visitor_in_wrong_type);
870 input_visitor_test_add("/visitor/input/alternate-number",
871 NULL, test_visitor_in_alternate_number);
872 input_visitor_test_add("/visitor/input/native_list/int",
873 NULL, test_visitor_in_native_list_int);
874 input_visitor_test_add("/visitor/input/native_list/int8",
875 NULL, test_visitor_in_native_list_int8);
876 input_visitor_test_add("/visitor/input/native_list/int16",
877 NULL, test_visitor_in_native_list_int16);
878 input_visitor_test_add("/visitor/input/native_list/int32",
879 NULL, test_visitor_in_native_list_int32);
880 input_visitor_test_add("/visitor/input/native_list/int64",
881 NULL, test_visitor_in_native_list_int64);
882 input_visitor_test_add("/visitor/input/native_list/uint8",
883 NULL, test_visitor_in_native_list_uint8);
884 input_visitor_test_add("/visitor/input/native_list/uint16",
885 NULL, test_visitor_in_native_list_uint16);
886 input_visitor_test_add("/visitor/input/native_list/uint32",
887 NULL, test_visitor_in_native_list_uint32);
888 input_visitor_test_add("/visitor/input/native_list/uint64",
889 NULL, test_visitor_in_native_list_uint64);
890 input_visitor_test_add("/visitor/input/native_list/bool",
891 NULL, test_visitor_in_native_list_bool);
892 input_visitor_test_add("/visitor/input/native_list/str",
893 NULL, test_visitor_in_native_list_string);
894 input_visitor_test_add("/visitor/input/native_list/number",
895 NULL, test_visitor_in_native_list_number);
896
897 g_test_run();
898
899 return 0;
900 }