]>
Commit | Line | Data |
---|---|---|
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 <[email protected]> | |
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 | |
23 | typedef struct TestInputVisitorData { | |
24 | QObject *obj; | |
b70ce101 | 25 | Visitor *qiv; |
d88f5fd1 LC |
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) { | |
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()). */ | |
43 | static 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 |
57 | static GCC_FMT_ATTR(2, 3) |
58 | Visitor *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 | */ | |
77 | static 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 |
83 | static 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 |
96 | static 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 |
113 | static 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 | ||
125 | static 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 | ||
137 | static 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 | ||
151 | static 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 | |
168 | static 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 |
185 | static 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 | ||
208 | static 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 |
237 | static 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 |
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': '' }"); | |
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 |
305 | static 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 |
330 | static 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 | ||
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"); | |
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 |
476 | static 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 | ||
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; | |
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 | ||
672 | static 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 | ||
709 | static 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 | 750 | static 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 |
759 | static 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 |
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, "[]"); | |
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 |
836 | int 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 | } |