2 * Unit tests for parsing of KEY=VALUE,... strings
4 * Copyright (C) 2017 Red Hat Inc.
7 * Markus Armbruster <armbru@redhat.com>,
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.
13 #include "qemu/osdep.h"
14 #include "qapi/error.h"
15 #include "qapi/qmp/qstring.h"
16 #include "qapi/qobject-input-visitor.h"
17 #include "test-qapi-visit.h"
18 #include "qemu/cutils.h"
19 #include "qemu/option.h"
21 static void test_keyval_parse(void)
24 QDict
*qdict
, *sub_qdict
;
29 qdict
= keyval_parse("", NULL
, &error_abort
);
30 g_assert_cmpuint(qdict_size(qdict
), ==, 0);
33 /* Empty key (qemu_opts_parse() accepts this) */
34 qdict
= keyval_parse("=val", NULL
, &err
);
35 error_free_or_abort(&err
);
38 /* Empty key fragment */
39 qdict
= keyval_parse(".", NULL
, &err
);
40 error_free_or_abort(&err
);
42 qdict
= keyval_parse("key.", NULL
, &err
);
43 error_free_or_abort(&err
);
46 /* Invalid non-empty key (qemu_opts_parse() doesn't care) */
47 qdict
= keyval_parse("7up=val", NULL
, &err
);
48 error_free_or_abort(&err
);
52 memset(long_key
, 'a', 127);
55 params
= g_strdup_printf("k.%s=v", long_key
);
56 qdict
= keyval_parse(params
+ 2, NULL
, &err
);
57 error_free_or_abort(&err
);
60 /* Overlong key fragment */
61 qdict
= keyval_parse(params
, NULL
, &err
);
62 error_free_or_abort(&err
);
66 /* Long key (qemu_opts_parse() accepts and truncates silently) */
67 params
= g_strdup_printf("k.%s=v", long_key
+ 1);
68 qdict
= keyval_parse(params
+ 2, NULL
, &error_abort
);
69 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
70 g_assert_cmpstr(qdict_get_try_str(qdict
, long_key
+ 1), ==, "v");
73 /* Long key fragment */
74 qdict
= keyval_parse(params
, NULL
, &error_abort
);
75 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
76 sub_qdict
= qdict_get_qdict(qdict
, "k");
78 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
79 g_assert_cmpstr(qdict_get_try_str(sub_qdict
, long_key
+ 1), ==, "v");
83 /* Crap after valid key */
84 qdict
= keyval_parse("key[0]=val", NULL
, &err
);
85 error_free_or_abort(&err
);
88 /* Multiple keys, last one wins */
89 qdict
= keyval_parse("a=1,b=2,,x,a=3", NULL
, &error_abort
);
90 g_assert_cmpuint(qdict_size(qdict
), ==, 2);
91 g_assert_cmpstr(qdict_get_try_str(qdict
, "a"), ==, "3");
92 g_assert_cmpstr(qdict_get_try_str(qdict
, "b"), ==, "2,x");
95 /* Even when it doesn't in qemu_opts_parse() */
96 qdict
= keyval_parse("id=foo,id=bar", NULL
, &error_abort
);
97 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
98 g_assert_cmpstr(qdict_get_try_str(qdict
, "id"), ==, "bar");
102 qdict
= keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL
, &error_abort
);
103 g_assert_cmpuint(qdict_size(qdict
), ==, 2);
104 sub_qdict
= qdict_get_qdict(qdict
, "a");
106 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
107 sub_qdict
= qdict_get_qdict(sub_qdict
, "b");
109 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
110 g_assert_cmpstr(qdict_get_try_str(sub_qdict
, "c"), ==, "2");
111 g_assert_cmpstr(qdict_get_try_str(qdict
, "d"), ==, "3");
114 /* Inconsistent dotted keys */
115 qdict
= keyval_parse("a.b=1,a=2", NULL
, &err
);
116 error_free_or_abort(&err
);
118 qdict
= keyval_parse("a.b=1,a.b.c=2", NULL
, &err
);
119 error_free_or_abort(&err
);
122 /* Trailing comma is ignored */
123 qdict
= keyval_parse("x=y,", NULL
, &error_abort
);
124 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
125 g_assert_cmpstr(qdict_get_try_str(qdict
, "x"), ==, "y");
128 /* Except when it isn't */
129 qdict
= keyval_parse(",", NULL
, &err
);
130 error_free_or_abort(&err
);
133 /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */
134 qdict
= keyval_parse("x=,,id=bar", NULL
, &error_abort
);
135 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
136 g_assert_cmpstr(qdict_get_try_str(qdict
, "x"), ==, ",id=bar");
139 /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */
140 qdict
= keyval_parse("id=666", NULL
, &error_abort
);
141 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
142 g_assert_cmpstr(qdict_get_try_str(qdict
, "id"), ==, "666");
145 /* Implied value not supported (unlike qemu_opts_parse()) */
146 qdict
= keyval_parse("an,noaus,noaus=", NULL
, &err
);
147 error_free_or_abort(&err
);
150 /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */
151 qdict
= keyval_parse("no", NULL
, &err
);
152 error_free_or_abort(&err
);
156 qdict
= keyval_parse("an,aus=off,noaus=", "implied", &error_abort
);
157 g_assert_cmpuint(qdict_size(qdict
), ==, 3);
158 g_assert_cmpstr(qdict_get_try_str(qdict
, "implied"), ==, "an");
159 g_assert_cmpstr(qdict_get_try_str(qdict
, "aus"), ==, "off");
160 g_assert_cmpstr(qdict_get_try_str(qdict
, "noaus"), ==, "");
163 /* Implied dotted key */
164 qdict
= keyval_parse("val", "eins.zwei", &error_abort
);
165 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
166 sub_qdict
= qdict_get_qdict(qdict
, "eins");
168 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
169 g_assert_cmpstr(qdict_get_try_str(sub_qdict
, "zwei"), ==, "val");
172 /* Implied key with empty value (qemu_opts_parse() accepts this) */
173 qdict
= keyval_parse(",", "implied", &err
);
174 error_free_or_abort(&err
);
177 /* Likewise (qemu_opts_parse(): implied key with comma value) */
178 qdict
= keyval_parse(",,,a=1", "implied", &err
);
179 error_free_or_abort(&err
);
182 /* Empty key is not an implied key */
183 qdict
= keyval_parse("=val", "implied", &err
);
184 error_free_or_abort(&err
);
188 static void check_list012(QList
*qlist
)
190 static const char *expected
[] = { "null", "eins", "zwei" };
195 for (i
= 0; i
< ARRAY_SIZE(expected
); i
++) {
196 qstr
= qobject_to_qstring(qlist_pop(qlist
));
198 g_assert_cmpstr(qstring_get_str(qstr
), ==, expected
[i
]);
201 g_assert(qlist_empty(qlist
));
204 static void test_keyval_parse_list(void)
207 QDict
*qdict
, *sub_qdict
;
209 /* Root can't be a list */
210 qdict
= keyval_parse("0=1", NULL
, &err
);
211 error_free_or_abort(&err
);
214 /* List elements need not be in order */
215 qdict
= keyval_parse("list.0=null,list.2=zwei,list.1=eins",
217 g_assert_cmpint(qdict_size(qdict
), ==, 1);
218 check_list012(qdict_get_qlist(qdict
, "list"));
221 /* Multiple indexes, last one wins */
222 qdict
= keyval_parse("list.1=goner,list.0=null,list.01=eins,list.2=zwei",
224 g_assert_cmpint(qdict_size(qdict
), ==, 1);
225 check_list012(qdict_get_qlist(qdict
, "list"));
228 /* List at deeper nesting */
229 qdict
= keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei",
231 g_assert_cmpint(qdict_size(qdict
), ==, 1);
232 sub_qdict
= qdict_get_qdict(qdict
, "a");
233 g_assert_cmpint(qdict_size(sub_qdict
), ==, 1);
234 check_list012(qdict_get_qlist(sub_qdict
, "list"));
237 /* Inconsistent dotted keys: both list and dictionary */
238 qdict
= keyval_parse("a.b.c=1,a.b.0=2", NULL
, &err
);
239 error_free_or_abort(&err
);
241 qdict
= keyval_parse("a.0.c=1,a.b.c=2", NULL
, &err
);
242 error_free_or_abort(&err
);
245 /* Missing list indexes */
246 qdict
= keyval_parse("list.1=lonely", NULL
, &err
);
247 error_free_or_abort(&err
);
249 qdict
= keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL
, &err
);
250 error_free_or_abort(&err
);
254 static void test_keyval_visit_bool(void)
261 qdict
= keyval_parse("bool1=on,bool2=off", NULL
, &error_abort
);
262 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
264 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
265 visit_type_bool(v
, "bool1", &b
, &error_abort
);
267 visit_type_bool(v
, "bool2", &b
, &error_abort
);
269 visit_check_struct(v
, &error_abort
);
270 visit_end_struct(v
, NULL
);
273 qdict
= keyval_parse("bool1=offer", NULL
, &error_abort
);
274 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
276 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
277 visit_type_bool(v
, "bool1", &b
, &err
);
278 error_free_or_abort(&err
);
279 visit_end_struct(v
, NULL
);
283 static void test_keyval_visit_number(void)
290 /* Lower limit zero */
291 qdict
= keyval_parse("number1=0", NULL
, &error_abort
);
292 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
294 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
295 visit_type_uint64(v
, "number1", &u
, &error_abort
);
296 g_assert_cmpuint(u
, ==, 0);
297 visit_check_struct(v
, &error_abort
);
298 visit_end_struct(v
, NULL
);
301 /* Upper limit 2^64-1 */
302 qdict
= keyval_parse("number1=18446744073709551615,number2=-1",
304 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
306 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
307 visit_type_uint64(v
, "number1", &u
, &error_abort
);
308 g_assert_cmphex(u
, ==, UINT64_MAX
);
309 visit_type_uint64(v
, "number2", &u
, &error_abort
);
310 g_assert_cmphex(u
, ==, UINT64_MAX
);
311 visit_check_struct(v
, &error_abort
);
312 visit_end_struct(v
, NULL
);
315 /* Above upper limit */
316 qdict
= keyval_parse("number1=18446744073709551616",
318 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
320 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
321 visit_type_uint64(v
, "number1", &u
, &err
);
322 error_free_or_abort(&err
);
323 visit_end_struct(v
, NULL
);
326 /* Below lower limit */
327 qdict
= keyval_parse("number1=-18446744073709551616",
329 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
331 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
332 visit_type_uint64(v
, "number1", &u
, &err
);
333 error_free_or_abort(&err
);
334 visit_end_struct(v
, NULL
);
338 qdict
= keyval_parse("number1=0x2a,number2=052",
340 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
342 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
343 visit_type_uint64(v
, "number1", &u
, &error_abort
);
344 g_assert_cmpuint(u
, ==, 42);
345 visit_type_uint64(v
, "number2", &u
, &error_abort
);
346 g_assert_cmpuint(u
, ==, 42);
347 visit_check_struct(v
, &error_abort
);
348 visit_end_struct(v
, NULL
);
352 qdict
= keyval_parse("number1=3.14,number2=08",
354 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
356 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
357 visit_type_uint64(v
, "number1", &u
, &err
);
358 error_free_or_abort(&err
);
359 visit_type_uint64(v
, "number2", &u
, &err
);
360 error_free_or_abort(&err
);
361 visit_end_struct(v
, NULL
);
365 static void test_keyval_visit_size(void)
372 /* Lower limit zero */
373 qdict
= keyval_parse("sz1=0", NULL
, &error_abort
);
374 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
376 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
377 visit_type_size(v
, "sz1", &sz
, &error_abort
);
378 g_assert_cmpuint(sz
, ==, 0);
379 visit_check_struct(v
, &error_abort
);
380 visit_end_struct(v
, NULL
);
383 /* Note: precision is 53 bits since we're parsing with strtod() */
385 /* Around limit of precision: 2^53-1, 2^53, 2^53+1 */
386 qdict
= keyval_parse("sz1=9007199254740991,"
387 "sz2=9007199254740992,"
388 "sz3=9007199254740993",
390 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
392 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
393 visit_type_size(v
, "sz1", &sz
, &error_abort
);
394 g_assert_cmphex(sz
, ==, 0x1fffffffffffff);
395 visit_type_size(v
, "sz2", &sz
, &error_abort
);
396 g_assert_cmphex(sz
, ==, 0x20000000000000);
397 visit_type_size(v
, "sz3", &sz
, &error_abort
);
398 g_assert_cmphex(sz
, ==, 0x20000000000000);
399 visit_check_struct(v
, &error_abort
);
400 visit_end_struct(v
, NULL
);
403 /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
404 qdict
= keyval_parse("sz1=9223372036854774784," /* 7ffffffffffffc00 */
405 "sz2=9223372036854775295", /* 7ffffffffffffdff */
407 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
409 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
410 visit_type_size(v
, "sz1", &sz
, &error_abort
);
411 g_assert_cmphex(sz
, ==, 0x7ffffffffffffc00);
412 visit_type_size(v
, "sz2", &sz
, &error_abort
);
413 g_assert_cmphex(sz
, ==, 0x7ffffffffffffc00);
414 visit_check_struct(v
, &error_abort
);
415 visit_end_struct(v
, NULL
);
418 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
419 qdict
= keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */
420 "sz2=18446744073709550591", /* fffffffffffffbff */
422 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
424 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
425 visit_type_size(v
, "sz1", &sz
, &error_abort
);
426 g_assert_cmphex(sz
, ==, 0xfffffffffffff800);
427 visit_type_size(v
, "sz2", &sz
, &error_abort
);
428 g_assert_cmphex(sz
, ==, 0xfffffffffffff800);
429 visit_check_struct(v
, &error_abort
);
430 visit_end_struct(v
, NULL
);
434 qdict
= keyval_parse("sz1=-1,"
435 "sz2=18446744073709550592", /* fffffffffffffc00 */
437 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
439 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
440 visit_type_size(v
, "sz1", &sz
, &err
);
441 error_free_or_abort(&err
);
442 visit_type_size(v
, "sz2", &sz
, &err
);
443 error_free_or_abort(&err
);
444 visit_end_struct(v
, NULL
);
448 qdict
= keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
450 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
452 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
453 visit_type_size(v
, "sz1", &sz
, &error_abort
);
454 g_assert_cmpuint(sz
, ==, 8);
455 visit_type_size(v
, "sz2", &sz
, &error_abort
);
456 g_assert_cmpuint(sz
, ==, 1536);
457 visit_type_size(v
, "sz3", &sz
, &error_abort
);
458 g_assert_cmphex(sz
, ==, 2 * M_BYTE
);
459 visit_type_size(v
, "sz4", &sz
, &error_abort
);
460 g_assert_cmphex(sz
, ==, G_BYTE
/ 10);
461 visit_type_size(v
, "sz5", &sz
, &error_abort
);
462 g_assert_cmphex(sz
, ==, 16777215 * T_BYTE
);
463 visit_check_struct(v
, &error_abort
);
464 visit_end_struct(v
, NULL
);
467 /* Beyond limit with suffix */
468 qdict
= keyval_parse("sz1=16777216T", NULL
, &error_abort
);
469 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
471 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
472 visit_type_size(v
, "sz1", &sz
, &err
);
473 error_free_or_abort(&err
);
474 visit_end_struct(v
, NULL
);
478 qdict
= keyval_parse("sz1=16E,sz2=16Gi", NULL
, &error_abort
);
479 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
481 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
482 visit_type_size(v
, "sz1", &sz
, &err
);
483 error_free_or_abort(&err
);
484 visit_type_size(v
, "sz2", &sz
, &err
);
485 error_free_or_abort(&err
);
486 visit_end_struct(v
, NULL
);
490 static void test_keyval_visit_dict(void)
497 qdict
= keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL
, &error_abort
);
498 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
500 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
501 visit_start_struct(v
, "a", NULL
, 0, &error_abort
);
502 visit_start_struct(v
, "b", NULL
, 0, &error_abort
);
503 visit_type_int(v
, "c", &i
, &error_abort
);
504 g_assert_cmpint(i
, ==, 2);
505 visit_check_struct(v
, &error_abort
);
506 visit_end_struct(v
, NULL
);
507 visit_check_struct(v
, &error_abort
);
508 visit_end_struct(v
, NULL
);
509 visit_type_int(v
, "d", &i
, &error_abort
);
510 g_assert_cmpint(i
, ==, 3);
511 visit_check_struct(v
, &error_abort
);
512 visit_end_struct(v
, NULL
);
515 qdict
= keyval_parse("a.b=", NULL
, &error_abort
);
516 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
518 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
519 visit_start_struct(v
, "a", NULL
, 0, &error_abort
);
520 visit_type_int(v
, "c", &i
, &err
); /* a.c missing */
521 error_free_or_abort(&err
);
522 visit_check_struct(v
, &err
);
523 error_free_or_abort(&err
); /* a.b unexpected */
524 visit_end_struct(v
, NULL
);
525 visit_check_struct(v
, &error_abort
);
526 visit_end_struct(v
, NULL
);
530 static void test_keyval_visit_list(void)
537 qdict
= keyval_parse("a.0=,a.1=I,a.2.0=II", NULL
, &error_abort
);
538 /* TODO empty list */
539 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
541 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
542 visit_start_list(v
, "a", NULL
, 0, &error_abort
);
543 visit_type_str(v
, NULL
, &s
, &error_abort
);
544 g_assert_cmpstr(s
, ==, "");
546 visit_type_str(v
, NULL
, &s
, &error_abort
);
547 g_assert_cmpstr(s
, ==, "I");
549 visit_start_list(v
, NULL
, NULL
, 0, &error_abort
);
550 visit_type_str(v
, NULL
, &s
, &error_abort
);
551 g_assert_cmpstr(s
, ==, "II");
553 visit_check_list(v
, &error_abort
);
554 visit_end_list(v
, NULL
);
555 visit_check_list(v
, &error_abort
);
556 visit_end_list(v
, NULL
);
557 visit_check_struct(v
, &error_abort
);
558 visit_end_struct(v
, NULL
);
561 qdict
= keyval_parse("a.0=,b.0.0=head", NULL
, &error_abort
);
562 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
564 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
565 visit_start_list(v
, "a", NULL
, 0, &error_abort
);
566 visit_check_list(v
, &err
); /* a[0] unexpected */
567 error_free_or_abort(&err
);
568 visit_end_list(v
, NULL
);
569 visit_start_list(v
, "b", NULL
, 0, &error_abort
);
570 visit_start_list(v
, NULL
, NULL
, 0, &error_abort
);
571 visit_type_str(v
, NULL
, &s
, &error_abort
);
572 g_assert_cmpstr(s
, ==, "head");
574 visit_type_str(v
, NULL
, &s
, &err
); /* b[0][1] missing */
575 error_free_or_abort(&err
);
576 visit_end_list(v
, NULL
);
577 visit_end_list(v
, NULL
);
578 visit_check_struct(v
, &error_abort
);
579 visit_end_struct(v
, NULL
);
583 static void test_keyval_visit_optional(void)
590 qdict
= keyval_parse("a.b=1", NULL
, &error_abort
);
591 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
593 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
594 visit_optional(v
, "b", &present
);
595 g_assert(!present
); /* b missing */
596 visit_optional(v
, "a", &present
);
597 g_assert(present
); /* a present */
598 visit_start_struct(v
, "a", NULL
, 0, &error_abort
);
599 visit_optional(v
, "b", &present
);
600 g_assert(present
); /* a.b present */
601 visit_type_int(v
, "b", &i
, &error_abort
);
602 g_assert_cmpint(i
, ==, 1);
603 visit_optional(v
, "a", &present
);
604 g_assert(!present
); /* a.a missing */
605 visit_check_struct(v
, &error_abort
);
606 visit_end_struct(v
, NULL
);
607 visit_check_struct(v
, &error_abort
);
608 visit_end_struct(v
, NULL
);
612 static void test_keyval_visit_alternate(void)
622 * Can't do scalar alternate variants other than string. You get
623 * the string variant if there is one, else an error.
624 * TODO make it work for unambiguous cases like AltEnumBool below
626 qdict
= keyval_parse("a=1,b=2,c=on", NULL
, &error_abort
);
627 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
629 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
630 visit_type_AltStrObj(v
, "a", &aso
, &error_abort
);
631 g_assert_cmpint(aso
->type
, ==, QTYPE_QSTRING
);
632 g_assert_cmpstr(aso
->u
.s
, ==, "1");
633 qapi_free_AltStrObj(aso
);
634 visit_type_AltNumInt(v
, "b", &ani
, &err
);
635 error_free_or_abort(&err
);
636 visit_type_AltEnumBool(v
, "c", &aeb
, &err
);
637 error_free_or_abort(&err
);
638 visit_end_struct(v
, NULL
);
642 static void test_keyval_visit_any(void)
650 qdict
= keyval_parse("a.0=null,a.1=1", NULL
, &error_abort
);
651 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
653 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
654 visit_type_any(v
, "a", &any
, &error_abort
);
655 qlist
= qobject_to_qlist(any
);
657 qstr
= qobject_to_qstring(qlist_pop(qlist
));
658 g_assert_cmpstr(qstring_get_str(qstr
), ==, "null");
660 qstr
= qobject_to_qstring(qlist_pop(qlist
));
661 g_assert_cmpstr(qstring_get_str(qstr
), ==, "1");
662 g_assert(qlist_empty(qlist
));
665 visit_check_struct(v
, &error_abort
);
666 visit_end_struct(v
, NULL
);
670 int main(int argc
, char *argv
[])
672 g_test_init(&argc
, &argv
, NULL
);
673 g_test_add_func("/keyval/keyval_parse", test_keyval_parse
);
674 g_test_add_func("/keyval/keyval_parse/list", test_keyval_parse_list
);
675 g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool
);
676 g_test_add_func("/keyval/visit/number", test_keyval_visit_number
);
677 g_test_add_func("/keyval/visit/size", test_keyval_visit_size
);
678 g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict
);
679 g_test_add_func("/keyval/visit/list", test_keyval_visit_list
);
680 g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional
);
681 g_test_add_func("/keyval/visit/alternate", test_keyval_visit_alternate
);
682 g_test_add_func("/keyval/visit/any", test_keyval_visit_any
);