]>
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 | #include <glib.h> |
d88f5fd1 | 15 | |
79ee7df8 | 16 | #include "qemu-common.h" |
da34e65c | 17 | #include "qapi/error.h" |
d88f5fd1 LC |
18 | #include "qapi/qmp-input-visitor.h" |
19 | #include "test-qapi-types.h" | |
20 | #include "test-qapi-visit.h" | |
7b1b5d19 | 21 | #include "qapi/qmp/types.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 | ||
54 | data->qiv = qmp_input_visitor_new(data->obj); | |
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 | ||
2fc00432 MA |
282 | static void test_visitor_in_union_flat(TestInputVisitorData *data, |
283 | const void *unused) | |
284 | { | |
285 | Visitor *v; | |
2fc00432 | 286 | UserDefFlatUnion *tmp; |
30594fe1 | 287 | UserDefUnionBase *base; |
2fc00432 | 288 | |
5223070c WX |
289 | v = visitor_input_test_init(data, |
290 | "{ 'enum1': 'value1', " | |
441cbac0 | 291 | "'integer': 41, " |
5223070c WX |
292 | "'string': 'str', " |
293 | "'boolean': true }"); | |
2fc00432 | 294 | |
51e72bc1 | 295 | visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort); |
0f61af3e | 296 | g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1); |
5223070c | 297 | g_assert_cmpstr(tmp->string, ==, "str"); |
441cbac0 | 298 | g_assert_cmpint(tmp->integer, ==, 41); |
544a3731 | 299 | g_assert_cmpint(tmp->u.value1.boolean, ==, true); |
30594fe1 EB |
300 | |
301 | base = qapi_UserDefFlatUnion_base(tmp); | |
302 | g_assert(&base->enum1 == &tmp->enum1); | |
303 | ||
2fc00432 MA |
304 | qapi_free_UserDefFlatUnion(tmp); |
305 | } | |
306 | ||
ab045267 EB |
307 | static void test_visitor_in_alternate(TestInputVisitorData *data, |
308 | const void *unused) | |
2c38b600 MA |
309 | { |
310 | Visitor *v; | |
311 | Error *err = NULL; | |
ab045267 | 312 | UserDefAlternate *tmp; |
68d07839 | 313 | WrapAlternate *wrap; |
2c38b600 MA |
314 | |
315 | v = visitor_input_test_init(data, "42"); | |
51e72bc1 | 316 | visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort); |
0426d53c | 317 | g_assert_cmpint(tmp->type, ==, QTYPE_QINT); |
c363acef | 318 | g_assert_cmpint(tmp->u.i, ==, 42); |
ab045267 | 319 | qapi_free_UserDefAlternate(tmp); |
9c51b441 EB |
320 | |
321 | v = visitor_input_test_init(data, "'string'"); | |
51e72bc1 | 322 | visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort); |
0426d53c | 323 | g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING); |
c363acef | 324 | g_assert_cmpstr(tmp->u.s, ==, "string"); |
9c51b441 | 325 | qapi_free_UserDefAlternate(tmp); |
9c51b441 | 326 | |
68d07839 EB |
327 | v = visitor_input_test_init(data, "{'integer':1, 'string':'str', " |
328 | "'enum1':'value1', 'boolean':true}"); | |
329 | visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort); | |
330 | g_assert_cmpint(tmp->type, ==, QTYPE_QDICT); | |
becceedc EB |
331 | g_assert_cmpint(tmp->u.udfu.integer, ==, 1); |
332 | g_assert_cmpstr(tmp->u.udfu.string, ==, "str"); | |
333 | g_assert_cmpint(tmp->u.udfu.enum1, ==, ENUM_ONE_VALUE1); | |
544a3731 EB |
334 | g_assert_cmpint(tmp->u.udfu.u.value1.boolean, ==, true); |
335 | g_assert_cmpint(tmp->u.udfu.u.value1.has_a_b, ==, false); | |
68d07839 EB |
336 | qapi_free_UserDefAlternate(tmp); |
337 | ||
9c51b441 | 338 | v = visitor_input_test_init(data, "false"); |
51e72bc1 | 339 | visit_type_UserDefAlternate(v, NULL, &tmp, &err); |
a12a5a1a | 340 | error_free_or_abort(&err); |
9c51b441 | 341 | qapi_free_UserDefAlternate(tmp); |
68d07839 EB |
342 | |
343 | v = visitor_input_test_init(data, "{ 'alt': 42 }"); | |
344 | visit_type_WrapAlternate(v, NULL, &wrap, &error_abort); | |
345 | g_assert_cmpint(wrap->alt->type, ==, QTYPE_QINT); | |
346 | g_assert_cmpint(wrap->alt->u.i, ==, 42); | |
347 | qapi_free_WrapAlternate(wrap); | |
348 | ||
349 | v = visitor_input_test_init(data, "{ 'alt': 'string' }"); | |
350 | visit_type_WrapAlternate(v, NULL, &wrap, &error_abort); | |
351 | g_assert_cmpint(wrap->alt->type, ==, QTYPE_QSTRING); | |
352 | g_assert_cmpstr(wrap->alt->u.s, ==, "string"); | |
353 | qapi_free_WrapAlternate(wrap); | |
354 | ||
355 | v = visitor_input_test_init(data, "{ 'alt': {'integer':1, 'string':'str', " | |
356 | "'enum1':'value1', 'boolean':true} }"); | |
357 | visit_type_WrapAlternate(v, NULL, &wrap, &error_abort); | |
358 | g_assert_cmpint(wrap->alt->type, ==, QTYPE_QDICT); | |
becceedc EB |
359 | g_assert_cmpint(wrap->alt->u.udfu.integer, ==, 1); |
360 | g_assert_cmpstr(wrap->alt->u.udfu.string, ==, "str"); | |
361 | g_assert_cmpint(wrap->alt->u.udfu.enum1, ==, ENUM_ONE_VALUE1); | |
544a3731 EB |
362 | g_assert_cmpint(wrap->alt->u.udfu.u.value1.boolean, ==, true); |
363 | g_assert_cmpint(wrap->alt->u.udfu.u.value1.has_a_b, ==, false); | |
68d07839 | 364 | qapi_free_WrapAlternate(wrap); |
9c51b441 EB |
365 | } |
366 | ||
367 | static void test_visitor_in_alternate_number(TestInputVisitorData *data, | |
368 | const void *unused) | |
369 | { | |
370 | Visitor *v; | |
371 | Error *err = NULL; | |
372 | AltStrBool *asb; | |
373 | AltStrNum *asn; | |
374 | AltNumStr *ans; | |
375 | AltStrInt *asi; | |
376 | AltIntNum *ain; | |
377 | AltNumInt *ani; | |
378 | ||
379 | /* Parsing an int */ | |
380 | ||
381 | v = visitor_input_test_init(data, "42"); | |
51e72bc1 | 382 | visit_type_AltStrBool(v, NULL, &asb, &err); |
a12a5a1a | 383 | error_free_or_abort(&err); |
9c51b441 | 384 | qapi_free_AltStrBool(asb); |
9c51b441 | 385 | |
9c51b441 | 386 | v = visitor_input_test_init(data, "42"); |
51e72bc1 | 387 | visit_type_AltStrNum(v, NULL, &asn, &error_abort); |
d00341af EB |
388 | g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT); |
389 | g_assert_cmpfloat(asn->u.n, ==, 42); | |
9c51b441 | 390 | qapi_free_AltStrNum(asn); |
9c51b441 EB |
391 | |
392 | v = visitor_input_test_init(data, "42"); | |
51e72bc1 | 393 | visit_type_AltNumStr(v, NULL, &ans, &error_abort); |
d00341af EB |
394 | g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT); |
395 | g_assert_cmpfloat(ans->u.n, ==, 42); | |
9c51b441 | 396 | qapi_free_AltNumStr(ans); |
9c51b441 EB |
397 | |
398 | v = visitor_input_test_init(data, "42"); | |
51e72bc1 | 399 | visit_type_AltStrInt(v, NULL, &asi, &error_abort); |
0426d53c | 400 | g_assert_cmpint(asi->type, ==, QTYPE_QINT); |
c363acef | 401 | g_assert_cmpint(asi->u.i, ==, 42); |
9c51b441 | 402 | qapi_free_AltStrInt(asi); |
9c51b441 EB |
403 | |
404 | v = visitor_input_test_init(data, "42"); | |
51e72bc1 | 405 | visit_type_AltIntNum(v, NULL, &ain, &error_abort); |
0426d53c | 406 | g_assert_cmpint(ain->type, ==, QTYPE_QINT); |
c363acef | 407 | g_assert_cmpint(ain->u.i, ==, 42); |
9c51b441 | 408 | qapi_free_AltIntNum(ain); |
9c51b441 EB |
409 | |
410 | v = visitor_input_test_init(data, "42"); | |
51e72bc1 | 411 | visit_type_AltNumInt(v, NULL, &ani, &error_abort); |
0426d53c | 412 | g_assert_cmpint(ani->type, ==, QTYPE_QINT); |
c363acef | 413 | g_assert_cmpint(ani->u.i, ==, 42); |
9c51b441 | 414 | qapi_free_AltNumInt(ani); |
9c51b441 EB |
415 | |
416 | /* Parsing a double */ | |
417 | ||
418 | v = visitor_input_test_init(data, "42.5"); | |
51e72bc1 | 419 | visit_type_AltStrBool(v, NULL, &asb, &err); |
a12a5a1a | 420 | error_free_or_abort(&err); |
9c51b441 | 421 | qapi_free_AltStrBool(asb); |
9c51b441 EB |
422 | |
423 | v = visitor_input_test_init(data, "42.5"); | |
51e72bc1 | 424 | visit_type_AltStrNum(v, NULL, &asn, &error_abort); |
0426d53c | 425 | g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT); |
c363acef | 426 | g_assert_cmpfloat(asn->u.n, ==, 42.5); |
9c51b441 | 427 | qapi_free_AltStrNum(asn); |
9c51b441 EB |
428 | |
429 | v = visitor_input_test_init(data, "42.5"); | |
51e72bc1 | 430 | visit_type_AltNumStr(v, NULL, &ans, &error_abort); |
0426d53c | 431 | g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT); |
c363acef | 432 | g_assert_cmpfloat(ans->u.n, ==, 42.5); |
9c51b441 | 433 | qapi_free_AltNumStr(ans); |
9c51b441 EB |
434 | |
435 | v = visitor_input_test_init(data, "42.5"); | |
51e72bc1 | 436 | visit_type_AltStrInt(v, NULL, &asi, &err); |
a12a5a1a | 437 | error_free_or_abort(&err); |
9c51b441 | 438 | qapi_free_AltStrInt(asi); |
9c51b441 EB |
439 | |
440 | v = visitor_input_test_init(data, "42.5"); | |
51e72bc1 | 441 | visit_type_AltIntNum(v, NULL, &ain, &error_abort); |
0426d53c | 442 | g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT); |
c363acef | 443 | g_assert_cmpfloat(ain->u.n, ==, 42.5); |
9c51b441 | 444 | qapi_free_AltIntNum(ain); |
9c51b441 EB |
445 | |
446 | v = visitor_input_test_init(data, "42.5"); | |
51e72bc1 | 447 | visit_type_AltNumInt(v, NULL, &ani, &error_abort); |
0426d53c | 448 | g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT); |
c363acef | 449 | g_assert_cmpfloat(ani->u.n, ==, 42.5); |
9c51b441 | 450 | qapi_free_AltNumInt(ani); |
2c38b600 MA |
451 | } |
452 | ||
199e0f17 MR |
453 | static void test_native_list_integer_helper(TestInputVisitorData *data, |
454 | const void *unused, | |
455 | UserDefNativeListUnionKind kind) | |
456 | { | |
457 | UserDefNativeListUnion *cvalue = NULL; | |
199e0f17 MR |
458 | Visitor *v; |
459 | GString *gstr_list = g_string_new(""); | |
460 | GString *gstr_union = g_string_new(""); | |
461 | int i; | |
462 | ||
463 | for (i = 0; i < 32; i++) { | |
464 | g_string_append_printf(gstr_list, "%d", i); | |
465 | if (i != 31) { | |
466 | g_string_append(gstr_list, ", "); | |
467 | } | |
468 | } | |
469 | g_string_append_printf(gstr_union, "{ 'type': '%s', 'data': [ %s ] }", | |
470 | UserDefNativeListUnionKind_lookup[kind], | |
471 | gstr_list->str); | |
472 | v = visitor_input_test_init_raw(data, gstr_union->str); | |
473 | ||
51e72bc1 | 474 | visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort); |
199e0f17 | 475 | g_assert(cvalue != NULL); |
c363acef | 476 | g_assert_cmpint(cvalue->type, ==, kind); |
199e0f17 MR |
477 | |
478 | switch (kind) { | |
479 | case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: { | |
480 | intList *elem = NULL; | |
32bafa8f EB |
481 | for (i = 0, elem = cvalue->u.integer.data; |
482 | elem; elem = elem->next, i++) { | |
199e0f17 MR |
483 | g_assert_cmpint(elem->value, ==, i); |
484 | } | |
485 | break; | |
486 | } | |
487 | case USER_DEF_NATIVE_LIST_UNION_KIND_S8: { | |
488 | int8List *elem = NULL; | |
32bafa8f | 489 | for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) { |
199e0f17 MR |
490 | g_assert_cmpint(elem->value, ==, i); |
491 | } | |
492 | break; | |
493 | } | |
494 | case USER_DEF_NATIVE_LIST_UNION_KIND_S16: { | |
495 | int16List *elem = NULL; | |
32bafa8f | 496 | for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) { |
199e0f17 MR |
497 | g_assert_cmpint(elem->value, ==, i); |
498 | } | |
499 | break; | |
500 | } | |
501 | case USER_DEF_NATIVE_LIST_UNION_KIND_S32: { | |
502 | int32List *elem = NULL; | |
32bafa8f | 503 | for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) { |
199e0f17 MR |
504 | g_assert_cmpint(elem->value, ==, i); |
505 | } | |
506 | break; | |
507 | } | |
508 | case USER_DEF_NATIVE_LIST_UNION_KIND_S64: { | |
509 | int64List *elem = NULL; | |
32bafa8f | 510 | for (i = 0, elem = cvalue->u.s64.data; 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_U8: { | |
516 | uint8List *elem = NULL; | |
32bafa8f | 517 | for (i = 0, elem = cvalue->u.u8.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_U16: { | |
523 | uint16List *elem = NULL; | |
32bafa8f | 524 | for (i = 0, elem = cvalue->u.u16.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_U32: { | |
530 | uint32List *elem = NULL; | |
32bafa8f | 531 | for (i = 0, elem = cvalue->u.u32.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_U64: { | |
537 | uint64List *elem = NULL; | |
32bafa8f | 538 | for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) { |
199e0f17 MR |
539 | g_assert_cmpint(elem->value, ==, i); |
540 | } | |
541 | break; | |
542 | } | |
543 | default: | |
dfc6f865 | 544 | g_assert_not_reached(); |
199e0f17 MR |
545 | } |
546 | ||
547 | g_string_free(gstr_union, true); | |
548 | g_string_free(gstr_list, true); | |
549 | qapi_free_UserDefNativeListUnion(cvalue); | |
550 | } | |
551 | ||
552 | static void test_visitor_in_native_list_int(TestInputVisitorData *data, | |
553 | const void *unused) | |
554 | { | |
555 | test_native_list_integer_helper(data, unused, | |
556 | USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER); | |
557 | } | |
558 | ||
559 | static void test_visitor_in_native_list_int8(TestInputVisitorData *data, | |
560 | const void *unused) | |
561 | { | |
562 | test_native_list_integer_helper(data, unused, | |
563 | USER_DEF_NATIVE_LIST_UNION_KIND_S8); | |
564 | } | |
565 | ||
566 | static void test_visitor_in_native_list_int16(TestInputVisitorData *data, | |
567 | const void *unused) | |
568 | { | |
569 | test_native_list_integer_helper(data, unused, | |
570 | USER_DEF_NATIVE_LIST_UNION_KIND_S16); | |
571 | } | |
572 | ||
573 | static void test_visitor_in_native_list_int32(TestInputVisitorData *data, | |
574 | const void *unused) | |
575 | { | |
576 | test_native_list_integer_helper(data, unused, | |
577 | USER_DEF_NATIVE_LIST_UNION_KIND_S32); | |
578 | } | |
579 | ||
580 | static void test_visitor_in_native_list_int64(TestInputVisitorData *data, | |
581 | const void *unused) | |
582 | { | |
583 | test_native_list_integer_helper(data, unused, | |
584 | USER_DEF_NATIVE_LIST_UNION_KIND_S64); | |
585 | } | |
586 | ||
587 | static void test_visitor_in_native_list_uint8(TestInputVisitorData *data, | |
588 | const void *unused) | |
589 | { | |
590 | test_native_list_integer_helper(data, unused, | |
591 | USER_DEF_NATIVE_LIST_UNION_KIND_U8); | |
592 | } | |
593 | ||
594 | static void test_visitor_in_native_list_uint16(TestInputVisitorData *data, | |
595 | const void *unused) | |
596 | { | |
597 | test_native_list_integer_helper(data, unused, | |
598 | USER_DEF_NATIVE_LIST_UNION_KIND_U16); | |
599 | } | |
600 | ||
601 | static void test_visitor_in_native_list_uint32(TestInputVisitorData *data, | |
602 | const void *unused) | |
603 | { | |
604 | test_native_list_integer_helper(data, unused, | |
605 | USER_DEF_NATIVE_LIST_UNION_KIND_U32); | |
606 | } | |
607 | ||
608 | static void test_visitor_in_native_list_uint64(TestInputVisitorData *data, | |
609 | const void *unused) | |
610 | { | |
611 | test_native_list_integer_helper(data, unused, | |
612 | USER_DEF_NATIVE_LIST_UNION_KIND_U64); | |
613 | } | |
614 | ||
615 | static void test_visitor_in_native_list_bool(TestInputVisitorData *data, | |
616 | const void *unused) | |
617 | { | |
618 | UserDefNativeListUnion *cvalue = NULL; | |
619 | boolList *elem = NULL; | |
199e0f17 MR |
620 | Visitor *v; |
621 | GString *gstr_list = g_string_new(""); | |
622 | GString *gstr_union = g_string_new(""); | |
623 | int i; | |
624 | ||
625 | for (i = 0; i < 32; i++) { | |
626 | g_string_append_printf(gstr_list, "%s", | |
627 | (i % 3 == 0) ? "true" : "false"); | |
628 | if (i != 31) { | |
629 | g_string_append(gstr_list, ", "); | |
630 | } | |
631 | } | |
632 | g_string_append_printf(gstr_union, "{ 'type': 'boolean', 'data': [ %s ] }", | |
633 | gstr_list->str); | |
634 | v = visitor_input_test_init_raw(data, gstr_union->str); | |
635 | ||
51e72bc1 | 636 | visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort); |
199e0f17 | 637 | g_assert(cvalue != NULL); |
c363acef | 638 | g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN); |
199e0f17 | 639 | |
32bafa8f | 640 | for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next, i++) { |
199e0f17 MR |
641 | g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0); |
642 | } | |
643 | ||
644 | g_string_free(gstr_union, true); | |
645 | g_string_free(gstr_list, true); | |
646 | qapi_free_UserDefNativeListUnion(cvalue); | |
647 | } | |
648 | ||
649 | static void test_visitor_in_native_list_string(TestInputVisitorData *data, | |
650 | const void *unused) | |
651 | { | |
652 | UserDefNativeListUnion *cvalue = NULL; | |
653 | strList *elem = NULL; | |
199e0f17 MR |
654 | Visitor *v; |
655 | GString *gstr_list = g_string_new(""); | |
656 | GString *gstr_union = g_string_new(""); | |
657 | int i; | |
658 | ||
659 | for (i = 0; i < 32; i++) { | |
660 | g_string_append_printf(gstr_list, "'%d'", i); | |
661 | if (i != 31) { | |
662 | g_string_append(gstr_list, ", "); | |
663 | } | |
664 | } | |
665 | g_string_append_printf(gstr_union, "{ 'type': 'string', 'data': [ %s ] }", | |
666 | gstr_list->str); | |
667 | v = visitor_input_test_init_raw(data, gstr_union->str); | |
668 | ||
51e72bc1 | 669 | visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort); |
199e0f17 | 670 | g_assert(cvalue != NULL); |
c363acef | 671 | g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING); |
199e0f17 | 672 | |
32bafa8f | 673 | for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) { |
199e0f17 MR |
674 | gchar str[8]; |
675 | sprintf(str, "%d", i); | |
676 | g_assert_cmpstr(elem->value, ==, str); | |
677 | } | |
678 | ||
679 | g_string_free(gstr_union, true); | |
680 | g_string_free(gstr_list, true); | |
681 | qapi_free_UserDefNativeListUnion(cvalue); | |
682 | } | |
683 | ||
684 | #define DOUBLE_STR_MAX 16 | |
685 | ||
686 | static void test_visitor_in_native_list_number(TestInputVisitorData *data, | |
687 | const void *unused) | |
688 | { | |
689 | UserDefNativeListUnion *cvalue = NULL; | |
690 | numberList *elem = NULL; | |
199e0f17 MR |
691 | Visitor *v; |
692 | GString *gstr_list = g_string_new(""); | |
693 | GString *gstr_union = g_string_new(""); | |
694 | int i; | |
695 | ||
696 | for (i = 0; i < 32; i++) { | |
697 | g_string_append_printf(gstr_list, "%f", (double)i / 3); | |
698 | if (i != 31) { | |
699 | g_string_append(gstr_list, ", "); | |
700 | } | |
701 | } | |
702 | g_string_append_printf(gstr_union, "{ 'type': 'number', 'data': [ %s ] }", | |
703 | gstr_list->str); | |
704 | v = visitor_input_test_init_raw(data, gstr_union->str); | |
705 | ||
51e72bc1 | 706 | visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort); |
199e0f17 | 707 | g_assert(cvalue != NULL); |
c363acef | 708 | g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER); |
199e0f17 | 709 | |
32bafa8f | 710 | for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next, i++) { |
199e0f17 MR |
711 | GString *double_expected = g_string_new(""); |
712 | GString *double_actual = g_string_new(""); | |
713 | ||
714 | g_string_printf(double_expected, "%.6f", (double)i / 3); | |
715 | g_string_printf(double_actual, "%.6f", elem->value); | |
716 | g_assert_cmpstr(double_expected->str, ==, double_actual->str); | |
717 | ||
718 | g_string_free(double_expected, true); | |
719 | g_string_free(double_actual, true); | |
720 | } | |
721 | ||
722 | g_string_free(gstr_union, true); | |
723 | g_string_free(gstr_list, true); | |
724 | qapi_free_UserDefNativeListUnion(cvalue); | |
725 | } | |
726 | ||
d88f5fd1 LC |
727 | static void input_visitor_test_add(const char *testpath, |
728 | TestInputVisitorData *data, | |
729 | void (*test_func)(TestInputVisitorData *data, const void *user_data)) | |
730 | { | |
731 | g_test_add(testpath, TestInputVisitorData, data, NULL, test_func, | |
732 | visitor_input_teardown); | |
733 | } | |
734 | ||
3dcf71f6 PB |
735 | static void test_visitor_in_errors(TestInputVisitorData *data, |
736 | const void *unused) | |
737 | { | |
738 | TestStruct *p = NULL; | |
e940f543 | 739 | Error *err = NULL; |
3dcf71f6 | 740 | Visitor *v; |
dd5ee2c2 | 741 | strList *q = NULL; |
3dcf71f6 | 742 | |
dd5ee2c2 EB |
743 | v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', " |
744 | "'string': -42 }"); | |
3dcf71f6 | 745 | |
51e72bc1 | 746 | visit_type_TestStruct(v, NULL, &p, &err); |
a12a5a1a | 747 | error_free_or_abort(&err); |
2f52e205 EB |
748 | /* FIXME - a failed parse should not leave a partially-allocated p |
749 | * for us to clean up; this could cause callers to leak memory. */ | |
3dcf71f6 PB |
750 | g_assert(p->string == NULL); |
751 | ||
752 | g_free(p->string); | |
753 | g_free(p); | |
dd5ee2c2 EB |
754 | |
755 | v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]"); | |
51e72bc1 | 756 | visit_type_strList(v, NULL, &q, &err); |
dd5ee2c2 EB |
757 | error_free_or_abort(&err); |
758 | assert(q); | |
759 | qapi_free_strList(q); | |
3dcf71f6 PB |
760 | } |
761 | ||
2533377c EB |
762 | static void test_visitor_in_wrong_type(TestInputVisitorData *data, |
763 | const void *unused) | |
764 | { | |
765 | TestStruct *p = NULL; | |
766 | Visitor *v; | |
767 | strList *q = NULL; | |
768 | int64_t i; | |
769 | Error *err = NULL; | |
770 | ||
771 | /* Make sure arrays and structs cannot be confused */ | |
772 | ||
773 | v = visitor_input_test_init(data, "[]"); | |
51e72bc1 | 774 | visit_type_TestStruct(v, NULL, &p, &err); |
2533377c EB |
775 | error_free_or_abort(&err); |
776 | g_assert(!p); | |
777 | ||
778 | v = visitor_input_test_init(data, "{}"); | |
51e72bc1 | 779 | visit_type_strList(v, NULL, &q, &err); |
2533377c EB |
780 | error_free_or_abort(&err); |
781 | assert(!q); | |
782 | ||
783 | /* Make sure primitives and struct cannot be confused */ | |
784 | ||
785 | v = visitor_input_test_init(data, "1"); | |
51e72bc1 | 786 | visit_type_TestStruct(v, NULL, &p, &err); |
2533377c EB |
787 | error_free_or_abort(&err); |
788 | g_assert(!p); | |
789 | ||
790 | v = visitor_input_test_init(data, "{}"); | |
51e72bc1 | 791 | visit_type_int(v, NULL, &i, &err); |
2533377c EB |
792 | error_free_or_abort(&err); |
793 | ||
794 | /* Make sure primitives and arrays cannot be confused */ | |
795 | ||
796 | v = visitor_input_test_init(data, "1"); | |
51e72bc1 | 797 | visit_type_strList(v, NULL, &q, &err); |
2533377c EB |
798 | error_free_or_abort(&err); |
799 | assert(!q); | |
800 | ||
801 | v = visitor_input_test_init(data, "[]"); | |
51e72bc1 | 802 | visit_type_int(v, NULL, &i, &err); |
2533377c EB |
803 | error_free_or_abort(&err); |
804 | } | |
805 | ||
d88f5fd1 LC |
806 | int main(int argc, char **argv) |
807 | { | |
808 | TestInputVisitorData in_visitor_data; | |
809 | ||
810 | g_test_init(&argc, &argv, NULL); | |
811 | ||
812 | input_visitor_test_add("/visitor/input/int", | |
813 | &in_visitor_data, test_visitor_in_int); | |
e92cfa0d MR |
814 | input_visitor_test_add("/visitor/input/int_overflow", |
815 | &in_visitor_data, test_visitor_in_int_overflow); | |
d88f5fd1 LC |
816 | input_visitor_test_add("/visitor/input/bool", |
817 | &in_visitor_data, test_visitor_in_bool); | |
818 | input_visitor_test_add("/visitor/input/number", | |
819 | &in_visitor_data, test_visitor_in_number); | |
820 | input_visitor_test_add("/visitor/input/string", | |
805017b7 | 821 | &in_visitor_data, test_visitor_in_string); |
d88f5fd1 | 822 | input_visitor_test_add("/visitor/input/enum", |
805017b7 | 823 | &in_visitor_data, test_visitor_in_enum); |
d88f5fd1 | 824 | input_visitor_test_add("/visitor/input/struct", |
805017b7 | 825 | &in_visitor_data, test_visitor_in_struct); |
d88f5fd1 | 826 | input_visitor_test_add("/visitor/input/struct-nested", |
805017b7 | 827 | &in_visitor_data, test_visitor_in_struct_nested); |
d88f5fd1 | 828 | input_visitor_test_add("/visitor/input/list", |
805017b7 | 829 | &in_visitor_data, test_visitor_in_list); |
28770e05 MA |
830 | input_visitor_test_add("/visitor/input/any", |
831 | &in_visitor_data, test_visitor_in_any); | |
2fc00432 | 832 | input_visitor_test_add("/visitor/input/union-flat", |
805017b7 | 833 | &in_visitor_data, test_visitor_in_union_flat); |
ab045267 EB |
834 | input_visitor_test_add("/visitor/input/alternate", |
835 | &in_visitor_data, test_visitor_in_alternate); | |
3dcf71f6 | 836 | input_visitor_test_add("/visitor/input/errors", |
805017b7 | 837 | &in_visitor_data, test_visitor_in_errors); |
2533377c EB |
838 | input_visitor_test_add("/visitor/input/wrong-type", |
839 | &in_visitor_data, test_visitor_in_wrong_type); | |
9c51b441 EB |
840 | input_visitor_test_add("/visitor/input/alternate-number", |
841 | &in_visitor_data, test_visitor_in_alternate_number); | |
199e0f17 | 842 | input_visitor_test_add("/visitor/input/native_list/int", |
805017b7 EB |
843 | &in_visitor_data, |
844 | test_visitor_in_native_list_int); | |
199e0f17 | 845 | input_visitor_test_add("/visitor/input/native_list/int8", |
805017b7 EB |
846 | &in_visitor_data, |
847 | test_visitor_in_native_list_int8); | |
199e0f17 | 848 | input_visitor_test_add("/visitor/input/native_list/int16", |
805017b7 EB |
849 | &in_visitor_data, |
850 | test_visitor_in_native_list_int16); | |
199e0f17 | 851 | input_visitor_test_add("/visitor/input/native_list/int32", |
805017b7 EB |
852 | &in_visitor_data, |
853 | test_visitor_in_native_list_int32); | |
199e0f17 | 854 | input_visitor_test_add("/visitor/input/native_list/int64", |
805017b7 EB |
855 | &in_visitor_data, |
856 | test_visitor_in_native_list_int64); | |
199e0f17 | 857 | input_visitor_test_add("/visitor/input/native_list/uint8", |
805017b7 EB |
858 | &in_visitor_data, |
859 | test_visitor_in_native_list_uint8); | |
199e0f17 | 860 | input_visitor_test_add("/visitor/input/native_list/uint16", |
805017b7 EB |
861 | &in_visitor_data, |
862 | test_visitor_in_native_list_uint16); | |
199e0f17 | 863 | input_visitor_test_add("/visitor/input/native_list/uint32", |
805017b7 EB |
864 | &in_visitor_data, |
865 | test_visitor_in_native_list_uint32); | |
199e0f17 | 866 | input_visitor_test_add("/visitor/input/native_list/uint64", |
805017b7 EB |
867 | &in_visitor_data, |
868 | test_visitor_in_native_list_uint64); | |
199e0f17 | 869 | input_visitor_test_add("/visitor/input/native_list/bool", |
805017b7 | 870 | &in_visitor_data, test_visitor_in_native_list_bool); |
199e0f17 | 871 | input_visitor_test_add("/visitor/input/native_list/str", |
805017b7 EB |
872 | &in_visitor_data, |
873 | test_visitor_in_native_list_string); | |
199e0f17 | 874 | input_visitor_test_add("/visitor/input/native_list/number", |
805017b7 EB |
875 | &in_visitor_data, |
876 | test_visitor_in_native_list_number); | |
d88f5fd1 LC |
877 | |
878 | g_test_run(); | |
879 | ||
880 | return 0; | |
881 | } |