]> Git Repo - qemu.git/blame - tests/test-qemu-opts.c
Merge remote-tracking branch 'remotes/maxreitz/tags/pull-block-2020-05-05' into staging
[qemu.git] / tests / test-qemu-opts.c
CommitLineData
4ba6fabf
LD
1/*
2 * QemuOpts unit-tests.
3 *
4 * Copyright (C) 2014 Leandro Dorileo <[email protected]>
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
681c28a3 10#include "qemu/osdep.h"
d23b6caa 11#include "qemu/units.h"
922a01a0 12#include "qemu/option.h"
37974a97 13#include "qemu/option_int.h"
da34e65c 14#include "qapi/error.h"
452fcdbc 15#include "qapi/qmp/qdict.h"
4ba6fabf
LD
16#include "qapi/qmp/qstring.h"
17#include "qemu/config-file.h"
18
4ba6fabf
LD
19
20static 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,
575ef8bf
KW
27 .help = "Help texts are preserved in qemu_opts_append",
28 .def_value_str = "default",
4ba6fabf
LD
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,
575ef8bf 38 .help = "Having help texts only for some options is okay",
694baf57
MA
39 },{
40 .name = "number2",
41 .type = QEMU_OPT_NUMBER,
4ba6fabf
LD
42 },
43 { /* end of list */ }
44 },
45};
46
47static 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,
694baf57
MA
54 },{
55 .name = "str2",
56 .type = QEMU_OPT_STRING,
4ba6fabf
LD
57 },{
58 .name = "bool1",
59 .type = QEMU_OPT_BOOL,
60 },{
694baf57
MA
61 .name = "bool2",
62 .type = QEMU_OPT_BOOL,
4ba6fabf
LD
63 },{
64 .name = "size1",
65 .type = QEMU_OPT_SIZE,
694baf57
MA
66 },{
67 .name = "size2",
68 .type = QEMU_OPT_SIZE,
69 },{
70 .name = "size3",
71 .type = QEMU_OPT_SIZE,
4ba6fabf
LD
72 },
73 { /* end of list */ }
74 },
75};
76
748bfb4e 77static QemuOptsList opts_list_03 = {
4ba6fabf 78 .name = "opts_list_03",
694baf57 79 .implied_opt_name = "implied",
4ba6fabf
LD
80 .head = QTAILQ_HEAD_INITIALIZER(opts_list_03.head),
81 .desc = {
82 /* no elements => accept any params */
83 { /* end of list */ }
84 },
85};
86
87static 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
94static 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);
157db293 102 error_free_or_abort(&err);
4ba6fabf
LD
103}
104
105static 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
115static 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
145static 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
f43e47db 169 qemu_opt_set(opts, "str2", "value", &error_abort);
4ba6fabf
LD
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
f43e47db 175 qemu_opt_set(opts, "str2", "value2", &error_abort);
4ba6fabf
LD
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
188static void test_qemu_opt_get_bool(void)
189{
cccb7967 190 Error *err = NULL;
4ba6fabf
LD
191 QemuOptsList *list;
192 QemuOpts *opts;
193 bool opt;
4ba6fabf
LD
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
cccb7967
MA
213 qemu_opt_set_bool(opts, "bool1", true, &err);
214 g_assert(!err);
4ba6fabf
LD
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 */
cccb7967
MA
221 qemu_opt_set_bool(opts, "bool1", false, &err);
222 g_assert(!err);
4ba6fabf
LD
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
234static void test_qemu_opt_get_number(void)
235{
39101f25 236 Error *err = NULL;
4ba6fabf
LD
237 QemuOptsList *list;
238 QemuOpts *opts;
239 uint64_t opt;
4ba6fabf
LD
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
39101f25
MA
259 qemu_opt_set_number(opts, "number1", 10, &err);
260 g_assert(!err);
4ba6fabf
LD
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 */
39101f25
MA
267 qemu_opt_set_number(opts, "number1", 15, &err);
268 g_assert(!err);
4ba6fabf
LD
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
280static 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
46f5ac20 308 qdict_put_str(dict, "size1", "10");
4ba6fabf
LD
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 */
46f5ac20 318 qdict_put_str(dict, "size1", "15");
4ba6fabf
LD
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
337static void test_qemu_opt_unset(void)
338{
339 QemuOpts *opts;
340 const char *value;
341 int ret;
342
343 /* dynamically initialized (parsed) opts */
70b94331 344 opts = qemu_opts_parse(&opts_list_03, "key=value", false, NULL);
4ba6fabf
LD
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 */
f43e47db 352 qemu_opt_set(opts, "key", "value2", &error_abort);
4ba6fabf
LD
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
368static void test_qemu_opts_reset(void)
369{
39101f25 370 Error *err = NULL;
4ba6fabf
LD
371 QemuOptsList *list;
372 QemuOpts *opts;
373 uint64_t opt;
4ba6fabf
LD
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
39101f25
MA
393 qemu_opt_set_number(opts, "number1", 10, &err);
394 g_assert(!err);
4ba6fabf
LD
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
407static void test_qemu_opts_set(void)
408{
79087c78 409 Error *err = NULL;
4ba6fabf
LD
410 QemuOptsList *list;
411 QemuOpts *opts;
4ba6fabf
LD
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 */
79087c78
MA
424 qemu_opts_set(list, NULL, "str3", "value", &err);
425 g_assert(!err);
4ba6fabf
LD
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
694baf57
MA
443static 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
450static 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
458static void test_opts_parse(void)
459{
460 Error *err = NULL;
461 QemuOpts *opts;
694baf57
MA
462
463 /* Nothing */
464 opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort);
465 g_assert_cmpuint(opts_count(opts), ==, 0);
466
467 /* Empty key */
468 opts = qemu_opts_parse(&opts_list_03, "=val", false, &error_abort);
469 g_assert_cmpuint(opts_count(opts), ==, 1);
470 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
471
694baf57
MA
472 /* Multiple keys, last one wins */
473 opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3",
474 false, &error_abort);
475 g_assert_cmpuint(opts_count(opts), ==, 3);
476 g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "3");
477 g_assert_cmpstr(qemu_opt_get(opts, "b"), ==, "2,x");
478
479 /* Except when it doesn't */
480 opts = qemu_opts_parse(&opts_list_03, "id=foo,id=bar",
481 false, &error_abort);
482 g_assert_cmpuint(opts_count(opts), ==, 0);
483 g_assert_cmpstr(qemu_opts_id(opts), ==, "foo");
484
485 /* TODO Cover low-level access to repeated keys */
486
487 /* Trailing comma is ignored */
488 opts = qemu_opts_parse(&opts_list_03, "x=y,", false, &error_abort);
489 g_assert_cmpuint(opts_count(opts), ==, 1);
490 g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, "y");
491
492 /* Except when it isn't */
493 opts = qemu_opts_parse(&opts_list_03, ",", false, &error_abort);
494 g_assert_cmpuint(opts_count(opts), ==, 1);
495 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "on");
496
497 /* Duplicate ID */
498 opts = qemu_opts_parse(&opts_list_03, "x=y,id=foo", false, &err);
499 error_free_or_abort(&err);
500 g_assert(!opts);
501 /* TODO Cover .merge_lists = true */
502
933d1527 503 /* Buggy ID recognition (fixed) */
694baf57
MA
504 opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort);
505 g_assert_cmpuint(opts_count(opts), ==, 1);
933d1527 506 g_assert(!qemu_opts_id(opts));
694baf57
MA
507 g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar");
508
509 /* Anti-social ID */
510 opts = qemu_opts_parse(&opts_list_01, "id=666", false, &err);
511 error_free_or_abort(&err);
512 g_assert(!opts);
513
514 /* Implied value */
515 opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=",
516 false, &error_abort);
517 g_assert_cmpuint(opts_count(opts), ==, 3);
518 g_assert_cmpstr(qemu_opt_get(opts, "an"), ==, "on");
519 g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
520 g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
521
0e2052b2
MA
522 /* Implied value, negated empty key */
523 opts = qemu_opts_parse(&opts_list_03, "no", false, &error_abort);
524 g_assert_cmpuint(opts_count(opts), ==, 1);
525 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "off");
526
694baf57
MA
527 /* Implied key */
528 opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", true,
529 &error_abort);
530 g_assert_cmpuint(opts_count(opts), ==, 3);
531 g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "an");
532 g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
533 g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
534
535 /* Implied key with empty value */
536 opts = qemu_opts_parse(&opts_list_03, ",", true, &error_abort);
537 g_assert_cmpuint(opts_count(opts), ==, 1);
538 g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "");
539
540 /* Implied key with comma value */
541 opts = qemu_opts_parse(&opts_list_03, ",,,a=1", true, &error_abort);
542 g_assert_cmpuint(opts_count(opts), ==, 2);
543 g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ",");
544 g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "1");
545
546 /* Empty key is not an implied key */
547 opts = qemu_opts_parse(&opts_list_03, "=val", true, &error_abort);
548 g_assert_cmpuint(opts_count(opts), ==, 1);
549 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
550
551 /* Unknown key */
552 opts = qemu_opts_parse(&opts_list_01, "nonexistent=", false, &err);
553 error_free_or_abort(&err);
554 g_assert(!opts);
555
556 qemu_opts_reset(&opts_list_01);
557 qemu_opts_reset(&opts_list_03);
558}
559
560static void test_opts_parse_bool(void)
561{
562 Error *err = NULL;
563 QemuOpts *opts;
564
565 opts = qemu_opts_parse(&opts_list_02, "bool1=on,bool2=off",
566 false, &error_abort);
567 g_assert_cmpuint(opts_count(opts), ==, 2);
568 g_assert(qemu_opt_get_bool(opts, "bool1", false));
569 g_assert(!qemu_opt_get_bool(opts, "bool2", true));
570
571 opts = qemu_opts_parse(&opts_list_02, "bool1=offer", false, &err);
572 error_free_or_abort(&err);
573 g_assert(!opts);
574
575 qemu_opts_reset(&opts_list_02);
576}
577
578static void test_opts_parse_number(void)
579{
580 Error *err = NULL;
581 QemuOpts *opts;
582
583 /* Lower limit zero */
584 opts = qemu_opts_parse(&opts_list_01, "number1=0", false, &error_abort);
585 g_assert_cmpuint(opts_count(opts), ==, 1);
586 g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 0);
587
588 /* Upper limit 2^64-1 */
589 opts = qemu_opts_parse(&opts_list_01,
590 "number1=18446744073709551615,number2=-1",
591 false, &error_abort);
592 g_assert_cmpuint(opts_count(opts), ==, 2);
593 g_assert_cmphex(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
594 g_assert_cmphex(qemu_opt_get_number(opts, "number2", 0), ==, UINT64_MAX);
595
596 /* Above upper limit */
597 opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616",
3403e5eb
MA
598 false, &err);
599 error_free_or_abort(&err);
600 g_assert(!opts);
694baf57
MA
601
602 /* Below lower limit */
603 opts = qemu_opts_parse(&opts_list_01, "number1=-18446744073709551616",
3403e5eb
MA
604 false, &err);
605 error_free_or_abort(&err);
606 g_assert(!opts);
694baf57
MA
607
608 /* Hex and octal */
609 opts = qemu_opts_parse(&opts_list_01, "number1=0x2a,number2=052",
610 false, &error_abort);
611 g_assert_cmpuint(opts_count(opts), ==, 2);
612 g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
613 g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), ==, 42);
614
615 /* Invalid */
616 opts = qemu_opts_parse(&opts_list_01, "number1=", false, &err);
3403e5eb
MA
617 error_free_or_abort(&err);
618 g_assert(!opts);
694baf57
MA
619 opts = qemu_opts_parse(&opts_list_01, "number1=eins", false, &err);
620 error_free_or_abort(&err);
621 g_assert(!opts);
622
623 /* Leading whitespace */
624 opts = qemu_opts_parse(&opts_list_01, "number1= \t42",
625 false, &error_abort);
626 g_assert_cmpuint(opts_count(opts), ==, 1);
627 g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
628
629 /* Trailing crap */
630 opts = qemu_opts_parse(&opts_list_01, "number1=3.14", false, &err);
631 error_free_or_abort(&err);
632 g_assert(!opts);
633 opts = qemu_opts_parse(&opts_list_01, "number1=08", false, &err);
634 error_free_or_abort(&err);
635 g_assert(!opts);
636 opts = qemu_opts_parse(&opts_list_01, "number1=0 ", false, &err);
637 error_free_or_abort(&err);
638 g_assert(!opts);
639
640 qemu_opts_reset(&opts_list_01);
641}
642
643static void test_opts_parse_size(void)
644{
645 Error *err = NULL;
646 QemuOpts *opts;
647
648 /* Lower limit zero */
649 opts = qemu_opts_parse(&opts_list_02, "size1=0", false, &error_abort);
650 g_assert_cmpuint(opts_count(opts), ==, 1);
651 g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
652
653 /* Note: precision is 53 bits since we're parsing with strtod() */
654
655 /* Around limit of precision: 2^53-1, 2^53, 2^54 */
656 opts = qemu_opts_parse(&opts_list_02,
657 "size1=9007199254740991,"
658 "size2=9007199254740992,"
659 "size3=9007199254740993",
660 false, &error_abort);
661 g_assert_cmpuint(opts_count(opts), ==, 3);
662 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
663 ==, 0x1fffffffffffff);
664 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
665 ==, 0x20000000000000);
666 g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1),
667 ==, 0x20000000000000);
668
669 /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
670 opts = qemu_opts_parse(&opts_list_02,
671 "size1=9223372036854774784," /* 7ffffffffffffc00 */
672 "size2=9223372036854775295", /* 7ffffffffffffdff */
673 false, &error_abort);
674 g_assert_cmpuint(opts_count(opts), ==, 2);
675 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
676 ==, 0x7ffffffffffffc00);
677 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
678 ==, 0x7ffffffffffffc00);
679
680 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
681 opts = qemu_opts_parse(&opts_list_02,
682 "size1=18446744073709549568," /* fffffffffffff800 */
683 "size2=18446744073709550591", /* fffffffffffffbff */
684 false, &error_abort);
685 g_assert_cmpuint(opts_count(opts), ==, 2);
686 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
687 ==, 0xfffffffffffff800);
688 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
689 ==, 0xfffffffffffff800);
690
691 /* Beyond limits */
692 opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err);
693 error_free_or_abort(&err);
694 g_assert(!opts);
695 opts = qemu_opts_parse(&opts_list_02,
696 "size1=18446744073709550592", /* fffffffffffffc00 */
75cdcd15
MA
697 false, &err);
698 error_free_or_abort(&err);
699 g_assert(!opts);
694baf57
MA
700
701 /* Suffixes */
702 opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M",
703 false, &error_abort);
704 g_assert_cmpuint(opts_count(opts), ==, 3);
705 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
706 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
d23b6caa 707 g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * MiB);
694baf57
MA
708 opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
709 false, &error_abort);
710 g_assert_cmpuint(opts_count(opts), ==, 2);
d23b6caa
PMD
711 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 10);
712 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 16777215ULL * TiB);
694baf57
MA
713
714 /* Beyond limit with suffix */
715 opts = qemu_opts_parse(&opts_list_02, "size1=16777216T",
75cdcd15
MA
716 false, &err);
717 error_free_or_abort(&err);
718 g_assert(!opts);
694baf57
MA
719
720 /* Trailing crap */
721 opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err);
722 error_free_or_abort(&err);
723 g_assert(!opts);
75cdcd15
MA
724 opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &err);
725 error_free_or_abort(&err);
726 g_assert(!opts);
694baf57
MA
727
728 qemu_opts_reset(&opts_list_02);
729}
730
32c2dcf5
MA
731static void test_has_help_option(void)
732{
733 static const struct {
734 const char *params;
32c2dcf5 735 /* expected value of qemu_opt_has_help_opt() with implied=false */
59d27ebc 736 bool expect;
32c2dcf5 737 /* expected value of qemu_opt_has_help_opt() with implied=true */
59d27ebc 738 bool expect_implied;
32c2dcf5 739 } test[] = {
59d27ebc
MA
740 { "help", true, false },
741 { "?", true, false },
742 { "helpme", false, false },
743 { "?me", false, false },
744 { "a,help", true, true },
745 { "a,?", true, true },
746 { "a=0,help,b", true, true },
747 { "a=0,?,b", true, true },
748 { "help,b=1", true, false },
749 { "?,b=1", true, false },
750 { "a,b,,help", true, true },
751 { "a,b,,?", true, true },
32c2dcf5
MA
752 };
753 int i;
754 QemuOpts *opts;
755
756 for (i = 0; i < ARRAY_SIZE(test); i++) {
757 g_assert_cmpint(has_help_option(test[i].params),
59d27ebc 758 ==, test[i].expect);
32c2dcf5
MA
759 opts = qemu_opts_parse(&opts_list_03, test[i].params, false,
760 &error_abort);
761 g_assert_cmpint(qemu_opt_has_help_opt(opts),
59d27ebc 762 ==, test[i].expect);
32c2dcf5
MA
763 qemu_opts_del(opts);
764 opts = qemu_opts_parse(&opts_list_03, test[i].params, true,
765 &error_abort);
766 g_assert_cmpint(qemu_opt_has_help_opt(opts),
59d27ebc 767 ==, test[i].expect_implied);
32c2dcf5
MA
768 qemu_opts_del(opts);
769 }
770}
771
575ef8bf
KW
772static void append_verify_list_01(QemuOptDesc *desc, bool with_overlapping)
773{
774 int i = 0;
775
776 if (with_overlapping) {
777 g_assert_cmpstr(desc[i].name, ==, "str1");
778 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
779 g_assert_cmpstr(desc[i].help, ==,
780 "Help texts are preserved in qemu_opts_append");
781 g_assert_cmpstr(desc[i].def_value_str, ==, "default");
782 i++;
783
784 g_assert_cmpstr(desc[i].name, ==, "str2");
785 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
786 g_assert_cmpstr(desc[i].help, ==, NULL);
787 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
788 i++;
789 }
790
791 g_assert_cmpstr(desc[i].name, ==, "str3");
792 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
793 g_assert_cmpstr(desc[i].help, ==, NULL);
794 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
795 i++;
796
797 g_assert_cmpstr(desc[i].name, ==, "number1");
798 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
799 g_assert_cmpstr(desc[i].help, ==,
800 "Having help texts only for some options is okay");
801 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
802 i++;
803
804 g_assert_cmpstr(desc[i].name, ==, "number2");
805 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
806 g_assert_cmpstr(desc[i].help, ==, NULL);
807 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
808 i++;
809
810 g_assert_cmpstr(desc[i].name, ==, NULL);
811}
812
813static void append_verify_list_02(QemuOptDesc *desc)
814{
815 int i = 0;
816
817 g_assert_cmpstr(desc[i].name, ==, "str1");
818 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
819 g_assert_cmpstr(desc[i].help, ==, NULL);
820 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
821 i++;
822
823 g_assert_cmpstr(desc[i].name, ==, "str2");
824 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
825 g_assert_cmpstr(desc[i].help, ==, NULL);
826 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
827 i++;
828
829 g_assert_cmpstr(desc[i].name, ==, "bool1");
830 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
831 g_assert_cmpstr(desc[i].help, ==, NULL);
832 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
833 i++;
834
835 g_assert_cmpstr(desc[i].name, ==, "bool2");
836 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
837 g_assert_cmpstr(desc[i].help, ==, NULL);
838 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
839 i++;
840
841 g_assert_cmpstr(desc[i].name, ==, "size1");
842 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
843 g_assert_cmpstr(desc[i].help, ==, NULL);
844 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
845 i++;
846
847 g_assert_cmpstr(desc[i].name, ==, "size2");
848 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
849 g_assert_cmpstr(desc[i].help, ==, NULL);
850 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
851 i++;
852
853 g_assert_cmpstr(desc[i].name, ==, "size3");
854 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
855 g_assert_cmpstr(desc[i].help, ==, NULL);
856 g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
857}
858
859static void test_opts_append_to_null(void)
860{
861 QemuOptsList *merged;
862
863 merged = qemu_opts_append(NULL, &opts_list_01);
864 g_assert(merged != &opts_list_01);
865
866 g_assert_cmpstr(merged->name, ==, NULL);
867 g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
868 g_assert_false(merged->merge_lists);
869
870 append_verify_list_01(merged->desc, true);
871
872 qemu_opts_free(merged);
873}
874
875static void test_opts_append(void)
876{
877 QemuOptsList *first, *merged;
878
879 first = qemu_opts_append(NULL, &opts_list_02);
880 merged = qemu_opts_append(first, &opts_list_01);
881 g_assert(first != &opts_list_02);
882 g_assert(merged != &opts_list_01);
883
884 g_assert_cmpstr(merged->name, ==, NULL);
885 g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
886 g_assert_false(merged->merge_lists);
887
888 append_verify_list_02(&merged->desc[0]);
889 append_verify_list_01(&merged->desc[7], false);
890
891 qemu_opts_free(merged);
892}
893
37974a97
KW
894static void test_opts_to_qdict_basic(void)
895{
896 QemuOpts *opts;
897 QDict *dict;
898
899 opts = qemu_opts_parse(&opts_list_01, "str1=foo,str2=,str3=bar,number1=42",
900 false, &error_abort);
901 g_assert(opts != NULL);
902
903 dict = qemu_opts_to_qdict(opts, NULL);
904 g_assert(dict != NULL);
905
906 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
907 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
908 g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
909 g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
910 g_assert_false(qdict_haskey(dict, "number2"));
911
cb3e7f08 912 qobject_unref(dict);
37974a97
KW
913 qemu_opts_del(opts);
914}
915
916static void test_opts_to_qdict_filtered(void)
917{
918 QemuOptsList *first, *merged;
919 QemuOpts *opts;
920 QDict *dict;
921
922 first = qemu_opts_append(NULL, &opts_list_02);
923 merged = qemu_opts_append(first, &opts_list_01);
924
925 opts = qemu_opts_parse(merged,
926 "str1=foo,str2=,str3=bar,bool1=off,number1=42",
927 false, &error_abort);
928 g_assert(opts != NULL);
929
930 /* Convert to QDict without deleting from opts */
931 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, false);
932 g_assert(dict != NULL);
933 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
934 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
935 g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
936 g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
937 g_assert_false(qdict_haskey(dict, "number2"));
938 g_assert_false(qdict_haskey(dict, "bool1"));
cb3e7f08 939 qobject_unref(dict);
37974a97
KW
940
941 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, false);
942 g_assert(dict != NULL);
943 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
944 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
945 g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
946 g_assert_false(qdict_haskey(dict, "str3"));
947 g_assert_false(qdict_haskey(dict, "number1"));
948 g_assert_false(qdict_haskey(dict, "number2"));
cb3e7f08 949 qobject_unref(dict);
37974a97
KW
950
951 /* Now delete converted options from opts */
952 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, true);
953 g_assert(dict != NULL);
954 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
955 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
956 g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
957 g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
958 g_assert_false(qdict_haskey(dict, "number2"));
959 g_assert_false(qdict_haskey(dict, "bool1"));
cb3e7f08 960 qobject_unref(dict);
37974a97
KW
961
962 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, true);
963 g_assert(dict != NULL);
964 g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
965 g_assert_false(qdict_haskey(dict, "str1"));
966 g_assert_false(qdict_haskey(dict, "str2"));
967 g_assert_false(qdict_haskey(dict, "str3"));
968 g_assert_false(qdict_haskey(dict, "number1"));
969 g_assert_false(qdict_haskey(dict, "number2"));
cb3e7f08 970 qobject_unref(dict);
37974a97
KW
971
972 g_assert_true(QTAILQ_EMPTY(&opts->head));
973
974 qemu_opts_del(opts);
975 qemu_opts_free(merged);
976}
977
978static void test_opts_to_qdict_duplicates(void)
979{
980 QemuOpts *opts;
981 QemuOpt *opt;
982 QDict *dict;
983
984 opts = qemu_opts_parse(&opts_list_03, "foo=a,foo=b", false, &error_abort);
985 g_assert(opts != NULL);
986
987 /* Verify that opts has two options with the same name */
988 opt = QTAILQ_FIRST(&opts->head);
989 g_assert_cmpstr(opt->name, ==, "foo");
990 g_assert_cmpstr(opt->str , ==, "a");
991
992 opt = QTAILQ_NEXT(opt, next);
993 g_assert_cmpstr(opt->name, ==, "foo");
994 g_assert_cmpstr(opt->str , ==, "b");
995
996 opt = QTAILQ_NEXT(opt, next);
997 g_assert(opt == NULL);
998
999 /* In the conversion to QDict, the last one wins */
1000 dict = qemu_opts_to_qdict(opts, NULL);
1001 g_assert(dict != NULL);
1002 g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
cb3e7f08 1003 qobject_unref(dict);
37974a97
KW
1004
1005 /* The last one still wins if entries are deleted, and both are deleted */
1006 dict = qemu_opts_to_qdict_filtered(opts, NULL, NULL, true);
1007 g_assert(dict != NULL);
1008 g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
cb3e7f08 1009 qobject_unref(dict);
37974a97
KW
1010
1011 g_assert_true(QTAILQ_EMPTY(&opts->head));
1012
1013 qemu_opts_del(opts);
1014}
575ef8bf 1015
4ba6fabf
LD
1016int main(int argc, char *argv[])
1017{
1018 register_opts();
1019 g_test_init(&argc, &argv, NULL);
1020 g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts);
1021 g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts);
1022 g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create);
1023 g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get);
1024 g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool);
1025 g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number);
1026 g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size);
1027 g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset);
1028 g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset);
1029 g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set);
694baf57
MA
1030 g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse);
1031 g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool);
1032 g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number);
1033 g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size);
32c2dcf5 1034 g_test_add_func("/qemu-opts/has_help_option", test_has_help_option);
575ef8bf
KW
1035 g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null);
1036 g_test_add_func("/qemu-opts/append", test_opts_append);
37974a97
KW
1037 g_test_add_func("/qemu-opts/to_qdict/basic", test_opts_to_qdict_basic);
1038 g_test_add_func("/qemu-opts/to_qdict/filtered", test_opts_to_qdict_filtered);
1039 g_test_add_func("/qemu-opts/to_qdict/duplicates", test_opts_to_qdict_duplicates);
4ba6fabf
LD
1040 g_test_run();
1041 return 0;
1042}
This page took 0.446212 seconds and 4 git commands to generate.