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