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 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
 420static 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
 428static 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
 530static 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
 548static 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
 613static 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
 712static 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
 753static 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
 794static 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
 840static 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
 856static 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
 875static 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
 897static 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
 959static 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
 997int 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}
1023