]> git.proxmox.com Git - mirror_qemu.git/blame - tests/test-qobject-input-visitor.c
qom: Make object_property_set_qobject()'s input visitor strict
[mirror_qemu.git] / tests / test-qobject-input-visitor.c
CommitLineData
d88f5fd1 1/*
b3db211f 2 * QObject Input Visitor unit-tests.
d88f5fd1 3 *
68d07839 4 * Copyright (C) 2011-2016 Red Hat Inc.
d88f5fd1
LC
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
681c28a3 13#include "qemu/osdep.h"
d88f5fd1 14
79ee7df8 15#include "qemu-common.h"
da34e65c 16#include "qapi/error.h"
b3db211f 17#include "qapi/qobject-input-visitor.h"
d88f5fd1
LC
18#include "test-qapi-types.h"
19#include "test-qapi-visit.h"
7b1b5d19 20#include "qapi/qmp/types.h"
c7eb39cb 21#include "qapi/qmp/qjson.h"
d88f5fd1
LC
22
23typedef struct TestInputVisitorData {
24 QObject *obj;
b70ce101 25 Visitor *qiv;
d88f5fd1
LC
26} TestInputVisitorData;
27
28static 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) {
b70ce101 35 visit_free(data->qiv);
d88f5fd1
LC
36 data->qiv = NULL;
37 }
38}
39
0920a171
EB
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()). */
43static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
44 const char *json_string,
45 va_list *ap)
46{
b18f1141
EB
47 visitor_input_teardown(data, NULL);
48
0920a171
EB
49 data->obj = qobject_from_jsonv(json_string, ap);
50 g_assert(data->obj);
51
09e68369 52 data->qiv = qobject_input_visitor_new(data->obj, false);
0920a171 53 g_assert(data->qiv);
b70ce101 54 return data->qiv;
0920a171
EB
55}
56
aba2107a
SW
57static GCC_FMT_ATTR(2, 3)
58Visitor *visitor_input_test_init(TestInputVisitorData *data,
59 const char *json_string, ...)
d88f5fd1
LC
60{
61 Visitor *v;
62 va_list ap;
63
64 va_start(ap, json_string);
0920a171 65 v = visitor_input_test_init_internal(data, json_string, &ap);
d88f5fd1 66 va_end(ap);
d88f5fd1
LC
67 return v;
68}
69
199e0f17
MR
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 */
77static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
78 const char *json_string)
79{
0920a171 80 return visitor_input_test_init_internal(data, json_string, NULL);
199e0f17
MR
81}
82
d88f5fd1
LC
83static void test_visitor_in_int(TestInputVisitorData *data,
84 const void *unused)
85{
29a6731a
EB
86 int64_t res = 0;
87 int value = -42;
d88f5fd1
LC
88 Visitor *v;
89
29a6731a 90 v = visitor_input_test_init(data, "%d", value);
d88f5fd1 91
51e72bc1 92 visit_type_int(v, NULL, &res, &error_abort);
d88f5fd1
LC
93 g_assert_cmpint(res, ==, value);
94}
95
e92cfa0d
MR
96static void test_visitor_in_int_overflow(TestInputVisitorData *data,
97 const void *unused)
98{
99 int64_t res = 0;
e940f543 100 Error *err = NULL;
e92cfa0d
MR
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
51e72bc1 109 visit_type_int(v, NULL, &res, &err);
a12a5a1a 110 error_free_or_abort(&err);
e92cfa0d
MR
111}
112
d88f5fd1
LC
113static void test_visitor_in_bool(TestInputVisitorData *data,
114 const void *unused)
115{
d88f5fd1
LC
116 bool res = false;
117 Visitor *v;
118
119 v = visitor_input_test_init(data, "true");
120
51e72bc1 121 visit_type_bool(v, NULL, &res, &error_abort);
d88f5fd1
LC
122 g_assert_cmpint(res, ==, true);
123}
124
125static void test_visitor_in_number(TestInputVisitorData *data,
126 const void *unused)
127{
128 double res = 0, value = 3.14;
d88f5fd1
LC
129 Visitor *v;
130
131 v = visitor_input_test_init(data, "%f", value);
132
51e72bc1 133 visit_type_number(v, NULL, &res, &error_abort);
d88f5fd1
LC
134 g_assert_cmpfloat(res, ==, value);
135}
136
137static void test_visitor_in_string(TestInputVisitorData *data,
138 const void *unused)
139{
140 char *res = NULL, *value = (char *) "Q E M U";
d88f5fd1
LC
141 Visitor *v;
142
143 v = visitor_input_test_init(data, "%s", value);
144
51e72bc1 145 visit_type_str(v, NULL, &res, &error_abort);
d88f5fd1
LC
146 g_assert_cmpstr(res, ==, value);
147
148 g_free(res);
149}
150
151static void test_visitor_in_enum(TestInputVisitorData *data,
152 const void *unused)
153{
d88f5fd1
LC
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
51e72bc1 162 visit_type_EnumOne(v, NULL, &res, &error_abort);
d88f5fd1 163 g_assert_cmpint(i, ==, res);
d88f5fd1 164 }
d88f5fd1
LC
165}
166
d88f5fd1
LC
167
168static void test_visitor_in_struct(TestInputVisitorData *data,
169 const void *unused)
170{
171 TestStruct *p = NULL;
d88f5fd1
LC
172 Visitor *v;
173
174 v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
175
51e72bc1 176 visit_type_TestStruct(v, NULL, &p, &error_abort);
d88f5fd1
LC
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
d88f5fd1
LC
185static void test_visitor_in_struct_nested(TestInputVisitorData *data,
186 const void *unused)
187{
b6fcf32d 188 UserDefTwo *udp = NULL;
d88f5fd1
LC
189 Visitor *v;
190
b6fcf32d
EB
191 v = visitor_input_test_init(data, "{ 'string0': 'string0', "
192 "'dict1': { 'string1': 'string1', "
193 "'dict2': { 'userdef': { 'integer': 42, "
194 "'string': 'string' }, 'string': 'string2'}}}");
d88f5fd1 195
51e72bc1 196 visit_type_UserDefTwo(v, NULL, &udp, &error_abort);
d88f5fd1 197
b18f1141
EB
198 g_assert_cmpstr(udp->string0, ==, "string0");
199 g_assert_cmpstr(udp->dict1->string1, ==, "string1");
ddf21908 200 g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
b18f1141
EB
201 g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
202 g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
6446a592
EB
203 g_assert(udp->dict1->has_dict3 == false);
204
b18f1141 205 qapi_free_UserDefTwo(udp);
d88f5fd1
LC
206}
207
208static void test_visitor_in_list(TestInputVisitorData *data,
209 const void *unused)
210{
211 UserDefOneList *item, *head = NULL;
d88f5fd1
LC
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
51e72bc1 217 visit_type_UserDefOneList(v, NULL, &head, &error_abort);
d88f5fd1
LC
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);
ddf21908 225 g_assert_cmpint(item->value->integer, ==, 42 + i);
d88f5fd1
LC
226 }
227
228 qapi_free_UserDefOneList(head);
2533377c
EB
229 head = NULL;
230
231 /* An empty list is valid */
232 v = visitor_input_test_init(data, "[]");
51e72bc1 233 visit_type_UserDefOneList(v, NULL, &head, &error_abort);
2533377c 234 g_assert(!head);
d88f5fd1
LC
235}
236
28770e05
MA
237static void test_visitor_in_any(TestInputVisitorData *data,
238 const void *unused)
239{
240 QObject *res = NULL;
28770e05
MA
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");
51e72bc1 249 visit_type_any(v, NULL, &res, &error_abort);
28770e05
MA
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' }");
51e72bc1 256 visit_type_any(v, NULL, &res, &error_abort);
28770e05
MA
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
3df016f1
EB
277static 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': '' }");
294 visit_start_struct(v, NULL, NULL, 0, &error_abort);
295 visit_type_null(v, "a", &error_abort);
296 visit_type_str(v, "a", &tmp, &err);
297 g_assert(!tmp);
298 error_free_or_abort(&err);
299 visit_type_null(v, "b", &err);
300 error_free_or_abort(&err);
15c2f669 301 visit_check_struct(v, &error_abort);
1158bb2a 302 visit_end_struct(v, NULL);
3df016f1
EB
303}
304
2fc00432
MA
305static void test_visitor_in_union_flat(TestInputVisitorData *data,
306 const void *unused)
307{
308 Visitor *v;
2fc00432 309 UserDefFlatUnion *tmp;
30594fe1 310 UserDefUnionBase *base;
2fc00432 311
5223070c
WX
312 v = visitor_input_test_init(data,
313 "{ 'enum1': 'value1', "
441cbac0 314 "'integer': 41, "
5223070c
WX
315 "'string': 'str', "
316 "'boolean': true }");
2fc00432 317
51e72bc1 318 visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
0f61af3e 319 g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
5223070c 320 g_assert_cmpstr(tmp->string, ==, "str");
441cbac0 321 g_assert_cmpint(tmp->integer, ==, 41);
544a3731 322 g_assert_cmpint(tmp->u.value1.boolean, ==, true);
30594fe1
EB
323
324 base = qapi_UserDefFlatUnion_base(tmp);
325 g_assert(&base->enum1 == &tmp->enum1);
326
2fc00432
MA
327 qapi_free_UserDefFlatUnion(tmp);
328}
329
ab045267
EB
330static void test_visitor_in_alternate(TestInputVisitorData *data,
331 const void *unused)
2c38b600
MA
332{
333 Visitor *v;
334 Error *err = NULL;
ab045267 335 UserDefAlternate *tmp;
68d07839 336 WrapAlternate *wrap;
2c38b600
MA
337
338 v = visitor_input_test_init(data, "42");
51e72bc1 339 visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
0426d53c 340 g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
c363acef 341 g_assert_cmpint(tmp->u.i, ==, 42);
ab045267 342 qapi_free_UserDefAlternate(tmp);
9c51b441
EB
343
344 v = visitor_input_test_init(data, "'string'");
51e72bc1 345 visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
0426d53c 346 g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
c363acef 347 g_assert_cmpstr(tmp->u.s, ==, "string");
9c51b441 348 qapi_free_UserDefAlternate(tmp);
9c51b441 349
68d07839
EB
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);
becceedc
EB
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);
544a3731
EB
357 g_assert_cmpint(tmp->u.udfu.u.value1.boolean, ==, true);
358 g_assert_cmpint(tmp->u.udfu.u.value1.has_a_b, ==, false);
68d07839
EB
359 qapi_free_UserDefAlternate(tmp);
360
9c51b441 361 v = visitor_input_test_init(data, "false");
51e72bc1 362 visit_type_UserDefAlternate(v, NULL, &tmp, &err);
a12a5a1a 363 error_free_or_abort(&err);
9c51b441 364 qapi_free_UserDefAlternate(tmp);
68d07839
EB
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);
becceedc
EB
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);
544a3731
EB
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);
68d07839 387 qapi_free_WrapAlternate(wrap);
9c51b441
EB
388}
389
390static 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");
51e72bc1 405 visit_type_AltStrBool(v, NULL, &asb, &err);
a12a5a1a 406 error_free_or_abort(&err);
9c51b441 407 qapi_free_AltStrBool(asb);
9c51b441 408
9c51b441 409 v = visitor_input_test_init(data, "42");
51e72bc1 410 visit_type_AltStrNum(v, NULL, &asn, &error_abort);
d00341af
EB
411 g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
412 g_assert_cmpfloat(asn->u.n, ==, 42);
9c51b441 413 qapi_free_AltStrNum(asn);
9c51b441
EB
414
415 v = visitor_input_test_init(data, "42");
51e72bc1 416 visit_type_AltNumStr(v, NULL, &ans, &error_abort);
d00341af
EB
417 g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
418 g_assert_cmpfloat(ans->u.n, ==, 42);
9c51b441 419 qapi_free_AltNumStr(ans);
9c51b441
EB
420
421 v = visitor_input_test_init(data, "42");
51e72bc1 422 visit_type_AltStrInt(v, NULL, &asi, &error_abort);
0426d53c 423 g_assert_cmpint(asi->type, ==, QTYPE_QINT);
c363acef 424 g_assert_cmpint(asi->u.i, ==, 42);
9c51b441 425 qapi_free_AltStrInt(asi);
9c51b441
EB
426
427 v = visitor_input_test_init(data, "42");
51e72bc1 428 visit_type_AltIntNum(v, NULL, &ain, &error_abort);
0426d53c 429 g_assert_cmpint(ain->type, ==, QTYPE_QINT);
c363acef 430 g_assert_cmpint(ain->u.i, ==, 42);
9c51b441 431 qapi_free_AltIntNum(ain);
9c51b441
EB
432
433 v = visitor_input_test_init(data, "42");
51e72bc1 434 visit_type_AltNumInt(v, NULL, &ani, &error_abort);
0426d53c 435 g_assert_cmpint(ani->type, ==, QTYPE_QINT);
c363acef 436 g_assert_cmpint(ani->u.i, ==, 42);
9c51b441 437 qapi_free_AltNumInt(ani);
9c51b441
EB
438
439 /* Parsing a double */
440
441 v = visitor_input_test_init(data, "42.5");
51e72bc1 442 visit_type_AltStrBool(v, NULL, &asb, &err);
a12a5a1a 443 error_free_or_abort(&err);
9c51b441 444 qapi_free_AltStrBool(asb);
9c51b441
EB
445
446 v = visitor_input_test_init(data, "42.5");
51e72bc1 447 visit_type_AltStrNum(v, NULL, &asn, &error_abort);
0426d53c 448 g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
c363acef 449 g_assert_cmpfloat(asn->u.n, ==, 42.5);
9c51b441 450 qapi_free_AltStrNum(asn);
9c51b441
EB
451
452 v = visitor_input_test_init(data, "42.5");
51e72bc1 453 visit_type_AltNumStr(v, NULL, &ans, &error_abort);
0426d53c 454 g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
c363acef 455 g_assert_cmpfloat(ans->u.n, ==, 42.5);
9c51b441 456 qapi_free_AltNumStr(ans);
9c51b441
EB
457
458 v = visitor_input_test_init(data, "42.5");
51e72bc1 459 visit_type_AltStrInt(v, NULL, &asi, &err);
a12a5a1a 460 error_free_or_abort(&err);
9c51b441 461 qapi_free_AltStrInt(asi);
9c51b441
EB
462
463 v = visitor_input_test_init(data, "42.5");
51e72bc1 464 visit_type_AltIntNum(v, NULL, &ain, &error_abort);
0426d53c 465 g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT);
c363acef 466 g_assert_cmpfloat(ain->u.n, ==, 42.5);
9c51b441 467 qapi_free_AltIntNum(ain);
9c51b441
EB
468
469 v = visitor_input_test_init(data, "42.5");
51e72bc1 470 visit_type_AltNumInt(v, NULL, &ani, &error_abort);
0426d53c 471 g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT);
c363acef 472 g_assert_cmpfloat(ani->u.n, ==, 42.5);
9c51b441 473 qapi_free_AltNumInt(ani);
2c38b600
MA
474}
475
199e0f17
MR
476static void test_native_list_integer_helper(TestInputVisitorData *data,
477 const void *unused,
478 UserDefNativeListUnionKind kind)
479{
480 UserDefNativeListUnion *cvalue = NULL;
199e0f17
MR
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
51e72bc1 497 visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
199e0f17 498 g_assert(cvalue != NULL);
c363acef 499 g_assert_cmpint(cvalue->type, ==, kind);
199e0f17
MR
500
501 switch (kind) {
502 case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
503 intList *elem = NULL;
32bafa8f
EB
504 for (i = 0, elem = cvalue->u.integer.data;
505 elem; elem = elem->next, i++) {
199e0f17
MR
506 g_assert_cmpint(elem->value, ==, i);
507 }
508 break;
509 }
510 case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
511 int8List *elem = NULL;
32bafa8f 512 for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) {
199e0f17
MR
513 g_assert_cmpint(elem->value, ==, i);
514 }
515 break;
516 }
517 case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
518 int16List *elem = NULL;
32bafa8f 519 for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) {
199e0f17
MR
520 g_assert_cmpint(elem->value, ==, i);
521 }
522 break;
523 }
524 case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
525 int32List *elem = NULL;
32bafa8f 526 for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) {
199e0f17
MR
527 g_assert_cmpint(elem->value, ==, i);
528 }
529 break;
530 }
531 case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
532 int64List *elem = NULL;
32bafa8f 533 for (i = 0, elem = cvalue->u.s64.data; elem; elem = elem->next, i++) {
199e0f17
MR
534 g_assert_cmpint(elem->value, ==, i);
535 }
536 break;
537 }
538 case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
539 uint8List *elem = NULL;
32bafa8f 540 for (i = 0, elem = cvalue->u.u8.data; elem; elem = elem->next, i++) {
199e0f17
MR
541 g_assert_cmpint(elem->value, ==, i);
542 }
543 break;
544 }
545 case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
546 uint16List *elem = NULL;
32bafa8f 547 for (i = 0, elem = cvalue->u.u16.data; elem; elem = elem->next, i++) {
199e0f17
MR
548 g_assert_cmpint(elem->value, ==, i);
549 }
550 break;
551 }
552 case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
553 uint32List *elem = NULL;
32bafa8f 554 for (i = 0, elem = cvalue->u.u32.data; elem; elem = elem->next, i++) {
199e0f17
MR
555 g_assert_cmpint(elem->value, ==, i);
556 }
557 break;
558 }
559 case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
560 uint64List *elem = NULL;
32bafa8f 561 for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) {
199e0f17
MR
562 g_assert_cmpint(elem->value, ==, i);
563 }
564 break;
565 }
566 default:
dfc6f865 567 g_assert_not_reached();
199e0f17
MR
568 }
569
570 g_string_free(gstr_union, true);
571 g_string_free(gstr_list, true);
572 qapi_free_UserDefNativeListUnion(cvalue);
573}
574
575static 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
582static 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
589static 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
596static 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
603static 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
610static 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
617static 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
624static 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
631static 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
638static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
639 const void *unused)
640{
641 UserDefNativeListUnion *cvalue = NULL;
642 boolList *elem = NULL;
199e0f17
MR
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
51e72bc1 659 visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
199e0f17 660 g_assert(cvalue != NULL);
c363acef 661 g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
199e0f17 662
32bafa8f 663 for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next, i++) {
199e0f17
MR
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
672static void test_visitor_in_native_list_string(TestInputVisitorData *data,
673 const void *unused)
674{
675 UserDefNativeListUnion *cvalue = NULL;
676 strList *elem = NULL;
199e0f17
MR
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
51e72bc1 692 visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
199e0f17 693 g_assert(cvalue != NULL);
c363acef 694 g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
199e0f17 695
32bafa8f 696 for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) {
199e0f17
MR
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
709static void test_visitor_in_native_list_number(TestInputVisitorData *data,
710 const void *unused)
711{
712 UserDefNativeListUnion *cvalue = NULL;
713 numberList *elem = NULL;
199e0f17
MR
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
51e72bc1 729 visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
199e0f17 730 g_assert(cvalue != NULL);
c363acef 731 g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
199e0f17 732
32bafa8f 733 for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next, i++) {
199e0f17
MR
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
d88f5fd1 750static void input_visitor_test_add(const char *testpath,
b1d2e5f1
DB
751 const void *user_data,
752 void (*test_func)(TestInputVisitorData *data,
753 const void *user_data))
d88f5fd1 754{
b1d2e5f1 755 g_test_add(testpath, TestInputVisitorData, user_data, NULL, test_func,
d88f5fd1
LC
756 visitor_input_teardown);
757}
758
3dcf71f6
PB
759static void test_visitor_in_errors(TestInputVisitorData *data,
760 const void *unused)
761{
762 TestStruct *p = NULL;
e940f543 763 Error *err = NULL;
3dcf71f6 764 Visitor *v;
dd5ee2c2 765 strList *q = NULL;
9b4e38fe
EB
766 UserDefTwo *r = NULL;
767 WrapAlternate *s = NULL;
3dcf71f6 768
dd5ee2c2
EB
769 v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
770 "'string': -42 }");
3dcf71f6 771
51e72bc1 772 visit_type_TestStruct(v, NULL, &p, &err);
a12a5a1a 773 error_free_or_abort(&err);
68ab47e4 774 g_assert(!p);
dd5ee2c2
EB
775
776 v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
51e72bc1 777 visit_type_strList(v, NULL, &q, &err);
dd5ee2c2 778 error_free_or_abort(&err);
68ab47e4 779 assert(!q);
9b4e38fe
EB
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);
3dcf71f6
PB
790}
791
2533377c
EB
792static 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, "[]");
51e72bc1 804 visit_type_TestStruct(v, NULL, &p, &err);
2533377c
EB
805 error_free_or_abort(&err);
806 g_assert(!p);
807
808 v = visitor_input_test_init(data, "{}");
51e72bc1 809 visit_type_strList(v, NULL, &q, &err);
2533377c
EB
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");
51e72bc1 816 visit_type_TestStruct(v, NULL, &p, &err);
2533377c
EB
817 error_free_or_abort(&err);
818 g_assert(!p);
819
820 v = visitor_input_test_init(data, "{}");
51e72bc1 821 visit_type_int(v, NULL, &i, &err);
2533377c
EB
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");
51e72bc1 827 visit_type_strList(v, NULL, &q, &err);
2533377c
EB
828 error_free_or_abort(&err);
829 assert(!q);
830
831 v = visitor_input_test_init(data, "[]");
51e72bc1 832 visit_type_int(v, NULL, &i, &err);
2533377c
EB
833 error_free_or_abort(&err);
834}
835
d88f5fd1
LC
836int main(int argc, char **argv)
837{
d88f5fd1
LC
838 g_test_init(&argc, &argv, NULL);
839
840 input_visitor_test_add("/visitor/input/int",
b1d2e5f1 841 NULL, test_visitor_in_int);
e92cfa0d 842 input_visitor_test_add("/visitor/input/int_overflow",
b1d2e5f1 843 NULL, test_visitor_in_int_overflow);
d88f5fd1 844 input_visitor_test_add("/visitor/input/bool",
b1d2e5f1 845 NULL, test_visitor_in_bool);
d88f5fd1 846 input_visitor_test_add("/visitor/input/number",
b1d2e5f1 847 NULL, test_visitor_in_number);
d88f5fd1 848 input_visitor_test_add("/visitor/input/string",
b1d2e5f1 849 NULL, test_visitor_in_string);
d88f5fd1 850 input_visitor_test_add("/visitor/input/enum",
b1d2e5f1 851 NULL, test_visitor_in_enum);
d88f5fd1 852 input_visitor_test_add("/visitor/input/struct",
b1d2e5f1 853 NULL, test_visitor_in_struct);
d88f5fd1 854 input_visitor_test_add("/visitor/input/struct-nested",
b1d2e5f1 855 NULL, test_visitor_in_struct_nested);
d88f5fd1 856 input_visitor_test_add("/visitor/input/list",
b1d2e5f1 857 NULL, test_visitor_in_list);
28770e05 858 input_visitor_test_add("/visitor/input/any",
b1d2e5f1 859 NULL, test_visitor_in_any);
3df016f1 860 input_visitor_test_add("/visitor/input/null",
b1d2e5f1 861 NULL, test_visitor_in_null);
2fc00432 862 input_visitor_test_add("/visitor/input/union-flat",
b1d2e5f1 863 NULL, test_visitor_in_union_flat);
ab045267 864 input_visitor_test_add("/visitor/input/alternate",
b1d2e5f1 865 NULL, test_visitor_in_alternate);
3dcf71f6 866 input_visitor_test_add("/visitor/input/errors",
b1d2e5f1 867 NULL, test_visitor_in_errors);
2533377c 868 input_visitor_test_add("/visitor/input/wrong-type",
b1d2e5f1 869 NULL, test_visitor_in_wrong_type);
9c51b441 870 input_visitor_test_add("/visitor/input/alternate-number",
b1d2e5f1 871 NULL, test_visitor_in_alternate_number);
199e0f17 872 input_visitor_test_add("/visitor/input/native_list/int",
b1d2e5f1 873 NULL, test_visitor_in_native_list_int);
199e0f17 874 input_visitor_test_add("/visitor/input/native_list/int8",
b1d2e5f1 875 NULL, test_visitor_in_native_list_int8);
199e0f17 876 input_visitor_test_add("/visitor/input/native_list/int16",
b1d2e5f1 877 NULL, test_visitor_in_native_list_int16);
199e0f17 878 input_visitor_test_add("/visitor/input/native_list/int32",
b1d2e5f1 879 NULL, test_visitor_in_native_list_int32);
199e0f17 880 input_visitor_test_add("/visitor/input/native_list/int64",
b1d2e5f1 881 NULL, test_visitor_in_native_list_int64);
199e0f17 882 input_visitor_test_add("/visitor/input/native_list/uint8",
b1d2e5f1 883 NULL, test_visitor_in_native_list_uint8);
199e0f17 884 input_visitor_test_add("/visitor/input/native_list/uint16",
b1d2e5f1 885 NULL, test_visitor_in_native_list_uint16);
199e0f17 886 input_visitor_test_add("/visitor/input/native_list/uint32",
b1d2e5f1 887 NULL, test_visitor_in_native_list_uint32);
199e0f17 888 input_visitor_test_add("/visitor/input/native_list/uint64",
b1d2e5f1 889 NULL, test_visitor_in_native_list_uint64);
199e0f17 890 input_visitor_test_add("/visitor/input/native_list/bool",
b1d2e5f1 891 NULL, test_visitor_in_native_list_bool);
199e0f17 892 input_visitor_test_add("/visitor/input/native_list/str",
b1d2e5f1 893 NULL, test_visitor_in_native_list_string);
199e0f17 894 input_visitor_test_add("/visitor/input/native_list/number",
b1d2e5f1 895 NULL, test_visitor_in_native_list_number);
d88f5fd1
LC
896
897 g_test_run();
898
899 return 0;
900}