qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

test-qemu-opts.c (33338B)


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