checkpatch.pl: add common glib defines to typelist
[qemu/ar7.git] / tests / test-keyval.c
blob63cb14629bf58a94ff4b2fdb56cde60e7a60c6c4
1 /*
2 * Unit tests for parsing of KEY=VALUE,... strings
4 * Copyright (C) 2017 Red Hat Inc.
6 * Authors:
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/qdict.h"
16 #include "qapi/qmp/qlist.h"
17 #include "qapi/qmp/qstring.h"
18 #include "qapi/qobject-input-visitor.h"
19 #include "test-qapi-visit.h"
20 #include "qemu/cutils.h"
21 #include "qemu/option.h"
23 static void test_keyval_parse(void)
25 Error *err = NULL;
26 QDict *qdict, *sub_qdict;
27 char long_key[129];
28 char *params;
30 /* Nothing */
31 qdict = keyval_parse("", NULL, &error_abort);
32 g_assert_cmpuint(qdict_size(qdict), ==, 0);
33 qobject_unref(qdict);
35 /* Empty key (qemu_opts_parse() accepts this) */
36 qdict = keyval_parse("=val", NULL, &err);
37 error_free_or_abort(&err);
38 g_assert(!qdict);
40 /* Empty key fragment */
41 qdict = keyval_parse(".", NULL, &err);
42 error_free_or_abort(&err);
43 g_assert(!qdict);
44 qdict = keyval_parse("key.", NULL, &err);
45 error_free_or_abort(&err);
46 g_assert(!qdict);
48 /* Invalid non-empty key (qemu_opts_parse() doesn't care) */
49 qdict = keyval_parse("7up=val", NULL, &err);
50 error_free_or_abort(&err);
51 g_assert(!qdict);
53 /* Overlong key */
54 memset(long_key, 'a', 127);
55 long_key[127] = 'z';
56 long_key[128] = 0;
57 params = g_strdup_printf("k.%s=v", long_key);
58 qdict = keyval_parse(params + 2, NULL, &err);
59 error_free_or_abort(&err);
60 g_assert(!qdict);
62 /* Overlong key fragment */
63 qdict = keyval_parse(params, NULL, &err);
64 error_free_or_abort(&err);
65 g_assert(!qdict);
66 g_free(params);
68 /* Long key (qemu_opts_parse() accepts and truncates silently) */
69 params = g_strdup_printf("k.%s=v", long_key + 1);
70 qdict = keyval_parse(params + 2, NULL, &error_abort);
71 g_assert_cmpuint(qdict_size(qdict), ==, 1);
72 g_assert_cmpstr(qdict_get_try_str(qdict, long_key + 1), ==, "v");
73 qobject_unref(qdict);
75 /* Long key fragment */
76 qdict = keyval_parse(params, NULL, &error_abort);
77 g_assert_cmpuint(qdict_size(qdict), ==, 1);
78 sub_qdict = qdict_get_qdict(qdict, "k");
79 g_assert(sub_qdict);
80 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
81 g_assert_cmpstr(qdict_get_try_str(sub_qdict, long_key + 1), ==, "v");
82 qobject_unref(qdict);
83 g_free(params);
85 /* Crap after valid key */
86 qdict = keyval_parse("key[0]=val", NULL, &err);
87 error_free_or_abort(&err);
88 g_assert(!qdict);
90 /* Multiple keys, last one wins */
91 qdict = keyval_parse("a=1,b=2,,x,a=3", NULL, &error_abort);
92 g_assert_cmpuint(qdict_size(qdict), ==, 2);
93 g_assert_cmpstr(qdict_get_try_str(qdict, "a"), ==, "3");
94 g_assert_cmpstr(qdict_get_try_str(qdict, "b"), ==, "2,x");
95 qobject_unref(qdict);
97 /* Even when it doesn't in qemu_opts_parse() */
98 qdict = keyval_parse("id=foo,id=bar", NULL, &error_abort);
99 g_assert_cmpuint(qdict_size(qdict), ==, 1);
100 g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "bar");
101 qobject_unref(qdict);
103 /* Dotted keys */
104 qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, &error_abort);
105 g_assert_cmpuint(qdict_size(qdict), ==, 2);
106 sub_qdict = qdict_get_qdict(qdict, "a");
107 g_assert(sub_qdict);
108 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
109 sub_qdict = qdict_get_qdict(sub_qdict, "b");
110 g_assert(sub_qdict);
111 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
112 g_assert_cmpstr(qdict_get_try_str(sub_qdict, "c"), ==, "2");
113 g_assert_cmpstr(qdict_get_try_str(qdict, "d"), ==, "3");
114 qobject_unref(qdict);
116 /* Inconsistent dotted keys */
117 qdict = keyval_parse("a.b=1,a=2", NULL, &err);
118 error_free_or_abort(&err);
119 g_assert(!qdict);
120 qdict = keyval_parse("a.b=1,a.b.c=2", NULL, &err);
121 error_free_or_abort(&err);
122 g_assert(!qdict);
124 /* Trailing comma is ignored */
125 qdict = keyval_parse("x=y,", NULL, &error_abort);
126 g_assert_cmpuint(qdict_size(qdict), ==, 1);
127 g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, "y");
128 qobject_unref(qdict);
130 /* Except when it isn't */
131 qdict = keyval_parse(",", NULL, &err);
132 error_free_or_abort(&err);
133 g_assert(!qdict);
135 /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */
136 qdict = keyval_parse("x=,,id=bar", NULL, &error_abort);
137 g_assert_cmpuint(qdict_size(qdict), ==, 1);
138 g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, ",id=bar");
139 qobject_unref(qdict);
141 /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */
142 qdict = keyval_parse("id=666", NULL, &error_abort);
143 g_assert_cmpuint(qdict_size(qdict), ==, 1);
144 g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "666");
145 qobject_unref(qdict);
147 /* Implied value not supported (unlike qemu_opts_parse()) */
148 qdict = keyval_parse("an,noaus,noaus=", NULL, &err);
149 error_free_or_abort(&err);
150 g_assert(!qdict);
152 /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */
153 qdict = keyval_parse("no", NULL, &err);
154 error_free_or_abort(&err);
155 g_assert(!qdict);
157 /* Implied key */
158 qdict = keyval_parse("an,aus=off,noaus=", "implied", &error_abort);
159 g_assert_cmpuint(qdict_size(qdict), ==, 3);
160 g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "an");
161 g_assert_cmpstr(qdict_get_try_str(qdict, "aus"), ==, "off");
162 g_assert_cmpstr(qdict_get_try_str(qdict, "noaus"), ==, "");
163 qobject_unref(qdict);
165 /* Implied dotted key */
166 qdict = keyval_parse("val", "eins.zwei", &error_abort);
167 g_assert_cmpuint(qdict_size(qdict), ==, 1);
168 sub_qdict = qdict_get_qdict(qdict, "eins");
169 g_assert(sub_qdict);
170 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
171 g_assert_cmpstr(qdict_get_try_str(sub_qdict, "zwei"), ==, "val");
172 qobject_unref(qdict);
174 /* Implied key with empty value (qemu_opts_parse() accepts this) */
175 qdict = keyval_parse(",", "implied", &err);
176 error_free_or_abort(&err);
177 g_assert(!qdict);
179 /* Likewise (qemu_opts_parse(): implied key with comma value) */
180 qdict = keyval_parse(",,,a=1", "implied", &err);
181 error_free_or_abort(&err);
182 g_assert(!qdict);
184 /* Empty key is not an implied key */
185 qdict = keyval_parse("=val", "implied", &err);
186 error_free_or_abort(&err);
187 g_assert(!qdict);
190 static void check_list012(QList *qlist)
192 static const char *expected[] = { "null", "eins", "zwei" };
193 int i;
194 QString *qstr;
196 g_assert(qlist);
197 for (i = 0; i < ARRAY_SIZE(expected); i++) {
198 qstr = qobject_to(QString, qlist_pop(qlist));
199 g_assert(qstr);
200 g_assert_cmpstr(qstring_get_str(qstr), ==, expected[i]);
201 qobject_unref(qstr);
203 g_assert(qlist_empty(qlist));
206 static void test_keyval_parse_list(void)
208 Error *err = NULL;
209 QDict *qdict, *sub_qdict;
211 /* Root can't be a list */
212 qdict = keyval_parse("0=1", NULL, &err);
213 error_free_or_abort(&err);
214 g_assert(!qdict);
216 /* List elements need not be in order */
217 qdict = keyval_parse("list.0=null,list.2=zwei,list.1=eins",
218 NULL, &error_abort);
219 g_assert_cmpint(qdict_size(qdict), ==, 1);
220 check_list012(qdict_get_qlist(qdict, "list"));
221 qobject_unref(qdict);
223 /* Multiple indexes, last one wins */
224 qdict = keyval_parse("list.1=goner,list.0=null,list.01=eins,list.2=zwei",
225 NULL, &error_abort);
226 g_assert_cmpint(qdict_size(qdict), ==, 1);
227 check_list012(qdict_get_qlist(qdict, "list"));
228 qobject_unref(qdict);
230 /* List at deeper nesting */
231 qdict = keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei",
232 NULL, &error_abort);
233 g_assert_cmpint(qdict_size(qdict), ==, 1);
234 sub_qdict = qdict_get_qdict(qdict, "a");
235 g_assert_cmpint(qdict_size(sub_qdict), ==, 1);
236 check_list012(qdict_get_qlist(sub_qdict, "list"));
237 qobject_unref(qdict);
239 /* Inconsistent dotted keys: both list and dictionary */
240 qdict = keyval_parse("a.b.c=1,a.b.0=2", NULL, &err);
241 error_free_or_abort(&err);
242 g_assert(!qdict);
243 qdict = keyval_parse("a.0.c=1,a.b.c=2", NULL, &err);
244 error_free_or_abort(&err);
245 g_assert(!qdict);
247 /* Missing list indexes */
248 qdict = keyval_parse("list.1=lonely", NULL, &err);
249 error_free_or_abort(&err);
250 g_assert(!qdict);
251 qdict = keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL, &err);
252 error_free_or_abort(&err);
253 g_assert(!qdict);
256 static void test_keyval_visit_bool(void)
258 Error *err = NULL;
259 Visitor *v;
260 QDict *qdict;
261 bool b;
263 qdict = keyval_parse("bool1=on,bool2=off", NULL, &error_abort);
264 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
265 qobject_unref(qdict);
266 visit_start_struct(v, NULL, NULL, 0, &error_abort);
267 visit_type_bool(v, "bool1", &b, &error_abort);
268 g_assert(b);
269 visit_type_bool(v, "bool2", &b, &error_abort);
270 g_assert(!b);
271 visit_check_struct(v, &error_abort);
272 visit_end_struct(v, NULL);
273 visit_free(v);
275 qdict = keyval_parse("bool1=offer", NULL, &error_abort);
276 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
277 qobject_unref(qdict);
278 visit_start_struct(v, NULL, NULL, 0, &error_abort);
279 visit_type_bool(v, "bool1", &b, &err);
280 error_free_or_abort(&err);
281 visit_end_struct(v, NULL);
282 visit_free(v);
285 static void test_keyval_visit_number(void)
287 Error *err = NULL;
288 Visitor *v;
289 QDict *qdict;
290 uint64_t u;
292 /* Lower limit zero */
293 qdict = keyval_parse("number1=0", NULL, &error_abort);
294 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
295 qobject_unref(qdict);
296 visit_start_struct(v, NULL, NULL, 0, &error_abort);
297 visit_type_uint64(v, "number1", &u, &error_abort);
298 g_assert_cmpuint(u, ==, 0);
299 visit_check_struct(v, &error_abort);
300 visit_end_struct(v, NULL);
301 visit_free(v);
303 /* Upper limit 2^64-1 */
304 qdict = keyval_parse("number1=18446744073709551615,number2=-1",
305 NULL, &error_abort);
306 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
307 qobject_unref(qdict);
308 visit_start_struct(v, NULL, NULL, 0, &error_abort);
309 visit_type_uint64(v, "number1", &u, &error_abort);
310 g_assert_cmphex(u, ==, UINT64_MAX);
311 visit_type_uint64(v, "number2", &u, &error_abort);
312 g_assert_cmphex(u, ==, UINT64_MAX);
313 visit_check_struct(v, &error_abort);
314 visit_end_struct(v, NULL);
315 visit_free(v);
317 /* Above upper limit */
318 qdict = keyval_parse("number1=18446744073709551616",
319 NULL, &error_abort);
320 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
321 qobject_unref(qdict);
322 visit_start_struct(v, NULL, NULL, 0, &error_abort);
323 visit_type_uint64(v, "number1", &u, &err);
324 error_free_or_abort(&err);
325 visit_end_struct(v, NULL);
326 visit_free(v);
328 /* Below lower limit */
329 qdict = keyval_parse("number1=-18446744073709551616",
330 NULL, &error_abort);
331 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
332 qobject_unref(qdict);
333 visit_start_struct(v, NULL, NULL, 0, &error_abort);
334 visit_type_uint64(v, "number1", &u, &err);
335 error_free_or_abort(&err);
336 visit_end_struct(v, NULL);
337 visit_free(v);
339 /* Hex and octal */
340 qdict = keyval_parse("number1=0x2a,number2=052",
341 NULL, &error_abort);
342 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
343 qobject_unref(qdict);
344 visit_start_struct(v, NULL, NULL, 0, &error_abort);
345 visit_type_uint64(v, "number1", &u, &error_abort);
346 g_assert_cmpuint(u, ==, 42);
347 visit_type_uint64(v, "number2", &u, &error_abort);
348 g_assert_cmpuint(u, ==, 42);
349 visit_check_struct(v, &error_abort);
350 visit_end_struct(v, NULL);
351 visit_free(v);
353 /* Trailing crap */
354 qdict = keyval_parse("number1=3.14,number2=08",
355 NULL, &error_abort);
356 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
357 qobject_unref(qdict);
358 visit_start_struct(v, NULL, NULL, 0, &error_abort);
359 visit_type_uint64(v, "number1", &u, &err);
360 error_free_or_abort(&err);
361 visit_type_uint64(v, "number2", &u, &err);
362 error_free_or_abort(&err);
363 visit_end_struct(v, NULL);
364 visit_free(v);
367 static void test_keyval_visit_size(void)
369 Error *err = NULL;
370 Visitor *v;
371 QDict *qdict;
372 uint64_t sz;
374 /* Lower limit zero */
375 qdict = keyval_parse("sz1=0", NULL, &error_abort);
376 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
377 qobject_unref(qdict);
378 visit_start_struct(v, NULL, NULL, 0, &error_abort);
379 visit_type_size(v, "sz1", &sz, &error_abort);
380 g_assert_cmpuint(sz, ==, 0);
381 visit_check_struct(v, &error_abort);
382 visit_end_struct(v, NULL);
383 visit_free(v);
385 /* Note: precision is 53 bits since we're parsing with strtod() */
387 /* Around limit of precision: 2^53-1, 2^53, 2^53+1 */
388 qdict = keyval_parse("sz1=9007199254740991,"
389 "sz2=9007199254740992,"
390 "sz3=9007199254740993",
391 NULL, &error_abort);
392 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
393 qobject_unref(qdict);
394 visit_start_struct(v, NULL, NULL, 0, &error_abort);
395 visit_type_size(v, "sz1", &sz, &error_abort);
396 g_assert_cmphex(sz, ==, 0x1fffffffffffff);
397 visit_type_size(v, "sz2", &sz, &error_abort);
398 g_assert_cmphex(sz, ==, 0x20000000000000);
399 visit_type_size(v, "sz3", &sz, &error_abort);
400 g_assert_cmphex(sz, ==, 0x20000000000000);
401 visit_check_struct(v, &error_abort);
402 visit_end_struct(v, NULL);
403 visit_free(v);
405 /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
406 qdict = keyval_parse("sz1=9223372036854774784," /* 7ffffffffffffc00 */
407 "sz2=9223372036854775295", /* 7ffffffffffffdff */
408 NULL, &error_abort);
409 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
410 qobject_unref(qdict);
411 visit_start_struct(v, NULL, NULL, 0, &error_abort);
412 visit_type_size(v, "sz1", &sz, &error_abort);
413 g_assert_cmphex(sz, ==, 0x7ffffffffffffc00);
414 visit_type_size(v, "sz2", &sz, &error_abort);
415 g_assert_cmphex(sz, ==, 0x7ffffffffffffc00);
416 visit_check_struct(v, &error_abort);
417 visit_end_struct(v, NULL);
418 visit_free(v);
420 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
421 qdict = keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */
422 "sz2=18446744073709550591", /* fffffffffffffbff */
423 NULL, &error_abort);
424 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
425 qobject_unref(qdict);
426 visit_start_struct(v, NULL, NULL, 0, &error_abort);
427 visit_type_size(v, "sz1", &sz, &error_abort);
428 g_assert_cmphex(sz, ==, 0xfffffffffffff800);
429 visit_type_size(v, "sz2", &sz, &error_abort);
430 g_assert_cmphex(sz, ==, 0xfffffffffffff800);
431 visit_check_struct(v, &error_abort);
432 visit_end_struct(v, NULL);
433 visit_free(v);
435 /* Beyond limits */
436 qdict = keyval_parse("sz1=-1,"
437 "sz2=18446744073709550592", /* fffffffffffffc00 */
438 NULL, &error_abort);
439 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
440 qobject_unref(qdict);
441 visit_start_struct(v, NULL, NULL, 0, &error_abort);
442 visit_type_size(v, "sz1", &sz, &err);
443 error_free_or_abort(&err);
444 visit_type_size(v, "sz2", &sz, &err);
445 error_free_or_abort(&err);
446 visit_end_struct(v, NULL);
447 visit_free(v);
449 /* Suffixes */
450 qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
451 NULL, &error_abort);
452 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
453 qobject_unref(qdict);
454 visit_start_struct(v, NULL, NULL, 0, &error_abort);
455 visit_type_size(v, "sz1", &sz, &error_abort);
456 g_assert_cmpuint(sz, ==, 8);
457 visit_type_size(v, "sz2", &sz, &error_abort);
458 g_assert_cmpuint(sz, ==, 1536);
459 visit_type_size(v, "sz3", &sz, &error_abort);
460 g_assert_cmphex(sz, ==, 2 * M_BYTE);
461 visit_type_size(v, "sz4", &sz, &error_abort);
462 g_assert_cmphex(sz, ==, G_BYTE / 10);
463 visit_type_size(v, "sz5", &sz, &error_abort);
464 g_assert_cmphex(sz, ==, 16777215 * T_BYTE);
465 visit_check_struct(v, &error_abort);
466 visit_end_struct(v, NULL);
467 visit_free(v);
469 /* Beyond limit with suffix */
470 qdict = keyval_parse("sz1=16777216T", NULL, &error_abort);
471 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
472 qobject_unref(qdict);
473 visit_start_struct(v, NULL, NULL, 0, &error_abort);
474 visit_type_size(v, "sz1", &sz, &err);
475 error_free_or_abort(&err);
476 visit_end_struct(v, NULL);
477 visit_free(v);
479 /* Trailing crap */
480 qdict = keyval_parse("sz1=16E,sz2=16Gi", NULL, &error_abort);
481 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
482 qobject_unref(qdict);
483 visit_start_struct(v, NULL, NULL, 0, &error_abort);
484 visit_type_size(v, "sz1", &sz, &err);
485 error_free_or_abort(&err);
486 visit_type_size(v, "sz2", &sz, &err);
487 error_free_or_abort(&err);
488 visit_end_struct(v, NULL);
489 visit_free(v);
492 static void test_keyval_visit_dict(void)
494 Error *err = NULL;
495 Visitor *v;
496 QDict *qdict;
497 int64_t i;
499 qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, &error_abort);
500 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
501 qobject_unref(qdict);
502 visit_start_struct(v, NULL, NULL, 0, &error_abort);
503 visit_start_struct(v, "a", NULL, 0, &error_abort);
504 visit_start_struct(v, "b", NULL, 0, &error_abort);
505 visit_type_int(v, "c", &i, &error_abort);
506 g_assert_cmpint(i, ==, 2);
507 visit_check_struct(v, &error_abort);
508 visit_end_struct(v, NULL);
509 visit_check_struct(v, &error_abort);
510 visit_end_struct(v, NULL);
511 visit_type_int(v, "d", &i, &error_abort);
512 g_assert_cmpint(i, ==, 3);
513 visit_check_struct(v, &error_abort);
514 visit_end_struct(v, NULL);
515 visit_free(v);
517 qdict = keyval_parse("a.b=", NULL, &error_abort);
518 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
519 qobject_unref(qdict);
520 visit_start_struct(v, NULL, NULL, 0, &error_abort);
521 visit_start_struct(v, "a", NULL, 0, &error_abort);
522 visit_type_int(v, "c", &i, &err); /* a.c missing */
523 error_free_or_abort(&err);
524 visit_check_struct(v, &err);
525 error_free_or_abort(&err); /* a.b unexpected */
526 visit_end_struct(v, NULL);
527 visit_check_struct(v, &error_abort);
528 visit_end_struct(v, NULL);
529 visit_free(v);
532 static void test_keyval_visit_list(void)
534 Error *err = NULL;
535 Visitor *v;
536 QDict *qdict;
537 char *s;
539 qdict = keyval_parse("a.0=,a.1=I,a.2.0=II", NULL, &error_abort);
540 /* TODO empty list */
541 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
542 qobject_unref(qdict);
543 visit_start_struct(v, NULL, NULL, 0, &error_abort);
544 visit_start_list(v, "a", NULL, 0, &error_abort);
545 visit_type_str(v, NULL, &s, &error_abort);
546 g_assert_cmpstr(s, ==, "");
547 g_free(s);
548 visit_type_str(v, NULL, &s, &error_abort);
549 g_assert_cmpstr(s, ==, "I");
550 g_free(s);
551 visit_start_list(v, NULL, NULL, 0, &error_abort);
552 visit_type_str(v, NULL, &s, &error_abort);
553 g_assert_cmpstr(s, ==, "II");
554 g_free(s);
555 visit_check_list(v, &error_abort);
556 visit_end_list(v, NULL);
557 visit_check_list(v, &error_abort);
558 visit_end_list(v, NULL);
559 visit_check_struct(v, &error_abort);
560 visit_end_struct(v, NULL);
561 visit_free(v);
563 qdict = keyval_parse("a.0=,b.0.0=head", NULL, &error_abort);
564 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
565 qobject_unref(qdict);
566 visit_start_struct(v, NULL, NULL, 0, &error_abort);
567 visit_start_list(v, "a", NULL, 0, &error_abort);
568 visit_check_list(v, &err); /* a[0] unexpected */
569 error_free_or_abort(&err);
570 visit_end_list(v, NULL);
571 visit_start_list(v, "b", NULL, 0, &error_abort);
572 visit_start_list(v, NULL, NULL, 0, &error_abort);
573 visit_type_str(v, NULL, &s, &error_abort);
574 g_assert_cmpstr(s, ==, "head");
575 g_free(s);
576 visit_type_str(v, NULL, &s, &err); /* b[0][1] missing */
577 error_free_or_abort(&err);
578 visit_end_list(v, NULL);
579 visit_end_list(v, NULL);
580 visit_check_struct(v, &error_abort);
581 visit_end_struct(v, NULL);
582 visit_free(v);
585 static void test_keyval_visit_optional(void)
587 Visitor *v;
588 QDict *qdict;
589 bool present;
590 int64_t i;
592 qdict = keyval_parse("a.b=1", NULL, &error_abort);
593 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
594 qobject_unref(qdict);
595 visit_start_struct(v, NULL, NULL, 0, &error_abort);
596 visit_optional(v, "b", &present);
597 g_assert(!present); /* b missing */
598 visit_optional(v, "a", &present);
599 g_assert(present); /* a present */
600 visit_start_struct(v, "a", NULL, 0, &error_abort);
601 visit_optional(v, "b", &present);
602 g_assert(present); /* a.b present */
603 visit_type_int(v, "b", &i, &error_abort);
604 g_assert_cmpint(i, ==, 1);
605 visit_optional(v, "a", &present);
606 g_assert(!present); /* a.a missing */
607 visit_check_struct(v, &error_abort);
608 visit_end_struct(v, NULL);
609 visit_check_struct(v, &error_abort);
610 visit_end_struct(v, NULL);
611 visit_free(v);
614 static void test_keyval_visit_alternate(void)
616 Error *err = NULL;
617 Visitor *v;
618 QDict *qdict;
619 AltStrObj *aso;
620 AltNumEnum *ane;
621 AltEnumBool *aeb;
624 * Can't do scalar alternate variants other than string. You get
625 * the string variant if there is one, else an error.
626 * TODO make it work for unambiguous cases like AltEnumBool below
628 qdict = keyval_parse("a=1,b=2,c=on", NULL, &error_abort);
629 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
630 qobject_unref(qdict);
631 visit_start_struct(v, NULL, NULL, 0, &error_abort);
632 visit_type_AltStrObj(v, "a", &aso, &error_abort);
633 g_assert_cmpint(aso->type, ==, QTYPE_QSTRING);
634 g_assert_cmpstr(aso->u.s, ==, "1");
635 qapi_free_AltStrObj(aso);
636 visit_type_AltNumEnum(v, "b", &ane, &err);
637 error_free_or_abort(&err);
638 visit_type_AltEnumBool(v, "c", &aeb, &err);
639 error_free_or_abort(&err);
640 visit_end_struct(v, NULL);
641 visit_free(v);
644 static void test_keyval_visit_any(void)
646 Visitor *v;
647 QDict *qdict;
648 QObject *any;
649 QList *qlist;
650 QString *qstr;
652 qdict = keyval_parse("a.0=null,a.1=1", NULL, &error_abort);
653 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
654 qobject_unref(qdict);
655 visit_start_struct(v, NULL, NULL, 0, &error_abort);
656 visit_type_any(v, "a", &any, &error_abort);
657 qlist = qobject_to(QList, any);
658 g_assert(qlist);
659 qstr = qobject_to(QString, qlist_pop(qlist));
660 g_assert_cmpstr(qstring_get_str(qstr), ==, "null");
661 qobject_unref(qstr);
662 qstr = qobject_to(QString, qlist_pop(qlist));
663 g_assert_cmpstr(qstring_get_str(qstr), ==, "1");
664 g_assert(qlist_empty(qlist));
665 qobject_unref(qstr);
666 qobject_unref(any);
667 visit_check_struct(v, &error_abort);
668 visit_end_struct(v, NULL);
669 visit_free(v);
672 int main(int argc, char *argv[])
674 g_test_init(&argc, &argv, NULL);
675 g_test_add_func("/keyval/keyval_parse", test_keyval_parse);
676 g_test_add_func("/keyval/keyval_parse/list", test_keyval_parse_list);
677 g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool);
678 g_test_add_func("/keyval/visit/number", test_keyval_visit_number);
679 g_test_add_func("/keyval/visit/size", test_keyval_visit_size);
680 g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict);
681 g_test_add_func("/keyval/visit/list", test_keyval_visit_list);
682 g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional);
683 g_test_add_func("/keyval/visit/alternate", test_keyval_visit_alternate);
684 g_test_add_func("/keyval/visit/any", test_keyval_visit_any);
685 g_test_run();
686 return 0;