rbd: Fix regression in legacy key/values containing escaped :
[qemu/ar7.git] / tests / test-keyval.c
blobba19560a229685f74e35515cfac3ff23eaf1b177
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/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)
23 Error *err = NULL;
24 QDict *qdict, *sub_qdict;
25 char long_key[129];
26 char *params;
28 /* Nothing */
29 qdict = keyval_parse("", NULL, &error_abort);
30 g_assert_cmpuint(qdict_size(qdict), ==, 0);
31 QDECREF(qdict);
33 /* Empty key (qemu_opts_parse() accepts this) */
34 qdict = keyval_parse("=val", NULL, &err);
35 error_free_or_abort(&err);
36 g_assert(!qdict);
38 /* Empty key fragment */
39 qdict = keyval_parse(".", NULL, &err);
40 error_free_or_abort(&err);
41 g_assert(!qdict);
42 qdict = keyval_parse("key.", NULL, &err);
43 error_free_or_abort(&err);
44 g_assert(!qdict);
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);
49 g_assert(!qdict);
51 /* Overlong key */
52 memset(long_key, 'a', 127);
53 long_key[127] = 'z';
54 long_key[128] = 0;
55 params = g_strdup_printf("k.%s=v", long_key);
56 qdict = keyval_parse(params + 2, NULL, &err);
57 error_free_or_abort(&err);
58 g_assert(!qdict);
60 /* Overlong key fragment */
61 qdict = keyval_parse(params, NULL, &err);
62 error_free_or_abort(&err);
63 g_assert(!qdict);
64 g_free(params);
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");
71 QDECREF(qdict);
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");
77 g_assert(sub_qdict);
78 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
79 g_assert_cmpstr(qdict_get_try_str(sub_qdict, long_key + 1), ==, "v");
80 QDECREF(qdict);
81 g_free(params);
83 /* Crap after valid key */
84 qdict = keyval_parse("key[0]=val", NULL, &err);
85 error_free_or_abort(&err);
86 g_assert(!qdict);
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");
93 QDECREF(qdict);
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");
99 QDECREF(qdict);
101 /* Dotted keys */
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");
105 g_assert(sub_qdict);
106 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
107 sub_qdict = qdict_get_qdict(sub_qdict, "b");
108 g_assert(sub_qdict);
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");
112 QDECREF(qdict);
114 /* Inconsistent dotted keys */
115 qdict = keyval_parse("a.b=1,a=2", NULL, &err);
116 error_free_or_abort(&err);
117 g_assert(!qdict);
118 qdict = keyval_parse("a.b=1,a.b.c=2", NULL, &err);
119 error_free_or_abort(&err);
120 g_assert(!qdict);
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");
126 QDECREF(qdict);
128 /* Except when it isn't */
129 qdict = keyval_parse(",", NULL, &err);
130 error_free_or_abort(&err);
131 g_assert(!qdict);
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");
137 QDECREF(qdict);
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");
143 QDECREF(qdict);
145 /* Implied value not supported (unlike qemu_opts_parse()) */
146 qdict = keyval_parse("an,noaus,noaus=", NULL, &err);
147 error_free_or_abort(&err);
148 g_assert(!qdict);
150 /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */
151 qdict = keyval_parse("no", NULL, &err);
152 error_free_or_abort(&err);
153 g_assert(!qdict);
155 /* Implied key */
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"), ==, "");
161 QDECREF(qdict);
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");
167 g_assert(sub_qdict);
168 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1);
169 g_assert_cmpstr(qdict_get_try_str(sub_qdict, "zwei"), ==, "val");
170 QDECREF(qdict);
172 /* Implied key with empty value (qemu_opts_parse() accepts this) */
173 qdict = keyval_parse(",", "implied", &err);
174 error_free_or_abort(&err);
175 g_assert(!qdict);
177 /* Likewise (qemu_opts_parse(): implied key with comma value) */
178 qdict = keyval_parse(",,,a=1", "implied", &err);
179 error_free_or_abort(&err);
180 g_assert(!qdict);
182 /* Empty key is not an implied key */
183 qdict = keyval_parse("=val", "implied", &err);
184 error_free_or_abort(&err);
185 g_assert(!qdict);
188 static void check_list012(QList *qlist)
190 static const char *expected[] = { "null", "eins", "zwei" };
191 int i;
192 QString *qstr;
194 g_assert(qlist);
195 for (i = 0; i < ARRAY_SIZE(expected); i++) {
196 qstr = qobject_to_qstring(qlist_pop(qlist));
197 g_assert(qstr);
198 g_assert_cmpstr(qstring_get_str(qstr), ==, expected[i]);
199 QDECREF(qstr);
201 g_assert(qlist_empty(qlist));
204 static void test_keyval_parse_list(void)
206 Error *err = NULL;
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);
212 g_assert(!qdict);
214 /* List elements need not be in order */
215 qdict = keyval_parse("list.0=null,list.2=zwei,list.1=eins",
216 NULL, &error_abort);
217 g_assert_cmpint(qdict_size(qdict), ==, 1);
218 check_list012(qdict_get_qlist(qdict, "list"));
219 QDECREF(qdict);
221 /* Multiple indexes, last one wins */
222 qdict = keyval_parse("list.1=goner,list.0=null,list.01=eins,list.2=zwei",
223 NULL, &error_abort);
224 g_assert_cmpint(qdict_size(qdict), ==, 1);
225 check_list012(qdict_get_qlist(qdict, "list"));
226 QDECREF(qdict);
228 /* List at deeper nesting */
229 qdict = keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei",
230 NULL, &error_abort);
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"));
235 QDECREF(qdict);
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);
240 g_assert(!qdict);
241 qdict = keyval_parse("a.0.c=1,a.b.c=2", NULL, &err);
242 error_free_or_abort(&err);
243 g_assert(!qdict);
245 /* Missing list indexes */
246 qdict = keyval_parse("list.1=lonely", NULL, &err);
247 error_free_or_abort(&err);
248 g_assert(!qdict);
249 qdict = keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL, &err);
250 error_free_or_abort(&err);
251 g_assert(!qdict);
254 static void test_keyval_visit_bool(void)
256 Error *err = NULL;
257 Visitor *v;
258 QDict *qdict;
259 bool b;
261 qdict = keyval_parse("bool1=on,bool2=off", NULL, &error_abort);
262 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
263 QDECREF(qdict);
264 visit_start_struct(v, NULL, NULL, 0, &error_abort);
265 visit_type_bool(v, "bool1", &b, &error_abort);
266 g_assert(b);
267 visit_type_bool(v, "bool2", &b, &error_abort);
268 g_assert(!b);
269 visit_check_struct(v, &error_abort);
270 visit_end_struct(v, NULL);
271 visit_free(v);
273 qdict = keyval_parse("bool1=offer", NULL, &error_abort);
274 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
275 QDECREF(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);
280 visit_free(v);
283 static void test_keyval_visit_number(void)
285 Error *err = NULL;
286 Visitor *v;
287 QDict *qdict;
288 uint64_t u;
290 /* Lower limit zero */
291 qdict = keyval_parse("number1=0", NULL, &error_abort);
292 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
293 QDECREF(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);
299 visit_free(v);
301 /* Upper limit 2^64-1 */
302 qdict = keyval_parse("number1=18446744073709551615,number2=-1",
303 NULL, &error_abort);
304 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
305 QDECREF(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);
313 visit_free(v);
315 /* Above upper limit */
316 qdict = keyval_parse("number1=18446744073709551616",
317 NULL, &error_abort);
318 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
319 QDECREF(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);
324 visit_free(v);
326 /* Below lower limit */
327 qdict = keyval_parse("number1=-18446744073709551616",
328 NULL, &error_abort);
329 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
330 QDECREF(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);
335 visit_free(v);
337 /* Hex and octal */
338 qdict = keyval_parse("number1=0x2a,number2=052",
339 NULL, &error_abort);
340 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
341 QDECREF(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);
349 visit_free(v);
351 /* Trailing crap */
352 qdict = keyval_parse("number1=3.14,number2=08",
353 NULL, &error_abort);
354 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
355 QDECREF(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);
362 visit_free(v);
365 static void test_keyval_visit_size(void)
367 Error *err = NULL;
368 Visitor *v;
369 QDict *qdict;
370 uint64_t sz;
372 /* Lower limit zero */
373 qdict = keyval_parse("sz1=0", NULL, &error_abort);
374 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
375 QDECREF(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);
381 visit_free(v);
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",
389 NULL, &error_abort);
390 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
391 QDECREF(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);
401 visit_free(v);
403 /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
404 qdict = keyval_parse("sz1=9223372036854774784," /* 7ffffffffffffc00 */
405 "sz2=9223372036854775295", /* 7ffffffffffffdff */
406 NULL, &error_abort);
407 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
408 QDECREF(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);
416 visit_free(v);
418 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
419 qdict = keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */
420 "sz2=18446744073709550591", /* fffffffffffffbff */
421 NULL, &error_abort);
422 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
423 QDECREF(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);
431 visit_free(v);
433 /* Beyond limits */
434 qdict = keyval_parse("sz1=-1,"
435 "sz2=18446744073709550592", /* fffffffffffffc00 */
436 NULL, &error_abort);
437 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
438 QDECREF(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);
445 visit_free(v);
447 /* Suffixes */
448 qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
449 NULL, &error_abort);
450 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
451 QDECREF(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);
465 visit_free(v);
467 /* Beyond limit with suffix */
468 qdict = keyval_parse("sz1=16777216T", NULL, &error_abort);
469 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
470 QDECREF(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);
475 visit_free(v);
477 /* Trailing crap */
478 qdict = keyval_parse("sz1=16E,sz2=16Gi", NULL, &error_abort);
479 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
480 QDECREF(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);
487 visit_free(v);
490 static void test_keyval_visit_dict(void)
492 Error *err = NULL;
493 Visitor *v;
494 QDict *qdict;
495 int64_t i;
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));
499 QDECREF(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);
513 visit_free(v);
515 qdict = keyval_parse("a.b=", NULL, &error_abort);
516 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
517 QDECREF(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);
527 visit_free(v);
530 static void test_keyval_visit_list(void)
532 Error *err = NULL;
533 Visitor *v;
534 QDict *qdict;
535 char *s;
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));
540 QDECREF(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, ==, "");
545 g_free(s);
546 visit_type_str(v, NULL, &s, &error_abort);
547 g_assert_cmpstr(s, ==, "I");
548 g_free(s);
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");
552 g_free(s);
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);
559 visit_free(v);
561 qdict = keyval_parse("a.0=,b.0.0=head", NULL, &error_abort);
562 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
563 QDECREF(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");
573 g_free(s);
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);
580 visit_free(v);
583 static void test_keyval_visit_optional(void)
585 Visitor *v;
586 QDict *qdict;
587 bool present;
588 int64_t i;
590 qdict = keyval_parse("a.b=1", NULL, &error_abort);
591 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
592 QDECREF(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);
609 visit_free(v);
612 static void test_keyval_visit_alternate(void)
614 Error *err = NULL;
615 Visitor *v;
616 QDict *qdict;
617 AltNumStr *ans;
618 AltNumInt *ani;
621 * Can't do scalar alternate variants other than string. You get
622 * the string variant if there is one, else an error.
624 qdict = keyval_parse("a=1,b=2", NULL, &error_abort);
625 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
626 QDECREF(qdict);
627 visit_start_struct(v, NULL, NULL, 0, &error_abort);
628 visit_type_AltNumStr(v, "a", &ans, &error_abort);
629 g_assert_cmpint(ans->type, ==, QTYPE_QSTRING);
630 g_assert_cmpstr(ans->u.s, ==, "1");
631 visit_type_AltNumInt(v, "a", &ani, &err);
632 error_free_or_abort(&err);
633 visit_end_struct(v, NULL);
634 visit_free(v);
637 static void test_keyval_visit_any(void)
639 Visitor *v;
640 QDict *qdict;
641 QObject *any;
642 QList *qlist;
643 QString *qstr;
645 qdict = keyval_parse("a.0=null,a.1=1", NULL, &error_abort);
646 v = qobject_input_visitor_new_keyval(QOBJECT(qdict));
647 QDECREF(qdict);
648 visit_start_struct(v, NULL, NULL, 0, &error_abort);
649 visit_type_any(v, "a", &any, &error_abort);
650 qlist = qobject_to_qlist(any);
651 g_assert(qlist);
652 qstr = qobject_to_qstring(qlist_pop(qlist));
653 g_assert_cmpstr(qstring_get_str(qstr), ==, "null");
654 qstr = qobject_to_qstring(qlist_pop(qlist));
655 g_assert_cmpstr(qstring_get_str(qstr), ==, "1");
656 g_assert(qlist_empty(qlist));
657 visit_check_struct(v, &error_abort);
658 visit_end_struct(v, NULL);
659 visit_free(v);
662 int main(int argc, char *argv[])
664 g_test_init(&argc, &argv, NULL);
665 g_test_add_func("/keyval/keyval_parse", test_keyval_parse);
666 g_test_add_func("/keyval/keyval_parse/list", test_keyval_parse_list);
667 g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool);
668 g_test_add_func("/keyval/visit/number", test_keyval_visit_number);
669 g_test_add_func("/keyval/visit/size", test_keyval_visit_size);
670 g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict);
671 g_test_add_func("/keyval/visit/list", test_keyval_visit_list);
672 g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional);
673 g_test_add_func("/keyval/visit/alternate", test_keyval_visit_alternate);
674 g_test_add_func("/keyval/visit/any", test_keyval_visit_any);
675 g_test_run();
676 return 0;