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
);
45 memset(long_key
, 'a', 127);
48 params
= g_strdup_printf("k.%s=v", long_key
);
49 qdict
= keyval_parse(params
+ 2, NULL
, &err
);
50 error_free_or_abort(&err
);
53 /* Overlong key fragment */
54 qdict
= keyval_parse(params
, NULL
, &err
);
55 error_free_or_abort(&err
);
59 /* Long key (qemu_opts_parse() accepts and truncates silently) */
60 params
= g_strdup_printf("k.%s=v", long_key
+ 1);
61 qdict
= keyval_parse(params
+ 2, NULL
, &error_abort
);
62 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
63 g_assert_cmpstr(qdict_get_try_str(qdict
, long_key
+ 1), ==, "v");
66 /* Long key fragment */
67 qdict
= keyval_parse(params
, NULL
, &error_abort
);
68 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
69 sub_qdict
= qdict_get_qdict(qdict
, "k");
71 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
72 g_assert_cmpstr(qdict_get_try_str(sub_qdict
, long_key
+ 1), ==, "v");
76 /* Multiple keys, last one wins */
77 qdict
= keyval_parse("a=1,b=2,,x,a=3", NULL
, &error_abort
);
78 g_assert_cmpuint(qdict_size(qdict
), ==, 2);
79 g_assert_cmpstr(qdict_get_try_str(qdict
, "a"), ==, "3");
80 g_assert_cmpstr(qdict_get_try_str(qdict
, "b"), ==, "2,x");
83 /* Even when it doesn't in qemu_opts_parse() */
84 qdict
= keyval_parse("id=foo,id=bar", NULL
, &error_abort
);
85 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
86 g_assert_cmpstr(qdict_get_try_str(qdict
, "id"), ==, "bar");
90 qdict
= keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL
, &error_abort
);
91 g_assert_cmpuint(qdict_size(qdict
), ==, 2);
92 sub_qdict
= qdict_get_qdict(qdict
, "a");
94 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
95 sub_qdict
= qdict_get_qdict(sub_qdict
, "b");
97 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
98 g_assert_cmpstr(qdict_get_try_str(sub_qdict
, "c"), ==, "2");
99 g_assert_cmpstr(qdict_get_try_str(qdict
, "d"), ==, "3");
102 /* Inconsistent dotted keys */
103 qdict
= keyval_parse("a.b=1,a=2", NULL
, &err
);
104 error_free_or_abort(&err
);
106 qdict
= keyval_parse("a.b=1,a.b.c=2", NULL
, &err
);
107 error_free_or_abort(&err
);
110 /* Trailing comma is ignored */
111 qdict
= keyval_parse("x=y,", NULL
, &error_abort
);
112 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
113 g_assert_cmpstr(qdict_get_try_str(qdict
, "x"), ==, "y");
116 /* Except when it isn't */
117 qdict
= keyval_parse(",", NULL
, &err
);
118 error_free_or_abort(&err
);
121 /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */
122 qdict
= keyval_parse("x=,,id=bar", NULL
, &error_abort
);
123 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
124 g_assert_cmpstr(qdict_get_try_str(qdict
, "x"), ==, ",id=bar");
127 /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */
128 qdict
= keyval_parse("id=666", NULL
, &error_abort
);
129 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
130 g_assert_cmpstr(qdict_get_try_str(qdict
, "id"), ==, "666");
133 /* Implied value not supported (unlike qemu_opts_parse()) */
134 qdict
= keyval_parse("an,noaus,noaus=", NULL
, &err
);
135 error_free_or_abort(&err
);
138 /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */
139 qdict
= keyval_parse("no", NULL
, &err
);
140 error_free_or_abort(&err
);
144 qdict
= keyval_parse("an,aus=off,noaus=", "implied", &error_abort
);
145 g_assert_cmpuint(qdict_size(qdict
), ==, 3);
146 g_assert_cmpstr(qdict_get_try_str(qdict
, "implied"), ==, "an");
147 g_assert_cmpstr(qdict_get_try_str(qdict
, "aus"), ==, "off");
148 g_assert_cmpstr(qdict_get_try_str(qdict
, "noaus"), ==, "");
151 /* Implied dotted key */
152 qdict
= keyval_parse("val", "eins.zwei", &error_abort
);
153 g_assert_cmpuint(qdict_size(qdict
), ==, 1);
154 sub_qdict
= qdict_get_qdict(qdict
, "eins");
156 g_assert_cmpuint(qdict_size(sub_qdict
), ==, 1);
157 g_assert_cmpstr(qdict_get_try_str(sub_qdict
, "zwei"), ==, "val");
160 /* Implied key with empty value (qemu_opts_parse() accepts this) */
161 qdict
= keyval_parse(",", "implied", &err
);
162 error_free_or_abort(&err
);
165 /* Likewise (qemu_opts_parse(): implied key with comma value) */
166 qdict
= keyval_parse(",,,a=1", "implied", &err
);
167 error_free_or_abort(&err
);
170 /* Empty key is not an implied key */
171 qdict
= keyval_parse("=val", "implied", &err
);
172 error_free_or_abort(&err
);
176 static void test_keyval_visit_bool(void)
183 qdict
= keyval_parse("bool1=on,bool2=off", NULL
, &error_abort
);
184 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
186 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
187 visit_type_bool(v
, "bool1", &b
, &error_abort
);
189 visit_type_bool(v
, "bool2", &b
, &error_abort
);
191 visit_check_struct(v
, &error_abort
);
192 visit_end_struct(v
, NULL
);
195 qdict
= keyval_parse("bool1=offer", NULL
, &error_abort
);
196 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
198 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
199 visit_type_bool(v
, "bool1", &b
, &err
);
200 error_free_or_abort(&err
);
201 visit_end_struct(v
, NULL
);
205 static void test_keyval_visit_number(void)
212 /* Lower limit zero */
213 qdict
= keyval_parse("number1=0", NULL
, &error_abort
);
214 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
216 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
217 visit_type_uint64(v
, "number1", &u
, &error_abort
);
218 g_assert_cmpuint(u
, ==, 0);
219 visit_check_struct(v
, &error_abort
);
220 visit_end_struct(v
, NULL
);
223 /* Upper limit 2^64-1 */
224 qdict
= keyval_parse("number1=18446744073709551615,number2=-1",
226 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
228 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
229 visit_type_uint64(v
, "number1", &u
, &error_abort
);
230 g_assert_cmphex(u
, ==, UINT64_MAX
);
231 visit_type_uint64(v
, "number2", &u
, &error_abort
);
232 g_assert_cmphex(u
, ==, UINT64_MAX
);
233 visit_check_struct(v
, &error_abort
);
234 visit_end_struct(v
, NULL
);
237 /* Above upper limit */
238 qdict
= keyval_parse("number1=18446744073709551616",
240 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
242 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
243 visit_type_uint64(v
, "number1", &u
, &err
);
244 error_free_or_abort(&err
);
245 visit_end_struct(v
, NULL
);
248 /* Below lower limit */
249 qdict
= keyval_parse("number1=-18446744073709551616",
251 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
253 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
254 visit_type_uint64(v
, "number1", &u
, &err
);
255 error_free_or_abort(&err
);
256 visit_end_struct(v
, NULL
);
260 qdict
= keyval_parse("number1=0x2a,number2=052",
262 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
264 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
265 visit_type_uint64(v
, "number1", &u
, &error_abort
);
266 g_assert_cmpuint(u
, ==, 42);
267 visit_type_uint64(v
, "number2", &u
, &error_abort
);
268 g_assert_cmpuint(u
, ==, 42);
269 visit_check_struct(v
, &error_abort
);
270 visit_end_struct(v
, NULL
);
274 qdict
= keyval_parse("number1=3.14,number2=08",
276 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
278 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
279 visit_type_uint64(v
, "number1", &u
, &err
);
280 error_free_or_abort(&err
);
281 visit_type_uint64(v
, "number2", &u
, &err
);
282 error_free_or_abort(&err
);
283 visit_end_struct(v
, NULL
);
287 static void test_keyval_visit_size(void)
294 /* Lower limit zero */
295 qdict
= keyval_parse("sz1=0", NULL
, &error_abort
);
296 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
298 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
299 visit_type_size(v
, "sz1", &sz
, &error_abort
);
300 g_assert_cmpuint(sz
, ==, 0);
301 visit_check_struct(v
, &error_abort
);
302 visit_end_struct(v
, NULL
);
305 /* Note: precision is 53 bits since we're parsing with strtod() */
307 /* Around limit of precision: 2^53-1, 2^53, 2^53+1 */
308 qdict
= keyval_parse("sz1=9007199254740991,"
309 "sz2=9007199254740992,"
310 "sz3=9007199254740993",
312 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
314 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
315 visit_type_size(v
, "sz1", &sz
, &error_abort
);
316 g_assert_cmphex(sz
, ==, 0x1fffffffffffff);
317 visit_type_size(v
, "sz2", &sz
, &error_abort
);
318 g_assert_cmphex(sz
, ==, 0x20000000000000);
319 visit_type_size(v
, "sz3", &sz
, &error_abort
);
320 g_assert_cmphex(sz
, ==, 0x20000000000000);
321 visit_check_struct(v
, &error_abort
);
322 visit_end_struct(v
, NULL
);
325 /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
326 qdict
= keyval_parse("sz1=9223372036854774784," /* 7ffffffffffffc00 */
327 "sz2=9223372036854775295", /* 7ffffffffffffdff */
329 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
331 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
332 visit_type_size(v
, "sz1", &sz
, &error_abort
);
333 g_assert_cmphex(sz
, ==, 0x7ffffffffffffc00);
334 visit_type_size(v
, "sz2", &sz
, &error_abort
);
335 g_assert_cmphex(sz
, ==, 0x7ffffffffffffc00);
336 visit_check_struct(v
, &error_abort
);
337 visit_end_struct(v
, NULL
);
340 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
341 qdict
= keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */
342 "sz2=18446744073709550591", /* fffffffffffffbff */
344 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
346 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
347 visit_type_size(v
, "sz1", &sz
, &error_abort
);
348 g_assert_cmphex(sz
, ==, 0xfffffffffffff800);
349 visit_type_size(v
, "sz2", &sz
, &error_abort
);
350 g_assert_cmphex(sz
, ==, 0xfffffffffffff800);
351 visit_check_struct(v
, &error_abort
);
352 visit_end_struct(v
, NULL
);
356 qdict
= keyval_parse("sz1=-1,"
357 "sz2=18446744073709550592", /* fffffffffffffc00 */
359 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
361 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
362 visit_type_size(v
, "sz1", &sz
, &err
);
363 error_free_or_abort(&err
);
364 visit_type_size(v
, "sz2", &sz
, &err
);
365 error_free_or_abort(&err
);
366 visit_end_struct(v
, NULL
);
370 qdict
= keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T",
372 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
374 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
375 visit_type_size(v
, "sz1", &sz
, &error_abort
);
376 g_assert_cmpuint(sz
, ==, 8);
377 visit_type_size(v
, "sz2", &sz
, &error_abort
);
378 g_assert_cmpuint(sz
, ==, 1536);
379 visit_type_size(v
, "sz3", &sz
, &error_abort
);
380 g_assert_cmphex(sz
, ==, 2 * M_BYTE
);
381 visit_type_size(v
, "sz4", &sz
, &error_abort
);
382 g_assert_cmphex(sz
, ==, G_BYTE
/ 10);
383 visit_type_size(v
, "sz5", &sz
, &error_abort
);
384 g_assert_cmphex(sz
, ==, 16777215 * T_BYTE
);
385 visit_check_struct(v
, &error_abort
);
386 visit_end_struct(v
, NULL
);
389 /* Beyond limit with suffix */
390 qdict
= keyval_parse("sz1=16777216T", NULL
, &error_abort
);
391 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
393 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
394 visit_type_size(v
, "sz1", &sz
, &err
);
395 error_free_or_abort(&err
);
396 visit_end_struct(v
, NULL
);
400 qdict
= keyval_parse("sz1=16E,sz2=16Gi", 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_type_size(v
, "sz2", &sz
, &err
);
407 error_free_or_abort(&err
);
408 visit_end_struct(v
, NULL
);
412 static void test_keyval_visit_dict(void)
419 qdict
= keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL
, &error_abort
);
420 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
422 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
423 visit_start_struct(v
, "a", NULL
, 0, &error_abort
);
424 visit_start_struct(v
, "b", NULL
, 0, &error_abort
);
425 visit_type_int(v
, "c", &i
, &error_abort
);
426 g_assert_cmpint(i
, ==, 2);
427 visit_check_struct(v
, &error_abort
);
428 visit_end_struct(v
, NULL
);
429 visit_check_struct(v
, &error_abort
);
430 visit_end_struct(v
, NULL
);
431 visit_type_int(v
, "d", &i
, &error_abort
);
432 g_assert_cmpint(i
, ==, 3);
433 visit_check_struct(v
, &error_abort
);
434 visit_end_struct(v
, NULL
);
437 qdict
= keyval_parse("a.b=", NULL
, &error_abort
);
438 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
440 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
441 visit_start_struct(v
, "a", NULL
, 0, &error_abort
);
442 visit_type_int(v
, "c", &i
, &err
); /* a.c missing */
443 error_free_or_abort(&err
);
444 visit_check_struct(v
, &err
);
445 error_free_or_abort(&err
); /* a.b unexpected */
446 visit_end_struct(v
, NULL
);
447 visit_check_struct(v
, &error_abort
);
448 visit_end_struct(v
, NULL
);
452 static void test_keyval_visit_optional(void)
459 qdict
= keyval_parse("a.b=1", NULL
, &error_abort
);
460 v
= qobject_input_visitor_new_keyval(QOBJECT(qdict
));
462 visit_start_struct(v
, NULL
, NULL
, 0, &error_abort
);
463 visit_optional(v
, "b", &present
);
464 g_assert(!present
); /* b missing */
465 visit_optional(v
, "a", &present
);
466 g_assert(present
); /* a present */
467 visit_start_struct(v
, "a", NULL
, 0, &error_abort
);
468 visit_optional(v
, "b", &present
);
469 g_assert(present
); /* a.b present */
470 visit_type_int(v
, "b", &i
, &error_abort
);
471 g_assert_cmpint(i
, ==, 1);
472 visit_optional(v
, "a", &present
);
473 g_assert(!present
); /* a.a missing */
474 visit_check_struct(v
, &error_abort
);
475 visit_end_struct(v
, NULL
);
476 visit_check_struct(v
, &error_abort
);
477 visit_end_struct(v
, NULL
);
481 int main(int argc
, char *argv
[])
483 g_test_init(&argc
, &argv
, NULL
);
484 g_test_add_func("/keyval/keyval_parse", test_keyval_parse
);
485 g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool
);
486 g_test_add_func("/keyval/visit/number", test_keyval_visit_number
);
487 g_test_add_func("/keyval/visit/size", test_keyval_visit_size
);
488 g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict
);
489 g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional
);