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