qemu/tests/unit/test-qemu-opts.c
<<
>>
Prefs
   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
  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,
  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
  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,
  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
  77static 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
  87static 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
 100static 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
 108static 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
 119static 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
 129static 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
 159static 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
 202static 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
 245static 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
 288static 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
 345static 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
 376static 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
 413static void test_qemu_opts_set(void)
 414{
 415    QemuOptsList *list;
 416    QemuOpts *opts;
 417    const char *opt;
 418
 419    list = qemu_find_opts("opts_list_04");
 420    g_assert(list != NULL);
 421    g_assert(QTAILQ_EMPTY(&list->head));
 422    g_assert_cmpstr(list->name, ==, "opts_list_04");
 423
 424    /* should not find anything at this point */
 425    opts = qemu_opts_find(list, NULL);
 426    g_assert(opts == NULL);
 427
 428    /* implicitly create opts and set str3 value */
 429    qemu_opts_set(list, "str3", "value", &error_abort);
 430    g_assert(!QTAILQ_EMPTY(&list->head));
 431
 432    /* get the just created opts */
 433    opts = qemu_opts_find(list, NULL);
 434    g_assert(opts != NULL);
 435
 436    /* check the str3 value */
 437    opt = qemu_opt_get(opts, "str3");
 438    g_assert_cmpstr(opt, ==, "value");
 439
 440    qemu_opts_del(opts);
 441
 442    /* should not find anything at this point */
 443    opts = qemu_opts_find(list, NULL);
 444    g_assert(opts == NULL);
 445}
 446
 447static int opts_count_iter(void *opaque, const char *name, const char *value,
 448                           Error **errp)
 449{
 450    (*(size_t *)opaque)++;
 451    return 0;
 452}
 453
 454static size_t opts_count(QemuOpts *opts)
 455{
 456    size_t n = 0;
 457
 458    qemu_opt_foreach(opts, opts_count_iter, &n, NULL);
 459    return n;
 460}
 461
 462static void test_opts_parse(void)
 463{
 464    Error *err = NULL;
 465    QemuOpts *opts;
 466
 467    /* Nothing */
 468    opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort);
 469    g_assert_cmpuint(opts_count(opts), ==, 0);
 470
 471    /* Empty key */
 472    opts = qemu_opts_parse(&opts_list_03, "=val", false, &error_abort);
 473    g_assert_cmpuint(opts_count(opts), ==, 1);
 474    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
 475
 476    /* Multiple keys, last one wins */
 477    opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3",
 478                           false, &error_abort);
 479    g_assert_cmpuint(opts_count(opts), ==, 3);
 480    g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "3");
 481    g_assert_cmpstr(qemu_opt_get(opts, "b"), ==, "2,x");
 482
 483    /* Except when it doesn't */
 484    opts = qemu_opts_parse(&opts_list_03, "id=foo,id=bar",
 485                           false, &error_abort);
 486    g_assert_cmpuint(opts_count(opts), ==, 0);
 487    g_assert_cmpstr(qemu_opts_id(opts), ==, "foo");
 488
 489    /* TODO Cover low-level access to repeated keys */
 490
 491    /* Trailing comma is ignored */
 492    opts = qemu_opts_parse(&opts_list_03, "x=y,", false, &error_abort);
 493    g_assert_cmpuint(opts_count(opts), ==, 1);
 494    g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, "y");
 495
 496    /* Except when it isn't */
 497    opts = qemu_opts_parse(&opts_list_03, ",", false, &error_abort);
 498    g_assert_cmpuint(opts_count(opts), ==, 1);
 499    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "on");
 500
 501    /* Duplicate ID */
 502    opts = qemu_opts_parse(&opts_list_03, "x=y,id=foo", false, &err);
 503    error_free_or_abort(&err);
 504    g_assert(!opts);
 505    /* TODO Cover .merge_lists = true */
 506
 507    /* Buggy ID recognition (fixed) */
 508    opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort);
 509    g_assert_cmpuint(opts_count(opts), ==, 1);
 510    g_assert(!qemu_opts_id(opts));
 511    g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar");
 512
 513    /* Anti-social ID */
 514    opts = qemu_opts_parse(&opts_list_01, "id=666", false, &err);
 515    error_free_or_abort(&err);
 516    g_assert(!opts);
 517
 518    /* Implied value (qemu_opts_parse warns but accepts it) */
 519    opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=",
 520                           false, &error_abort);
 521    g_assert_cmpuint(opts_count(opts), ==, 3);
 522    g_assert_cmpstr(qemu_opt_get(opts, "an"), ==, "on");
 523    g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
 524    g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
 525
 526    /* Implied value, negated empty key */
 527    opts = qemu_opts_parse(&opts_list_03, "no", false, &error_abort);
 528    g_assert_cmpuint(opts_count(opts), ==, 1);
 529    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "off");
 530
 531    /* Implied key */
 532    opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", true,
 533                           &error_abort);
 534    g_assert_cmpuint(opts_count(opts), ==, 3);
 535    g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "an");
 536    g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
 537    g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
 538
 539    /* Implied key with empty value */
 540    opts = qemu_opts_parse(&opts_list_03, ",", true, &error_abort);
 541    g_assert_cmpuint(opts_count(opts), ==, 1);
 542    g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "");
 543
 544    /* Implied key with comma value */
 545    opts = qemu_opts_parse(&opts_list_03, ",,,a=1", true, &error_abort);
 546    g_assert_cmpuint(opts_count(opts), ==, 2);
 547    g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ",");
 548    g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "1");
 549
 550    /* Empty key is not an implied key */
 551    opts = qemu_opts_parse(&opts_list_03, "=val", true, &error_abort);
 552    g_assert_cmpuint(opts_count(opts), ==, 1);
 553    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
 554
 555    /* Unknown key */
 556    opts = qemu_opts_parse(&opts_list_01, "nonexistent=", false, &err);
 557    error_free_or_abort(&err);
 558    g_assert(!opts);
 559
 560    qemu_opts_reset(&opts_list_01);
 561    qemu_opts_reset(&opts_list_03);
 562}
 563
 564static void test_opts_parse_bool(void)
 565{
 566    Error *err = NULL;
 567    QemuOpts *opts;
 568
 569    opts = qemu_opts_parse(&opts_list_02, "bool1=on,bool2=off",
 570                           false, &error_abort);
 571    g_assert_cmpuint(opts_count(opts), ==, 2);
 572    g_assert(qemu_opt_get_bool(opts, "bool1", false));
 573    g_assert(!qemu_opt_get_bool(opts, "bool2", true));
 574
 575    opts = qemu_opts_parse(&opts_list_02, "bool1=offer", false, &err);
 576    error_free_or_abort(&err);
 577    g_assert(!opts);
 578
 579    qemu_opts_reset(&opts_list_02);
 580}
 581
 582static void test_opts_parse_number(void)
 583{
 584    Error *err = NULL;
 585    QemuOpts *opts;
 586
 587    /* Lower limit zero */
 588    opts = qemu_opts_parse(&opts_list_01, "number1=0", false, &error_abort);
 589    g_assert_cmpuint(opts_count(opts), ==, 1);
 590    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 0);
 591
 592    /* Upper limit 2^64-1 */
 593    opts = qemu_opts_parse(&opts_list_01,
 594                           "number1=18446744073709551615,number2=-1",
 595                           false, &error_abort);
 596    g_assert_cmpuint(opts_count(opts), ==, 2);
 597    g_assert_cmphex(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
 598    g_assert_cmphex(qemu_opt_get_number(opts, "number2", 0), ==, UINT64_MAX);
 599
 600    /* Above upper limit */
 601    opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616",
 602                           false, &err);
 603    error_free_or_abort(&err);
 604    g_assert(!opts);
 605
 606    /* Below lower limit */
 607    opts = qemu_opts_parse(&opts_list_01, "number1=-18446744073709551616",
 608                           false, &err);
 609    error_free_or_abort(&err);
 610    g_assert(!opts);
 611
 612    /* Hex and octal */
 613    opts = qemu_opts_parse(&opts_list_01, "number1=0x2a,number2=052",
 614                           false, &error_abort);
 615    g_assert_cmpuint(opts_count(opts), ==, 2);
 616    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
 617    g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), ==, 42);
 618
 619    /* Invalid */
 620    opts = qemu_opts_parse(&opts_list_01, "number1=", false, &err);
 621    error_free_or_abort(&err);
 622    g_assert(!opts);
 623    opts = qemu_opts_parse(&opts_list_01, "number1=eins", false, &err);
 624    error_free_or_abort(&err);
 625    g_assert(!opts);
 626
 627    /* Leading whitespace */
 628    opts = qemu_opts_parse(&opts_list_01, "number1= \t42",
 629                           false, &error_abort);
 630    g_assert_cmpuint(opts_count(opts), ==, 1);
 631    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
 632
 633    /* Trailing crap */
 634    opts = qemu_opts_parse(&opts_list_01, "number1=3.14", false, &err);
 635    error_free_or_abort(&err);
 636    g_assert(!opts);
 637    opts = qemu_opts_parse(&opts_list_01, "number1=08", false, &err);
 638    error_free_or_abort(&err);
 639    g_assert(!opts);
 640    opts = qemu_opts_parse(&opts_list_01, "number1=0 ", false, &err);
 641    error_free_or_abort(&err);
 642    g_assert(!opts);
 643
 644    qemu_opts_reset(&opts_list_01);
 645}
 646
 647static void test_opts_parse_size(void)
 648{
 649    Error *err = NULL;
 650    QemuOpts *opts;
 651
 652    /* Lower limit zero */
 653    opts = qemu_opts_parse(&opts_list_02, "size1=0", false, &error_abort);
 654    g_assert_cmpuint(opts_count(opts), ==, 1);
 655    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
 656
 657    /* Note: full 64 bits of precision */
 658
 659    /* Around double limit of precision: 2^53-1, 2^53, 2^53+1 */
 660    opts = qemu_opts_parse(&opts_list_02,
 661                           "size1=9007199254740991,"
 662                           "size2=9007199254740992,"
 663                           "size3=9007199254740993",
 664                           false, &error_abort);
 665    g_assert_cmpuint(opts_count(opts), ==, 3);
 666    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
 667                     ==, 0x1fffffffffffff);
 668    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
 669                     ==, 0x20000000000000);
 670    g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1),
 671                     ==, 0x20000000000001);
 672
 673    /* Close to signed int limit: 2^63-1, 2^63, 2^63+1 */
 674    opts = qemu_opts_parse(&opts_list_02,
 675                           "size1=9223372036854775807," /* 7fffffffffffffff */
 676                           "size2=9223372036854775808," /* 8000000000000000 */
 677                           "size3=9223372036854775809", /* 8000000000000001 */
 678                           false, &error_abort);
 679    g_assert_cmpuint(opts_count(opts), ==, 3);
 680    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
 681                     ==, 0x7fffffffffffffff);
 682    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
 683                     ==, 0x8000000000000000);
 684    g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1),
 685                     ==, 0x8000000000000001);
 686
 687    /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
 688    opts = qemu_opts_parse(&opts_list_02,
 689                           "size1=18446744073709549568," /* fffffffffffff800 */
 690                           "size2=18446744073709550591", /* fffffffffffffbff */
 691                           false, &error_abort);
 692    g_assert_cmpuint(opts_count(opts), ==, 2);
 693    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
 694                     ==, 0xfffffffffffff800);
 695    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
 696                     ==, 0xfffffffffffffbff);
 697
 698    /* Actual limit, 2^64-1 */
 699    opts = qemu_opts_parse(&opts_list_02,
 700                           "size1=18446744073709551615", /* ffffffffffffffff */
 701                           false, &error_abort);
 702    g_assert_cmpuint(opts_count(opts), ==, 1);
 703    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
 704                     ==, 0xffffffffffffffff);
 705
 706    /* Beyond limits */
 707    opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err);
 708    error_free_or_abort(&err);
 709    g_assert(!opts);
 710    opts = qemu_opts_parse(&opts_list_02,
 711                           "size1=18446744073709551616", /* 2^64 */
 712                           false, &err);
 713    error_free_or_abort(&err);
 714    g_assert(!opts);
 715
 716    /* Suffixes */
 717    opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M",
 718                           false, &error_abort);
 719    g_assert_cmpuint(opts_count(opts), ==, 3);
 720    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
 721    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
 722    g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * MiB);
 723    opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
 724                           false, &error_abort);
 725    g_assert_cmpuint(opts_count(opts), ==, 2);
 726    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 10);
 727    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 16777215ULL * TiB);
 728
 729    /* Beyond limit with suffix */
 730    opts = qemu_opts_parse(&opts_list_02, "size1=16777216T",
 731                           false, &err);
 732    error_free_or_abort(&err);
 733    g_assert(!opts);
 734
 735    /* Trailing crap */
 736    opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err);
 737    error_free_or_abort(&err);
 738    g_assert(!opts);
 739    opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &err);
 740    error_free_or_abort(&err);
 741    g_assert(!opts);
 742
 743    qemu_opts_reset(&opts_list_02);
 744}
 745
 746static void test_has_help_option(void)
 747{
 748    static const struct {
 749        const char *params;
 750        /* expected value of qemu_opt_has_help_opt() with implied=false */
 751        bool expect;
 752        /* expected value of qemu_opt_has_help_opt() with implied=true */
 753        bool expect_implied;
 754    } test[] = {
 755        { "help", true, false },
 756        { "?", true, false },
 757        { "helpme", false, false },
 758        { "?me", false, false },
 759        { "a,help", true, true },
 760        { "a,?", true, true },
 761        { "a=0,help,b", true, true },
 762        { "a=0,?,b", true, true },
 763        { "help,b=1", true, false },
 764        { "?,b=1", true, false },
 765        { "a,b,,help", true, true },
 766        { "a,b,,?", true, true },
 767    };
 768    int i;
 769    QemuOpts *opts;
 770
 771    for (i = 0; i < ARRAY_SIZE(test); i++) {
 772        g_assert_cmpint(has_help_option(test[i].params),
 773                        ==, test[i].expect);
 774        opts = qemu_opts_parse(&opts_list_03, test[i].params, false,
 775                               &error_abort);
 776        g_assert_cmpint(qemu_opt_has_help_opt(opts),
 777                        ==, test[i].expect);
 778        qemu_opts_del(opts);
 779        opts = qemu_opts_parse(&opts_list_03, test[i].params, true,
 780                               &error_abort);
 781        g_assert_cmpint(qemu_opt_has_help_opt(opts),
 782                        ==, test[i].expect_implied);
 783        qemu_opts_del(opts);
 784    }
 785}
 786
 787static void append_verify_list_01(QemuOptDesc *desc, bool with_overlapping)
 788{
 789    int i = 0;
 790
 791    if (with_overlapping) {
 792        g_assert_cmpstr(desc[i].name, ==, "str1");
 793        g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
 794        g_assert_cmpstr(desc[i].help, ==,
 795                        "Help texts are preserved in qemu_opts_append");
 796        g_assert_cmpstr(desc[i].def_value_str, ==, "default");
 797        i++;
 798
 799        g_assert_cmpstr(desc[i].name, ==, "str2");
 800        g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
 801        g_assert_cmpstr(desc[i].help, ==, NULL);
 802        g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 803        i++;
 804    }
 805
 806    g_assert_cmpstr(desc[i].name, ==, "str3");
 807    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
 808    g_assert_cmpstr(desc[i].help, ==, NULL);
 809    g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 810    i++;
 811
 812    g_assert_cmpstr(desc[i].name, ==, "number1");
 813    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
 814    g_assert_cmpstr(desc[i].help, ==,
 815                    "Having help texts only for some options is okay");
 816    g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 817    i++;
 818
 819    g_assert_cmpstr(desc[i].name, ==, "number2");
 820    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER);
 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, ==, NULL);
 826}
 827
 828static void append_verify_list_02(QemuOptDesc *desc)
 829{
 830    int i = 0;
 831
 832    g_assert_cmpstr(desc[i].name, ==, "str1");
 833    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
 834    g_assert_cmpstr(desc[i].help, ==, NULL);
 835    g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 836    i++;
 837
 838    g_assert_cmpstr(desc[i].name, ==, "str2");
 839    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING);
 840    g_assert_cmpstr(desc[i].help, ==, NULL);
 841    g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 842    i++;
 843
 844    g_assert_cmpstr(desc[i].name, ==, "bool1");
 845    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
 846    g_assert_cmpstr(desc[i].help, ==, NULL);
 847    g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 848    i++;
 849
 850    g_assert_cmpstr(desc[i].name, ==, "bool2");
 851    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL);
 852    g_assert_cmpstr(desc[i].help, ==, NULL);
 853    g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 854    i++;
 855
 856    g_assert_cmpstr(desc[i].name, ==, "size1");
 857    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
 858    g_assert_cmpstr(desc[i].help, ==, NULL);
 859    g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 860    i++;
 861
 862    g_assert_cmpstr(desc[i].name, ==, "size2");
 863    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
 864    g_assert_cmpstr(desc[i].help, ==, NULL);
 865    g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 866    i++;
 867
 868    g_assert_cmpstr(desc[i].name, ==, "size3");
 869    g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE);
 870    g_assert_cmpstr(desc[i].help, ==, NULL);
 871    g_assert_cmpstr(desc[i].def_value_str, ==, NULL);
 872}
 873
 874static void test_opts_append_to_null(void)
 875{
 876    QemuOptsList *merged;
 877
 878    merged = qemu_opts_append(NULL, &opts_list_01);
 879    g_assert(merged != &opts_list_01);
 880
 881    g_assert_cmpstr(merged->name, ==, NULL);
 882    g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
 883    g_assert_false(merged->merge_lists);
 884
 885    append_verify_list_01(merged->desc, true);
 886
 887    qemu_opts_free(merged);
 888}
 889
 890static void test_opts_append(void)
 891{
 892    QemuOptsList *first, *merged;
 893
 894    first = qemu_opts_append(NULL, &opts_list_02);
 895    merged = qemu_opts_append(first, &opts_list_01);
 896    g_assert(first != &opts_list_02);
 897    g_assert(merged != &opts_list_01);
 898
 899    g_assert_cmpstr(merged->name, ==, NULL);
 900    g_assert_cmpstr(merged->implied_opt_name, ==, NULL);
 901    g_assert_false(merged->merge_lists);
 902
 903    append_verify_list_02(&merged->desc[0]);
 904    append_verify_list_01(&merged->desc[7], false);
 905
 906    qemu_opts_free(merged);
 907}
 908
 909static void test_opts_to_qdict_basic(void)
 910{
 911    QemuOpts *opts;
 912    QDict *dict;
 913
 914    opts = qemu_opts_parse(&opts_list_01, "str1=foo,str2=,str3=bar,number1=42",
 915                           false, &error_abort);
 916    g_assert(opts != NULL);
 917
 918    dict = qemu_opts_to_qdict(opts, NULL);
 919    g_assert(dict != NULL);
 920
 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, "str3"), ==, "bar");
 924    g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
 925    g_assert_false(qdict_haskey(dict, "number2"));
 926
 927    qobject_unref(dict);
 928    qemu_opts_del(opts);
 929}
 930
 931static void test_opts_to_qdict_filtered(void)
 932{
 933    QemuOptsList *first, *merged;
 934    QemuOpts *opts;
 935    QDict *dict;
 936
 937    first = qemu_opts_append(NULL, &opts_list_02);
 938    merged = qemu_opts_append(first, &opts_list_01);
 939
 940    opts = qemu_opts_parse(merged,
 941                           "str1=foo,str2=,str3=bar,bool1=off,number1=42",
 942                           false, &error_abort);
 943    g_assert(opts != NULL);
 944
 945    /* Convert to QDict without deleting from opts */
 946    dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, false);
 947    g_assert(dict != NULL);
 948    g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
 949    g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
 950    g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
 951    g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
 952    g_assert_false(qdict_haskey(dict, "number2"));
 953    g_assert_false(qdict_haskey(dict, "bool1"));
 954    qobject_unref(dict);
 955
 956    dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, false);
 957    g_assert(dict != NULL);
 958    g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
 959    g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
 960    g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
 961    g_assert_false(qdict_haskey(dict, "str3"));
 962    g_assert_false(qdict_haskey(dict, "number1"));
 963    g_assert_false(qdict_haskey(dict, "number2"));
 964    qobject_unref(dict);
 965
 966    /* Now delete converted options from opts */
 967    dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, true);
 968    g_assert(dict != NULL);
 969    g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo");
 970    g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, "");
 971    g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar");
 972    g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42");
 973    g_assert_false(qdict_haskey(dict, "number2"));
 974    g_assert_false(qdict_haskey(dict, "bool1"));
 975    qobject_unref(dict);
 976
 977    dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, true);
 978    g_assert(dict != NULL);
 979    g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off");
 980    g_assert_false(qdict_haskey(dict, "str1"));
 981    g_assert_false(qdict_haskey(dict, "str2"));
 982    g_assert_false(qdict_haskey(dict, "str3"));
 983    g_assert_false(qdict_haskey(dict, "number1"));
 984    g_assert_false(qdict_haskey(dict, "number2"));
 985    qobject_unref(dict);
 986
 987    g_assert_true(QTAILQ_EMPTY(&opts->head));
 988
 989    qemu_opts_del(opts);
 990    qemu_opts_free(merged);
 991}
 992
 993static void test_opts_to_qdict_duplicates(void)
 994{
 995    QemuOpts *opts;
 996    QemuOpt *opt;
 997    QDict *dict;
 998
 999    opts = qemu_opts_parse(&opts_list_03, "foo=a,foo=b", false, &error_abort);
1000    g_assert(opts != NULL);
1001
1002    /* Verify that opts has two options with the same name */
1003    opt = QTAILQ_FIRST(&opts->head);
1004    g_assert_cmpstr(opt->name, ==, "foo");
1005    g_assert_cmpstr(opt->str , ==, "a");
1006
1007    opt = QTAILQ_NEXT(opt, next);
1008    g_assert_cmpstr(opt->name, ==, "foo");
1009    g_assert_cmpstr(opt->str , ==, "b");
1010
1011    opt = QTAILQ_NEXT(opt, next);
1012    g_assert(opt == NULL);
1013
1014    /* In the conversion to QDict, the last one wins */
1015    dict = qemu_opts_to_qdict(opts, NULL);
1016    g_assert(dict != NULL);
1017    g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
1018    qobject_unref(dict);
1019
1020    /* The last one still wins if entries are deleted, and both are deleted */
1021    dict = qemu_opts_to_qdict_filtered(opts, NULL, NULL, true);
1022    g_assert(dict != NULL);
1023    g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b");
1024    qobject_unref(dict);
1025
1026    g_assert_true(QTAILQ_EMPTY(&opts->head));
1027
1028    qemu_opts_del(opts);
1029}
1030
1031int main(int argc, char *argv[])
1032{
1033    register_opts();
1034    g_test_init(&argc, &argv, NULL);
1035    g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts);
1036    g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts);
1037    g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create);
1038    g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get);
1039    g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool);
1040    g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number);
1041    g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size);
1042    g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset);
1043    g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset);
1044    g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set);
1045    g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse);
1046    g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool);
1047    g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number);
1048    g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size);
1049    g_test_add_func("/qemu-opts/has_help_option", test_has_help_option);
1050    g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null);
1051    g_test_add_func("/qemu-opts/append", test_opts_append);
1052    g_test_add_func("/qemu-opts/to_qdict/basic", test_opts_to_qdict_basic);
1053    g_test_add_func("/qemu-opts/to_qdict/filtered", test_opts_to_qdict_filtered);
1054    g_test_add_func("/qemu-opts/to_qdict/duplicates", test_opts_to_qdict_duplicates);
1055    g_test_run();
1056    return 0;
1057}
1058