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