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/qobject-input-visitor.h"
16 #include "qemu/cutils.h"
17 #include "qemu/option.h"
19 static void test_keyval_parse(void)
22 QDict
*qdict
, *sub_qdict
;
27 qdict
= keyval_parse("", NULL
, &error_abort
);
28 g_assert_cmpuint(qdict_size(qdict
), ==, 0);
31 /* Empty key (qemu_opts_parse() accepts this) */
32 qdict
= keyval_parse("=val", NULL
, &err
);
33 error_free_or_abort(&err
);
36 /* Empty key fragment */
37 qdict
= keyval_parse(".", NULL
, &err
);
38 error_free_or_abort(&err
);
40 qdict
= keyval_parse("key.", NULL
, &err
);
41 error_free_or_abort(&err
);
44 /* Invalid non-empty key (qemu_opts_parse() doesn't care) */
45 qdict
= keyval_parse("7up=val", NULL
, &err
);
46 error_free_or_abort(&err
);
50 memset(long_key
, 'a', 127);
53 params
= g_strdup_printf("k.%s=v", long_key
);
54 qdict
= keyval_parse(params
+ 2, NULL
, &err
);
55 error_free_or_abort(&err
);
58 /* Overlong key fragment */
59 qdict
= keyval_parse(params
, NULL
, &err
);
60 error_free_or_abort(&err
);
64 /* Long key (qemu_opts_parse() accepts and truncates silently) */
65 params
= g_strdup_printf("k.%s=v", long_key
+ 1);
66 qdict
= keyval_parse(params
+ 2, NULL
, &error_abort
);
67 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
68 g_assert_cmpstr(qdict_get_try_str(qdict
, long_key
+ 1), ==, "v");
71 /* Long key fragment */
72 qdict
= keyval_parse(params
, NULL
, &error_abort
);
73 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
74 sub_qdict
= qdict_get_qdict(qdict
, "k");
76 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
77 g_assert_cmpstr(qdict_get_try_str(sub_qdict
, long_key
+ 1), ==, "v");
81 /* Crap after valid key */
82 qdict
= keyval_parse("key[0]=val", NULL
, &err
);
83 error_free_or_abort(&err
);
86 /* Multiple keys, last one wins */
87 qdict
= keyval_parse("a=1,b=2,,x,a=3", NULL
, &error_abort
);
88 g_assert_cmpuint(qdict_size(qdict
), ==, 2);
89 g_assert_cmpstr(qdict_get_try_str(qdict
, "a"), ==, "3");
90 g_assert_cmpstr(qdict_get_try_str(qdict
, "b"), ==, "2,x");
93 /* Even when it doesn't in qemu_opts_parse() */
94 qdict
= keyval_parse("id=foo,id=bar", NULL
, &error_abort
);
95 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
96 g_assert_cmpstr(qdict_get_try_str(qdict
, "id"), ==, "bar");
100 qdict
= keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL
, &error_abort
);
101 g_assert_cmpuint(qdict_size(qdict
), ==, 2);
102 sub_qdict
= qdict_get_qdict(qdict
, "a");
104 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
105 sub_qdict
= qdict_get_qdict(sub_qdict
, "b");
107 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
108 g_assert_cmpstr(qdict_get_try_str(sub_qdict
, "c"), ==, "2");
109 g_assert_cmpstr(qdict_get_try_str(qdict
, "d"), ==, "3");
112 /* Inconsistent dotted keys */
113 qdict
= keyval_parse("a.b=1,a=2", NULL
, &err
);
114 error_free_or_abort(&err
);
116 qdict
= keyval_parse("a.b=1,a.b.c=2", NULL
, &err
);
117 error_free_or_abort(&err
);
120 /* Trailing comma is ignored */
121 qdict
= keyval_parse("x=y,", NULL
, &error_abort
);
122 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
123 g_assert_cmpstr(qdict_get_try_str(qdict
, "x"), ==, "y");
126 /* Except when it isn't */
127 qdict
= keyval_parse(",", NULL
, &err
);
128 error_free_or_abort(&err
);
131 /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */
132 qdict
= keyval_parse("x=,,id=bar", NULL
, &error_abort
);
133 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
134 g_assert_cmpstr(qdict_get_try_str(qdict
, "x"), ==, ",id=bar");
137 /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */
138 qdict
= keyval_parse("id=666", NULL
, &error_abort
);
139 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
140 g_assert_cmpstr(qdict_get_try_str(qdict
, "id"), ==, "666");
143 /* Implied value not supported (unlike qemu_opts_parse()) */
144 qdict
= keyval_parse("an,noaus,noaus=", NULL
, &err
);
145 error_free_or_abort(&err
);
148 /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */
149 qdict
= keyval_parse("no", NULL
, &err
);
150 error_free_or_abort(&err
);
154 qdict
= keyval_parse("an,aus=off,noaus=", "implied", &error_abort
);
155 g_assert_cmpuint(qdict_size(qdict
), ==, 3);
156 g_assert_cmpstr(qdict_get_try_str(qdict
, "implied"), ==, "an");
157 g_assert_cmpstr(qdict_get_try_str(qdict
, "aus"), ==, "off");
158 g_assert_cmpstr(qdict_get_try_str(qdict
, "noaus"), ==, "");
161 /* Implied dotted key */
162 qdict
= keyval_parse("val", "eins.zwei", &error_abort
);
163 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
164 sub_qdict
= qdict_get_qdict(qdict
, "eins");
166 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
167 g_assert_cmpstr(qdict_get_try_str(sub_qdict
, "zwei"), ==, "val");
170 /* Implied key with empty value (qemu_opts_parse() accepts this) */
171 qdict
= keyval_parse(",", "implied", &err
);
172 error_free_or_abort(&err
);
175 /* Likewise (qemu_opts_parse(): implied key with comma value) */
176 qdict
= keyval_parse(",,,a=1", "implied", &err
);
177 error_free_or_abort(&err
);
180 /* Empty key is not an implied key */
181 qdict
= keyval_parse("=val", "implied", &err
);
182 error_free_or_abort(&err
);
186 static void test_keyval_visit_bool(void)
193 qdict
= keyval_parse("bool1=on,bool2=off", NULL
, &error_abort
);
194 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
196 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
197 visit_type_bool(v
, "bool1", &b
, &error_abort
);
199 visit_type_bool(v
, "bool2", &b
, &error_abort
);
201 visit_check_struct(v
, &error_abort
);
202 visit_end_struct(v
, NULL
);
205 qdict
= keyval_parse("bool1=offer", NULL
, &error_abort
);
206 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
208 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
209 visit_type_bool(v
, "bool1", &b
, &err
);
210 error_free_or_abort(&err
);
211 visit_end_struct(v
, NULL
);
215 static void test_keyval_visit_number(void)
222 /* Lower limit zero */
223 qdict
= keyval_parse("number1=0", NULL
, &error_abort
);
224 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
226 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
227 visit_type_uint64(v
, "number1", &u
, &error_abort
);
228 g_assert_cmpuint(u
, ==, 0);
229 visit_check_struct(v
, &error_abort
);
230 visit_end_struct(v
, NULL
);
233 /* Upper limit 2^64-1 */
234 qdict
= keyval_parse("number1=18446744073709551615,number2=-1",
236 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
238 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
239 visit_type_uint64(v
, "number1", &u
, &error_abort
);
240 g_assert_cmphex(u
, ==, UINT64_MAX
);
241 visit_type_uint64(v
, "number2", &u
, &error_abort
);
242 g_assert_cmphex(u
, ==, UINT64_MAX
);
243 visit_check_struct(v
, &error_abort
);
244 visit_end_struct(v
, NULL
);
247 /* Above upper limit */
248 qdict
= keyval_parse("number1=18446744073709551616",
250 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
252 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
253 visit_type_uint64(v
, "number1", &u
, &err
);
254 error_free_or_abort(&err
);
255 visit_end_struct(v
, NULL
);
258 /* Below lower limit */
259 qdict
= keyval_parse("number1=-18446744073709551616",
261 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
263 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
264 visit_type_uint64(v
, "number1", &u
, &err
);
265 error_free_or_abort(&err
);
266 visit_end_struct(v
, NULL
);
270 qdict
= keyval_parse("number1=0x2a,number2=052",
272 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
274 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
275 visit_type_uint64(v
, "number1", &u
, &error_abort
);
276 g_assert_cmpuint(u
, ==, 42);
277 visit_type_uint64(v
, "number2", &u
, &error_abort
);
278 g_assert_cmpuint(u
, ==, 42);
279 visit_check_struct(v
, &error_abort
);
280 visit_end_struct(v
, NULL
);
284 qdict
= keyval_parse("number1=3.14,number2=08",
286 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
288 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
289 visit_type_uint64(v
, "number1", &u
, &err
);
290 error_free_or_abort(&err
);
291 visit_type_uint64(v
, "number2", &u
, &err
);
292 error_free_or_abort(&err
);
293 visit_end_struct(v
, NULL
);
297 static void test_keyval_visit_size(void)
304 /* Lower limit zero */
305 qdict
= keyval_parse("sz1=0", NULL
, &error_abort
);
306 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
308 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
309 visit_type_size(v
, "sz1", &sz
, &error_abort
);
310 g_assert_cmpuint(sz
, ==, 0);
311 visit_check_struct(v
, &error_abort
);
312 visit_end_struct(v
, NULL
);
315 /* Note: precision is 53 bits since we're parsing with strtod() */
317 /* Around limit of precision: 2^53-1, 2^53, 2^53+1 */
318 qdict
= keyval_parse("sz1=9007199254740991,"
319 "sz2=9007199254740992,"
320 "sz3=9007199254740993",
322 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
324 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
325 visit_type_size(v
, "sz1", &sz
, &error_abort
);
326 g_assert_cmphex(sz
, ==, 0x1fffffffffffff);
327 visit_type_size(v
, "sz2", &sz
, &error_abort
);
328 g_assert_cmphex(sz
, ==, 0x20000000000000);
329 visit_type_size(v
, "sz3", &sz
, &error_abort
);
330 g_assert_cmphex(sz
, ==, 0x20000000000000);
331 visit_check_struct(v
, &error_abort
);
332 visit_end_struct(v
, NULL
);
335 /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
336 qdict
= keyval_parse("sz1=9223372036854774784," /* 7ffffffffffffc00 */
337 "sz2=9223372036854775295", /* 7ffffffffffffdff */
339 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
341 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
342 visit_type_size(v
, "sz1", &sz
, &error_abort
);
343 g_assert_cmphex(sz
, ==, 0x7ffffffffffffc00);
344 visit_type_size(v
, "sz2", &sz
, &error_abort
);
345 g_assert_cmphex(sz
, ==, 0x7ffffffffffffc00);
346 visit_check_struct(v
, &error_abort
);
347 visit_end_struct(v
, NULL
);
350 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
351 qdict
= keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */
352 "sz2=18446744073709550591", /* fffffffffffffbff */
354 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
356 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
357 visit_type_size(v
, "sz1", &sz
, &error_abort
);
358 g_assert_cmphex(sz
, ==, 0xfffffffffffff800);
359 visit_type_size(v
, "sz2", &sz
, &error_abort
);
360 g_assert_cmphex(sz
, ==, 0xfffffffffffff800);
361 visit_check_struct(v
, &error_abort
);
362 visit_end_struct(v
, NULL
);
366 qdict
= keyval_parse("sz1=-1,"
367 "sz2=18446744073709550592", /* fffffffffffffc00 */
369 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
371 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
372 visit_type_size(v
, "sz1", &sz
, &err
);
373 error_free_or_abort(&err
);
374 visit_type_size(v
, "sz2", &sz
, &err
);
375 error_free_or_abort(&err
);
376 visit_end_struct(v
, NULL
);
380 qdict
= keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
382 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
384 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
385 visit_type_size(v
, "sz1", &sz
, &error_abort
);
386 g_assert_cmpuint(sz
, ==, 8);
387 visit_type_size(v
, "sz2", &sz
, &error_abort
);
388 g_assert_cmpuint(sz
, ==, 1536);
389 visit_type_size(v
, "sz3", &sz
, &error_abort
);
390 g_assert_cmphex(sz
, ==, 2 * M_BYTE
);
391 visit_type_size(v
, "sz4", &sz
, &error_abort
);
392 g_assert_cmphex(sz
, ==, G_BYTE
/ 10);
393 visit_type_size(v
, "sz5", &sz
, &error_abort
);
394 g_assert_cmphex(sz
, ==, 16777215 * T_BYTE
);
395 visit_check_struct(v
, &error_abort
);
396 visit_end_struct(v
, NULL
);
399 /* Beyond limit with suffix */
400 qdict
= keyval_parse("sz1=16777216T", NULL
, &error_abort
);
401 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
403 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
404 visit_type_size(v
, "sz1", &sz
, &err
);
405 error_free_or_abort(&err
);
406 visit_end_struct(v
, NULL
);
410 qdict
= keyval_parse("sz1=16E,sz2=16Gi", NULL
, &error_abort
);
411 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
413 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
414 visit_type_size(v
, "sz1", &sz
, &err
);
415 error_free_or_abort(&err
);
416 visit_type_size(v
, "sz2", &sz
, &err
);
417 error_free_or_abort(&err
);
418 visit_end_struct(v
, NULL
);
422 static void test_keyval_visit_dict(void)
429 qdict
= keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL
, &error_abort
);
430 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
432 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
433 visit_start_struct(v
, "a", NULL
, 0, &error_abort
);
434 visit_start_struct(v
, "b", NULL
, 0, &error_abort
);
435 visit_type_int(v
, "c", &i
, &error_abort
);
436 g_assert_cmpint(i
, ==, 2);
437 visit_check_struct(v
, &error_abort
);
438 visit_end_struct(v
, NULL
);
439 visit_check_struct(v
, &error_abort
);
440 visit_end_struct(v
, NULL
);
441 visit_type_int(v
, "d", &i
, &error_abort
);
442 g_assert_cmpint(i
, ==, 3);
443 visit_check_struct(v
, &error_abort
);
444 visit_end_struct(v
, NULL
);
447 qdict
= keyval_parse("a.b=", NULL
, &error_abort
);
448 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
450 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
451 visit_start_struct(v
, "a", NULL
, 0, &error_abort
);
452 visit_type_int(v
, "c", &i
, &err
); /* a.c missing */
453 error_free_or_abort(&err
);
454 visit_check_struct(v
, &err
);
455 error_free_or_abort(&err
); /* a.b unexpected */
456 visit_end_struct(v
, NULL
);
457 visit_check_struct(v
, &error_abort
);
458 visit_end_struct(v
, NULL
);
462 static void test_keyval_visit_optional(void)
469 qdict
= keyval_parse("a.b=1", NULL
, &error_abort
);
470 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
472 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
473 visit_optional(v
, "b", &present
);
474 g_assert(!present
); /* b missing */
475 visit_optional(v
, "a", &present
);
476 g_assert(present
); /* a present */
477 visit_start_struct(v
, "a", NULL
, 0, &error_abort
);
478 visit_optional(v
, "b", &present
);
479 g_assert(present
); /* a.b present */
480 visit_type_int(v
, "b", &i
, &error_abort
);
481 g_assert_cmpint(i
, ==, 1);
482 visit_optional(v
, "a", &present
);
483 g_assert(!present
); /* a.a missing */
484 visit_check_struct(v
, &error_abort
);
485 visit_end_struct(v
, NULL
);
486 visit_check_struct(v
, &error_abort
);
487 visit_end_struct(v
, NULL
);
491 int main(int argc
, char *argv
[])
493 g_test_init(&argc
, &argv
, NULL
);
494 g_test_add_func("/keyval/keyval_parse", test_keyval_parse
);
495 g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool
);
496 g_test_add_func("/keyval/visit/number", test_keyval_visit_number
);
497 g_test_add_func("/keyval/visit/size", test_keyval_visit_size
);
498 g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict
);
499 g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional
);