xref: /qemu/tests/unit/test-qemu-opts.c (revision 37974a97d4d29229255b39ddd16c31743e1880ed)
1 /*
2  * QemuOpts unit-tests.
3  *
4  * Copyright (C) 2014 Leandro Dorileo <l@dorileo.org>
5  *
6  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
7  * See the COPYING.LIB file in the top-level directory.
8  */
9 
10 #include "qemu/osdep.h"
11 #include "qemu/cutils.h"
12 #include "qemu/option.h"
13 #include "qemu/option_int.h"
14 #include "qapi/error.h"
15 #include "qapi/qmp/qdict.h"
16 #include "qapi/qmp/qstring.h"
17 #include "qemu/config-file.h"
18 
19 
20 static QemuOptsList opts_list_01 = {
21     .name = "opts_list_01",
22     .head = QTAILQ_HEAD_INITIALIZER(opts_list_01.head),
23     .desc = {
24         {
25             .name = "str1",
26             .type = QEMU_OPT_STRING,
27             .help = "Help texts are preserved in qemu_opts_append",
28             .def_value_str = "default",
29         },{
30             .name = "str2",
31             .type = QEMU_OPT_STRING,
32         },{
33             .name = "str3",
34             .type = QEMU_OPT_STRING,
35         },{
36             .name = "number1",
37             .type = QEMU_OPT_NUMBER,
38             .help = "Having help texts only for some options is okay",
39         },{
40             .name = "number2",
41             .type = QEMU_OPT_NUMBER,
42         },
43         { /* end of list */ }
44     },
45 };
46 
47 static QemuOptsList opts_list_02 = {
48     .name = "opts_list_02",
49     .head = QTAILQ_HEAD_INITIALIZER(opts_list_02.head),
50     .desc = {
51         {
52             .name = "str1",
53             .type = QEMU_OPT_STRING,
54         },{
55             .name = "str2",
56             .type = QEMU_OPT_STRING,
57         },{
58             .name = "bool1",
59             .type = QEMU_OPT_BOOL,
60         },{
61             .name = "bool2",
62             .type = QEMU_OPT_BOOL,
63         },{
64             .name = "size1",
65             .type = QEMU_OPT_SIZE,
66         },{
67             .name = "size2",
68             .type = QEMU_OPT_SIZE,
69         },{
70             .name = "size3",
71             .type = QEMU_OPT_SIZE,
72         },
73         { /* end of list */ }
74     },
75 };
76 
77 static QemuOptsList opts_list_03 = {
78     .name = "opts_list_03",
79     .implied_opt_name = "implied",
80     .head = QTAILQ_HEAD_INITIALIZER(opts_list_03.head),
81     .desc = {
82         /* no elements => accept any params */
83         { /* end of list */ }
84     },
85 };
86 
87 static void register_opts(void)
88 {
89     qemu_add_opts(&opts_list_01);
90     qemu_add_opts(&opts_list_02);
91     qemu_add_opts(&opts_list_03);
92 }
93 
94 static void test_find_unknown_opts(void)
95 {
96     QemuOptsList *list;
97     Error *err = NULL;
98 
99     /* should not return anything, we don't have an "unknown" option */
100     list = qemu_find_opts_err("unknown", &err);
101     g_assert(list == NULL);
102     error_free_or_abort(&err);
103 }
104 
105 static void test_qemu_find_opts(void)
106 {
107     QemuOptsList *list;
108 
109     /* we have an "opts_list_01" option, should return it */
110     list = qemu_find_opts("opts_list_01");
111     g_assert(list != NULL);
112     g_assert_cmpstr(list->name, ==, "opts_list_01");
113 }
114 
115 static void test_qemu_opts_create(void)
116 {
117     QemuOptsList *list;
118     QemuOpts *opts;
119 
120     list = qemu_find_opts("opts_list_01");
121     g_assert(list != NULL);
122     g_assert(QTAILQ_EMPTY(&list->head));
123     g_assert_cmpstr(list->name, ==, "opts_list_01");
124 
125     /* should not find anything at this point */
126     opts = qemu_opts_find(list, NULL);
127     g_assert(opts == NULL);
128 
129     /* create the opts */
130     opts = qemu_opts_create(list, NULL, 0, &error_abort);
131     g_assert(opts != NULL);
132     g_assert(!QTAILQ_EMPTY(&list->head));
133 
134     /* now we've create the opts, must find it */
135     opts = qemu_opts_find(list, NULL);
136     g_assert(opts != NULL);
137 
138     qemu_opts_del(opts);
139 
140     /* should not find anything at this point */
141     opts = qemu_opts_find(list, NULL);
142     g_assert(opts == NULL);
143 }
144 
145 static void test_qemu_opt_get(void)
146 {
147     QemuOptsList *list;
148     QemuOpts *opts;
149     const char *opt = NULL;
150 
151     list = qemu_find_opts("opts_list_01");
152     g_assert(list != NULL);
153     g_assert(QTAILQ_EMPTY(&list->head));
154     g_assert_cmpstr(list->name, ==, "opts_list_01");
155 
156     /* should not find anything at this point */
157     opts = qemu_opts_find(list, NULL);
158     g_assert(opts == NULL);
159 
160     /* create the opts */
161     opts = qemu_opts_create(list, NULL, 0, &error_abort);
162     g_assert(opts != NULL);
163     g_assert(!QTAILQ_EMPTY(&list->head));
164 
165     /* haven't set anything to str2 yet */
166     opt = qemu_opt_get(opts, "str2");
167     g_assert(opt == NULL);
168 
169     qemu_opt_set(opts, "str2", "value", &error_abort);
170 
171     /* now we have set str2, should know about it */
172     opt = qemu_opt_get(opts, "str2");
173     g_assert_cmpstr(opt, ==, "value");
174 
175     qemu_opt_set(opts, "str2", "value2", &error_abort);
176 
177     /* having reset the value, the returned should be the reset one */
178     opt = qemu_opt_get(opts, "str2");
179     g_assert_cmpstr(opt, ==, "value2");
180 
181     qemu_opts_del(opts);
182 
183     /* should not find anything at this point */
184     opts = qemu_opts_find(list, NULL);
185     g_assert(opts == NULL);
186 }
187 
188 static void test_qemu_opt_get_bool(void)
189 {
190     Error *err = NULL;
191     QemuOptsList *list;
192     QemuOpts *opts;
193     bool opt;
194 
195     list = qemu_find_opts("opts_list_02");
196     g_assert(list != NULL);
197     g_assert(QTAILQ_EMPTY(&list->head));
198     g_assert_cmpstr(list->name, ==, "opts_list_02");
199 
200     /* should not find anything at this point */
201     opts = qemu_opts_find(list, NULL);
202     g_assert(opts == NULL);
203 
204     /* create the opts */
205     opts = qemu_opts_create(list, NULL, 0, &error_abort);
206     g_assert(opts != NULL);
207     g_assert(!QTAILQ_EMPTY(&list->head));
208 
209     /* haven't set anything to bool1 yet, so defval should be returned */
210     opt = qemu_opt_get_bool(opts, "bool1", false);
211     g_assert(opt == false);
212 
213     qemu_opt_set_bool(opts, "bool1", true, &err);
214     g_assert(!err);
215 
216     /* now we have set bool1, should know about it */
217     opt = qemu_opt_get_bool(opts, "bool1", false);
218     g_assert(opt == true);
219 
220     /* having reset the value, opt should be the reset one not defval */
221     qemu_opt_set_bool(opts, "bool1", false, &err);
222     g_assert(!err);
223 
224     opt = qemu_opt_get_bool(opts, "bool1", true);
225     g_assert(opt == false);
226 
227     qemu_opts_del(opts);
228 
229     /* should not find anything at this point */
230     opts = qemu_opts_find(list, NULL);
231     g_assert(opts == NULL);
232 }
233 
234 static void test_qemu_opt_get_number(void)
235 {
236     Error *err = NULL;
237     QemuOptsList *list;
238     QemuOpts *opts;
239     uint64_t opt;
240 
241     list = qemu_find_opts("opts_list_01");
242     g_assert(list != NULL);
243     g_assert(QTAILQ_EMPTY(&list->head));
244     g_assert_cmpstr(list->name, ==, "opts_list_01");
245 
246     /* should not find anything at this point */
247     opts = qemu_opts_find(list, NULL);
248     g_assert(opts == NULL);
249 
250     /* create the opts */
251     opts = qemu_opts_create(list, NULL, 0, &error_abort);
252     g_assert(opts != NULL);
253     g_assert(!QTAILQ_EMPTY(&list->head));
254 
255     /* haven't set anything to number1 yet, so defval should be returned */
256     opt = qemu_opt_get_number(opts, "number1", 5);
257     g_assert(opt == 5);
258 
259     qemu_opt_set_number(opts, "number1", 10, &err);
260     g_assert(!err);
261 
262     /* now we have set number1, should know about it */
263     opt = qemu_opt_get_number(opts, "number1", 5);
264     g_assert(opt == 10);
265 
266     /* having reset it, the returned should be the reset one not defval */
267     qemu_opt_set_number(opts, "number1", 15, &err);
268     g_assert(!err);
269 
270     opt = qemu_opt_get_number(opts, "number1", 5);
271     g_assert(opt == 15);
272 
273     qemu_opts_del(opts);
274 
275     /* should not find anything at this point */
276     opts = qemu_opts_find(list, NULL);
277     g_assert(opts == NULL);
278 }
279 
280 static void test_qemu_opt_get_size(void)
281 {
282     QemuOptsList *list;
283     QemuOpts *opts;
284     uint64_t opt;
285     QDict *dict;
286 
287     list = qemu_find_opts("opts_list_02");
288     g_assert(list != NULL);
289     g_assert(QTAILQ_EMPTY(&list->head));
290     g_assert_cmpstr(list->name, ==, "opts_list_02");
291 
292     /* should not find anything at this point */
293     opts = qemu_opts_find(list, NULL);
294     g_assert(opts == NULL);
295 
296     /* create the opts */
297     opts = qemu_opts_create(list, NULL, 0, &error_abort);
298     g_assert(opts != NULL);
299     g_assert(!QTAILQ_EMPTY(&list->head));
300 
301     /* haven't set anything to size1 yet, so defval should be returned */
302     opt = qemu_opt_get_size(opts, "size1", 5);
303     g_assert(opt == 5);
304 
305     dict = qdict_new();
306     g_assert(dict != NULL);
307 
308     qdict_put_str(dict, "size1", "10");
309 
310     qemu_opts_absorb_qdict(opts, dict, &error_abort);
311     g_assert(error_abort == NULL);
312 
313     /* now we have set size1, should know about it */
314     opt = qemu_opt_get_size(opts, "size1", 5);
315     g_assert(opt == 10);
316 
317     /* reset value */
318     qdict_put_str(dict, "size1", "15");
319 
320     qemu_opts_absorb_qdict(opts, dict, &error_abort);
321     g_assert(error_abort == NULL);
322 
323     /* test the reset value */
324     opt = qemu_opt_get_size(opts, "size1", 5);
325     g_assert(opt == 15);
326 
327     qdict_del(dict, "size1");
328     g_free(dict);
329 
330     qemu_opts_del(opts);
331 
332     /* should not find anything at this point */
333     opts = qemu_opts_find(list, NULL);
334     g_assert(opts == NULL);
335 }
336 
337 static void test_qemu_opt_unset(void)
338 {
339     QemuOpts *opts;
340     const char *value;
341     int ret;
342 
343     /* dynamically initialized (parsed) opts */
344     opts = qemu_opts_parse(&opts_list_03, "key=value", false, NULL);
345     g_assert(opts != NULL);
346 
347     /* check default/parsed value */
348     value = qemu_opt_get(opts, "key");
349     g_assert_cmpstr(value, ==, "value");
350 
351     /* reset it to value2 */
352     qemu_opt_set(opts, "key", "value2", &error_abort);
353 
354     value = qemu_opt_get(opts, "key");
355     g_assert_cmpstr(value, ==, "value2");
356 
357     /* unset, valid only for "accept any" */
358     ret = qemu_opt_unset(opts, "key");
359     g_assert(ret == 0);
360 
361     /* after reset the value should be the parsed/default one */
362     value = qemu_opt_get(opts, "key");
363     g_assert_cmpstr(value, ==, "value");
364 
365     qemu_opts_del(opts);
366 }
367 
368 static void test_qemu_opts_reset(void)
369 {
370     Error *err = NULL;
371     QemuOptsList *list;
372     QemuOpts *opts;
373     uint64_t opt;
374 
375     list = qemu_find_opts("opts_list_01");
376     g_assert(list != NULL);
377     g_assert(QTAILQ_EMPTY(&list->head));
378     g_assert_cmpstr(list->name, ==, "opts_list_01");
379 
380     /* should not find anything at this point */
381     opts = qemu_opts_find(list, NULL);
382     g_assert(opts == NULL);
383 
384     /* create the opts */
385     opts = qemu_opts_create(list, NULL, 0, &error_abort);
386     g_assert(opts != NULL);
387     g_assert(!QTAILQ_EMPTY(&list->head));
388 
389     /* haven't set anything to number1 yet, so defval should be returned */
390     opt = qemu_opt_get_number(opts, "number1", 5);
391     g_assert(opt == 5);
392 
393     qemu_opt_set_number(opts, "number1", 10, &err);
394     g_assert(!err);
395 
396     /* now we have set number1, should know about it */
397     opt = qemu_opt_get_number(opts, "number1", 5);
398     g_assert(opt == 10);
399 
400     qemu_opts_reset(list);
401 
402     /* should not find anything at this point */
403     opts = qemu_opts_find(list, NULL);
404     g_assert(opts == NULL);
405 }
406 
407 static void test_qemu_opts_set(void)
408 {
409     Error *err = NULL;
410     QemuOptsList *list;
411     QemuOpts *opts;
412     const char *opt;
413 
414     list = qemu_find_opts("opts_list_01");
415     g_assert(list != NULL);
416     g_assert(QTAILQ_EMPTY(&list->head));
417     g_assert_cmpstr(list->name, ==, "opts_list_01");
418 
419     /* should not find anything at this point */
420     opts = qemu_opts_find(list, NULL);
421     g_assert(opts == NULL);
422 
423     /* implicitly create opts and set str3 value */
424     qemu_opts_set(list, NULL, "str3", "value", &err);
425     g_assert(!err);
426     g_assert(!QTAILQ_EMPTY(&list->head));
427 
428     /* get the just created opts */
429     opts = qemu_opts_find(list, NULL);
430     g_assert(opts != NULL);
431 
432     /* check the str3 value */
433     opt = qemu_opt_get(opts, "str3");
434     g_assert_cmpstr(opt, ==, "value");
435 
436     qemu_opts_del(opts);
437 
438     /* should not find anything at this point */
439     opts = qemu_opts_find(list, NULL);
440     g_assert(opts == NULL);
441 }
442 
443 static int opts_count_iter(void *opaque, const char *name, const char *value,
444                            Error **errp)
445 {
446     (*(size_t *)opaque)++;
447     return 0;
448 }
449 
450 static size_t opts_count(QemuOpts *opts)
451 {
452     size_t n = 0;
453 
454     qemu_opt_foreach(opts, opts_count_iter, &n, NULL);
455     return n;
456 }
457 
458 static void test_opts_parse(void)
459 {
460     Error *err = NULL;
461     QemuOpts *opts;
462     char long_key[129];
463     char *params;
464 
465     /* Nothing */
466     opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort);
467     g_assert_cmpuint(opts_count(opts), ==, 0);
468 
469     /* Empty key */
470     opts = qemu_opts_parse(&opts_list_03, "=val", false, &error_abort);
471     g_assert_cmpuint(opts_count(opts), ==, 1);
472     g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
473 
474     /* Long key */
475     memset(long_key, 'a', 127);
476     long_key[127] = 'z';
477     long_key[128] = 0;
478     params = g_strdup_printf("%s=v", long_key);
479     opts = qemu_opts_parse(&opts_list_03, params + 1, NULL, &error_abort);
480     g_assert_cmpuint(opts_count(opts), ==, 1);
481     g_assert_cmpstr(qemu_opt_get(opts, long_key + 1), ==, "v");
482 
483     /* Overlong key gets truncated */
484     opts = qemu_opts_parse(&opts_list_03, params, NULL, &error_abort);
485     g_assert(opts_count(opts) == 1);
486     long_key[127] = 0;
487     g_assert_cmpstr(qemu_opt_get(opts, long_key), ==, "v");
488     g_free(params);
489 
490     /* Multiple keys, last one wins */
491     opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3",
492                            false, &error_abort);
493     g_assert_cmpuint(opts_count(opts), ==, 3);
494     g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "3");
495     g_assert_cmpstr(qemu_opt_get(opts, "b"), ==, "2,x");
496 
497     /* Except when it doesn't */
498     opts = qemu_opts_parse(&opts_list_03, "id=foo,id=bar",
499                            false, &error_abort);
500     g_assert_cmpuint(opts_count(opts), ==, 0);
501     g_assert_cmpstr(qemu_opts_id(opts), ==, "foo");
502 
503     /* TODO Cover low-level access to repeated keys */
504 
505     /* Trailing comma is ignored */
506     opts = qemu_opts_parse(&opts_list_03, "x=y,", false, &error_abort);
507     g_assert_cmpuint(opts_count(opts), ==, 1);
508     g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, "y");
509 
510     /* Except when it isn't */
511     opts = qemu_opts_parse(&opts_list_03, ",", false, &error_abort);
512     g_assert_cmpuint(opts_count(opts), ==, 1);
513     g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "on");
514 
515     /* Duplicate ID */
516     opts = qemu_opts_parse(&opts_list_03, "x=y,id=foo", false, &err);
517     error_free_or_abort(&err);
518     g_assert(!opts);
519     /* TODO Cover .merge_lists = true */
520 
521     /* Buggy ID recognition */
522     opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort);
523     g_assert_cmpuint(opts_count(opts), ==, 1);
524     g_assert_cmpstr(qemu_opts_id(opts), ==, "bar"); /* BUG */
525     g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar");
526 
527     /* Anti-social ID */
528     opts = qemu_opts_parse(&opts_list_01, "id=666", false, &err);
529     error_free_or_abort(&err);
530     g_assert(!opts);
531 
532     /* Implied value */
533     opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=",
534                            false, &error_abort);
535     g_assert_cmpuint(opts_count(opts), ==, 3);
536     g_assert_cmpstr(qemu_opt_get(opts, "an"), ==, "on");
537     g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
538     g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
539 
540     /* Implied value, negated empty key */
541     opts = qemu_opts_parse(&opts_list_03, "no", false, &error_abort);
542     g_assert_cmpuint(opts_count(opts), ==, 1);
543     g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "off");
544 
545     /* Implied key */
546     opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", true,
547                            &error_abort);
548     g_assert_cmpuint(opts_count(opts), ==, 3);
549     g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "an");
550     g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
551     g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
552 
553     /* Implied key with empty value */
554     opts = qemu_opts_parse(&opts_list_03, ",", true, &error_abort);
555     g_assert_cmpuint(opts_count(opts), ==, 1);
556     g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "");
557 
558     /* Implied key with comma value */
559     opts = qemu_opts_parse(&opts_list_03, ",,,a=1", true, &error_abort);
560     g_assert_cmpuint(opts_count(opts), ==, 2);
561     g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ",");
562     g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "1");
563 
564     /* Empty key is not an implied key */
565     opts = qemu_opts_parse(&opts_list_03, "=val", true, &error_abort);
566     g_assert_cmpuint(opts_count(opts), ==, 1);
567     g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
568 
569     /* Unknown key */
570     opts = qemu_opts_parse(&opts_list_01, "nonexistent=", false, &err);
571     error_free_or_abort(&err);
572     g_assert(!opts);
573 
574     qemu_opts_reset(&opts_list_01);
575     qemu_opts_reset(&opts_list_03);
576 }
577 
578 static void test_opts_parse_bool(void)
579 {
580     Error *err = NULL;
581     QemuOpts *opts;
582 
583     opts = qemu_opts_parse(&opts_list_02, "bool1=on,bool2=off",
584                            false, &error_abort);
585     g_assert_cmpuint(opts_count(opts), ==, 2);
586     g_assert(qemu_opt_get_bool(opts, "bool1", false));
587     g_assert(!qemu_opt_get_bool(opts, "bool2", true));
588 
589     opts = qemu_opts_parse(&opts_list_02, "bool1=offer", false, &err);
590     error_free_or_abort(&err);
591     g_assert(!opts);
592 
593     qemu_opts_reset(&opts_list_02);
594 }
595 
596 static void test_opts_parse_number(void)
597 {
598     Error *err = NULL;
599     QemuOpts *opts;
600 
601     /* Lower limit zero */
602     opts = qemu_opts_parse(&opts_list_01, "number1=0", false, &error_abort);
603     g_assert_cmpuint(opts_count(opts), ==, 1);
604     g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 0);
605 
606     /* Upper limit 2^64-1 */
607     opts = qemu_opts_parse(&opts_list_01,
608                            "number1=18446744073709551615,number2=-1",
609                            false, &error_abort);
610     g_assert_cmpuint(opts_count(opts), ==, 2);
611     g_assert_cmphex(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
612     g_assert_cmphex(qemu_opt_get_number(opts, "number2", 0), ==, UINT64_MAX);
613 
614     /* Above upper limit */
615     opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616",
616                            false, &err);
617     error_free_or_abort(&err);
618     g_assert(!opts);
619 
620     /* Below lower limit */
621     opts = qemu_opts_parse(&opts_list_01, "number1=-18446744073709551616",
622                            false, &err);
623     error_free_or_abort(&err);
624     g_assert(!opts);
625 
626     /* Hex and octal */
627     opts = qemu_opts_parse(&opts_list_01, "number1=0x2a,number2=052",
628                            false, &error_abort);
629     g_assert_cmpuint(opts_count(opts), ==, 2);
630     g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
631     g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), ==, 42);
632 
633     /* Invalid */
634     opts = qemu_opts_parse(&opts_list_01, "number1=", false, &err);
635     error_free_or_abort(&err);
636     g_assert(!opts);
637     opts = qemu_opts_parse(&opts_list_01, "number1=eins", false, &err);
638     error_free_or_abort(&err);
639     g_assert(!opts);
640 
641     /* Leading whitespace */
642     opts = qemu_opts_parse(&opts_list_01, "number1= \t42",
643                            false, &error_abort);
644     g_assert_cmpuint(opts_count(opts), ==, 1);
645     g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
646 
647     /* Trailing crap */
648     opts = qemu_opts_parse(&opts_list_01, "number1=3.14", false, &err);
649     error_free_or_abort(&err);
650     g_assert(!opts);
651     opts = qemu_opts_parse(&opts_list_01, "number1=08", false, &err);
652     error_free_or_abort(&err);
653     g_assert(!opts);
654     opts = qemu_opts_parse(&opts_list_01, "number1=0 ", false, &err);
655     error_free_or_abort(&err);
656     g_assert(!opts);
657 
658     qemu_opts_reset(&opts_list_01);
659 }
660 
661 static void test_opts_parse_size(void)
662 {
663     Error *err = NULL;
664     QemuOpts *opts;
665 
666     /* Lower limit zero */
667     opts = qemu_opts_parse(&opts_list_02, "size1=0", false, &error_abort);
668     g_assert_cmpuint(opts_count(opts), ==, 1);
669     g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
670 
671     /* Note: precision is 53 bits since we're parsing with strtod() */
672 
673     /* Around limit of precision: 2^53-1, 2^53, 2^54 */
674     opts = qemu_opts_parse(&opts_list_02,
675                            "size1=9007199254740991,"
676                            "size2=9007199254740992,"
677                            "size3=9007199254740993",
678                            false, &error_abort);
679     g_assert_cmpuint(opts_count(opts), ==, 3);
680     g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
681                      ==, 0x1fffffffffffff);
682     g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
683                      ==, 0x20000000000000);
684     g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1),
685                      ==, 0x20000000000000);
686 
687     /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
688     opts = qemu_opts_parse(&opts_list_02,
689                            "size1=9223372036854774784," /* 7ffffffffffffc00 */
690                            "size2=9223372036854775295", /* 7ffffffffffffdff */
691                            false, &error_abort);
692     g_assert_cmpuint(opts_count(opts), ==, 2);
693     g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
694                      ==, 0x7ffffffffffffc00);
695     g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
696                      ==, 0x7ffffffffffffc00);
697 
698     /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
699     opts = qemu_opts_parse(&opts_list_02,
700                            "size1=18446744073709549568," /* fffffffffffff800 */
701                            "size2=18446744073709550591", /* fffffffffffffbff */
702                            false, &error_abort);
703     g_assert_cmpuint(opts_count(opts), ==, 2);
704     g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
705                      ==, 0xfffffffffffff800);
706     g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
707                      ==, 0xfffffffffffff800);
708 
709     /* Beyond limits */
710     opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err);
711     error_free_or_abort(&err);
712     g_assert(!opts);
713     opts = qemu_opts_parse(&opts_list_02,
714                            "size1=18446744073709550592", /* fffffffffffffc00 */
715                            false, &err);
716     error_free_or_abort(&err);
717     g_assert(!opts);
718 
719     /* Suffixes */
720     opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M",
721                            false, &error_abort);
722     g_assert_cmpuint(opts_count(opts), ==, 3);
723     g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
724     g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
725     g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * M_BYTE);
726     opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
727                            false, &error_abort);
728     g_assert_cmpuint(opts_count(opts), ==, 2);
729     g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, G_BYTE / 10);
730     g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0),
731                      ==, 16777215 * T_BYTE);
732 
733     /* Beyond limit with suffix */
734     opts = qemu_opts_parse(&opts_list_02, "size1=16777216T",
735                            false, &err);
736     error_free_or_abort(&err);
737     g_assert(!opts);
738 
739     /* Trailing crap */
740     opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err);
741     error_free_or_abort(&err);
742     g_assert(!opts);
743     opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &err);
744     error_free_or_abort(&err);
745     g_assert(!opts);
746 
747     qemu_opts_reset(&opts_list_02);
748 }
749 
750 static void append_verify_list_01(QemuOptDesc *desc, bool with_overlapping)
751 {
752     int i = 0;
753 
754     if (with_overlapping) {
755         g_assert_cmpstr(desc[i].name, ==, "str1");
756         g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
757         g_assert_cmpstr(desc[i].help, ==,
758                         "Help texts are preserved in qemu_opts_append");
759         g_assert_cmpstr(desc[i].def_value_str, ==, "default");
760         i++;
761 
762         g_assert_cmpstr(desc[i].name, ==, "str2");
763         g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
764         g_assert_cmpstr(desc[i].help, ==, NULL);
765         g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
766         i++;
767     }
768 
769     g_assert_cmpstr(desc[i].name, ==, "str3");
770     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
771     g_assert_cmpstr(desc[i].help, ==, NULL);
772     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
773     i++;
774 
775     g_assert_cmpstr(desc[i].name, ==, "number1");
776     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
777     g_assert_cmpstr(desc[i].help, ==,
778                     "Having help texts only for some options is okay");
779     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
780     i++;
781 
782     g_assert_cmpstr(desc[i].name, ==, "number2");
783     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
784     g_assert_cmpstr(desc[i].help, ==, NULL);
785     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
786     i++;
787 
788     g_assert_cmpstr(desc[i].name, ==, NULL);
789 }
790 
791 static void append_verify_list_02(QemuOptDesc *desc)
792 {
793     int i = 0;
794 
795     g_assert_cmpstr(desc[i].name, ==, "str1");
796     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
797     g_assert_cmpstr(desc[i].help, ==, NULL);
798     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
799     i++;
800 
801     g_assert_cmpstr(desc[i].name, ==, "str2");
802     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
803     g_assert_cmpstr(desc[i].help, ==, NULL);
804     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
805     i++;
806 
807     g_assert_cmpstr(desc[i].name, ==, "bool1");
808     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
809     g_assert_cmpstr(desc[i].help, ==, NULL);
810     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
811     i++;
812 
813     g_assert_cmpstr(desc[i].name, ==, "bool2");
814     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
815     g_assert_cmpstr(desc[i].help, ==, NULL);
816     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
817     i++;
818 
819     g_assert_cmpstr(desc[i].name, ==, "size1");
820     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
821     g_assert_cmpstr(desc[i].help, ==, NULL);
822     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
823     i++;
824 
825     g_assert_cmpstr(desc[i].name, ==, "size2");
826     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
827     g_assert_cmpstr(desc[i].help, ==, NULL);
828     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
829     i++;
830 
831     g_assert_cmpstr(desc[i].name, ==, "size3");
832     g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
833     g_assert_cmpstr(desc[i].help, ==, NULL);
834     g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
835 }
836 
837 static void test_opts_append_to_null(void)
838 {
839     QemuOptsList *merged;
840 
841     merged = qemu_opts_append(NULL, &opts_list_01);
842     g_assert(merged != &opts_list_01);
843 
844     g_assert_cmpstr(merged->name, ==, NULL);
845     g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
846     g_assert_false(merged->merge_lists);
847 
848     append_verify_list_01(merged->desc, true);
849 
850     qemu_opts_free(merged);
851 }
852 
853 static void test_opts_append(void)
854 {
855     QemuOptsList *first, *merged;
856 
857     first = qemu_opts_append(NULL, &opts_list_02);
858     merged = qemu_opts_append(first, &opts_list_01);
859     g_assert(first != &opts_list_02);
860     g_assert(merged != &opts_list_01);
861 
862     g_assert_cmpstr(merged->name, ==, NULL);
863     g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
864     g_assert_false(merged->merge_lists);
865 
866     append_verify_list_02(&merged->desc[0]);
867     append_verify_list_01(&merged->desc[7], false);
868 
869     qemu_opts_free(merged);
870 }
871 
872 static void test_opts_to_qdict_basic(void)
873 {
874     QemuOpts *opts;
875     QDict *dict;
876 
877     opts = qemu_opts_parse(&opts_list_01, "str1=foo,str2=,str3=bar,number1=42",
878                            false, &error_abort);
879     g_assert(opts != NULL);
880 
881     dict = qemu_opts_to_qdict(opts, NULL);
882     g_assert(dict != NULL);
883 
884     g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
885     g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
886     g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
887     g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
888     g_assert_false(qdict_haskey(dict, "number2"));
889 
890     QDECREF(dict);
891     qemu_opts_del(opts);
892 }
893 
894 static void test_opts_to_qdict_filtered(void)
895 {
896     QemuOptsList *first, *merged;
897     QemuOpts *opts;
898     QDict *dict;
899 
900     first = qemu_opts_append(NULL, &opts_list_02);
901     merged = qemu_opts_append(first, &opts_list_01);
902 
903     opts = qemu_opts_parse(merged,
904                            "str1=foo,str2=,str3=bar,bool1=off,number1=42",
905                            false, &error_abort);
906     g_assert(opts != NULL);
907 
908     /* Convert to QDict without deleting from opts */
909     dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, false);
910     g_assert(dict != NULL);
911     g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
912     g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
913     g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
914     g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
915     g_assert_false(qdict_haskey(dict, "number2"));
916     g_assert_false(qdict_haskey(dict, "bool1"));
917     QDECREF(dict);
918 
919     dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, false);
920     g_assert(dict != NULL);
921     g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
922     g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
923     g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
924     g_assert_false(qdict_haskey(dict, "str3"));
925     g_assert_false(qdict_haskey(dict, "number1"));
926     g_assert_false(qdict_haskey(dict, "number2"));
927     QDECREF(dict);
928 
929     /* Now delete converted options from opts */
930     dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, true);
931     g_assert(dict != NULL);
932     g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
933     g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
934     g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
935     g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
936     g_assert_false(qdict_haskey(dict, "number2"));
937     g_assert_false(qdict_haskey(dict, "bool1"));
938     QDECREF(dict);
939 
940     dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, true);
941     g_assert(dict != NULL);
942     g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
943     g_assert_false(qdict_haskey(dict, "str1"));
944     g_assert_false(qdict_haskey(dict, "str2"));
945     g_assert_false(qdict_haskey(dict, "str3"));
946     g_assert_false(qdict_haskey(dict, "number1"));
947     g_assert_false(qdict_haskey(dict, "number2"));
948     QDECREF(dict);
949 
950     g_assert_true(QTAILQ_EMPTY(&opts->head));
951 
952     qemu_opts_del(opts);
953     qemu_opts_free(merged);
954 }
955 
956 static void test_opts_to_qdict_duplicates(void)
957 {
958     QemuOpts *opts;
959     QemuOpt *opt;
960     QDict *dict;
961 
962     opts = qemu_opts_parse(&opts_list_03, "foo=a,foo=b", false, &error_abort);
963     g_assert(opts != NULL);
964 
965     /* Verify that opts has two options with the same name */
966     opt = QTAILQ_FIRST(&opts->head);
967     g_assert_cmpstr(opt->name, ==, "foo");
968     g_assert_cmpstr(opt->str , ==, "a");
969 
970     opt = QTAILQ_NEXT(opt, next);
971     g_assert_cmpstr(opt->name, ==, "foo");
972     g_assert_cmpstr(opt->str , ==, "b");
973 
974     opt = QTAILQ_NEXT(opt, next);
975     g_assert(opt == NULL);
976 
977     /* In the conversion to QDict, the last one wins */
978     dict = qemu_opts_to_qdict(opts, NULL);
979     g_assert(dict != NULL);
980     g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
981     QDECREF(dict);
982 
983     /* The last one still wins if entries are deleted, and both are deleted */
984     dict = qemu_opts_to_qdict_filtered(opts, NULL, NULL, true);
985     g_assert(dict != NULL);
986     g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
987     QDECREF(dict);
988 
989     g_assert_true(QTAILQ_EMPTY(&opts->head));
990 
991     qemu_opts_del(opts);
992 }
993 
994 int main(int argc, char *argv[])
995 {
996     register_opts();
997     g_test_init(&argc, &argv, NULL);
998     g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts);
999     g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts);
1000     g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create);
1001     g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get);
1002     g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool);
1003     g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number);
1004     g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size);
1005     g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset);
1006     g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset);
1007     g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set);
1008     g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse);
1009     g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool);
1010     g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number);
1011     g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size);
1012     g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null);
1013     g_test_add_func("/qemu-opts/append", test_opts_append);
1014     g_test_add_func("/qemu-opts/to_qdict/basic", test_opts_to_qdict_basic);
1015     g_test_add_func("/qemu-opts/to_qdict/filtered", test_opts_to_qdict_filtered);
1016     g_test_add_func("/qemu-opts/to_qdict/duplicates", test_opts_to_qdict_duplicates);
1017     g_test_run();
1018     return 0;
1019 }
1020