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/cutils.h"
  12#include "qapi/error.h"
  13#include "qapi/qmp/qstring.h"
  14#include "qemu/config-file.h"
  15
  16
  17static QemuOptsList opts_list_01 = {
  18    .name = "opts_list_01",
  19    .head = QTAILQ_HEAD_INITIALIZER(opts_list_01.head),
  20    .desc = {
  21        {
  22            .name = "str1",
  23            .type = QEMU_OPT_STRING,
  24        },{
  25            .name = "str2",
  26            .type = QEMU_OPT_STRING,
  27        },{
  28            .name = "str3",
  29            .type = QEMU_OPT_STRING,
  30        },{
  31            .name = "number1",
  32            .type = QEMU_OPT_NUMBER,
  33        },{
  34            .name = "number2",
  35            .type = QEMU_OPT_NUMBER,
  36        },
  37        { /* end of list */ }
  38    },
  39};
  40
  41static QemuOptsList opts_list_02 = {
  42    .name = "opts_list_02",
  43    .head = QTAILQ_HEAD_INITIALIZER(opts_list_02.head),
  44    .desc = {
  45        {
  46            .name = "str1",
  47            .type = QEMU_OPT_STRING,
  48        },{
  49            .name = "str2",
  50            .type = QEMU_OPT_STRING,
  51        },{
  52            .name = "bool1",
  53            .type = QEMU_OPT_BOOL,
  54        },{
  55            .name = "bool2",
  56            .type = QEMU_OPT_BOOL,
  57        },{
  58            .name = "size1",
  59            .type = QEMU_OPT_SIZE,
  60        },{
  61            .name = "size2",
  62            .type = QEMU_OPT_SIZE,
  63        },{
  64            .name = "size3",
  65            .type = QEMU_OPT_SIZE,
  66        },
  67        { /* end of list */ }
  68    },
  69};
  70
  71static QemuOptsList opts_list_03 = {
  72    .name = "opts_list_03",
  73    .implied_opt_name = "implied",
  74    .head = QTAILQ_HEAD_INITIALIZER(opts_list_03.head),
  75    .desc = {
  76        /* no elements => accept any params */
  77        { /* end of list */ }
  78    },
  79};
  80
  81static void register_opts(void)
  82{
  83    qemu_add_opts(&opts_list_01);
  84    qemu_add_opts(&opts_list_02);
  85    qemu_add_opts(&opts_list_03);
  86}
  87
  88static void test_find_unknown_opts(void)
  89{
  90    QemuOptsList *list;
  91    Error *err = NULL;
  92
  93    /* should not return anything, we don't have an "unknown" option */
  94    list = qemu_find_opts_err("unknown", &err);
  95    g_assert(list == NULL);
  96    error_free_or_abort(&err);
  97}
  98
  99static void test_qemu_find_opts(void)
 100{
 101    QemuOptsList *list;
 102
 103    /* we have an "opts_list_01" option, should return it */
 104    list = qemu_find_opts("opts_list_01");
 105    g_assert(list != NULL);
 106    g_assert_cmpstr(list->name, ==, "opts_list_01");
 107}
 108
 109static void test_qemu_opts_create(void)
 110{
 111    QemuOptsList *list;
 112    QemuOpts *opts;
 113
 114    list = qemu_find_opts("opts_list_01");
 115    g_assert(list != NULL);
 116    g_assert(QTAILQ_EMPTY(&list->head));
 117    g_assert_cmpstr(list->name, ==, "opts_list_01");
 118
 119    /* should not find anything at this point */
 120    opts = qemu_opts_find(list, NULL);
 121    g_assert(opts == NULL);
 122
 123    /* create the opts */
 124    opts = qemu_opts_create(list, NULL, 0, &error_abort);
 125    g_assert(opts != NULL);
 126    g_assert(!QTAILQ_EMPTY(&list->head));
 127
 128    /* now we've create the opts, must find it */
 129    opts = qemu_opts_find(list, NULL);
 130    g_assert(opts != NULL);
 131
 132    qemu_opts_del(opts);
 133
 134    /* should not find anything at this point */
 135    opts = qemu_opts_find(list, NULL);
 136    g_assert(opts == NULL);
 137}
 138
 139static void test_qemu_opt_get(void)
 140{
 141    QemuOptsList *list;
 142    QemuOpts *opts;
 143    const char *opt = NULL;
 144
 145    list = qemu_find_opts("opts_list_01");
 146    g_assert(list != NULL);
 147    g_assert(QTAILQ_EMPTY(&list->head));
 148    g_assert_cmpstr(list->name, ==, "opts_list_01");
 149
 150    /* should not find anything at this point */
 151    opts = qemu_opts_find(list, NULL);
 152    g_assert(opts == NULL);
 153
 154    /* create the opts */
 155    opts = qemu_opts_create(list, NULL, 0, &error_abort);
 156    g_assert(opts != NULL);
 157    g_assert(!QTAILQ_EMPTY(&list->head));
 158
 159    /* haven't set anything to str2 yet */
 160    opt = qemu_opt_get(opts, "str2");
 161    g_assert(opt == NULL);
 162
 163    qemu_opt_set(opts, "str2", "value", &error_abort);
 164
 165    /* now we have set str2, should know about it */
 166    opt = qemu_opt_get(opts, "str2");
 167    g_assert_cmpstr(opt, ==, "value");
 168
 169    qemu_opt_set(opts, "str2", "value2", &error_abort);
 170
 171    /* having reset the value, the returned should be the reset one */
 172    opt = qemu_opt_get(opts, "str2");
 173    g_assert_cmpstr(opt, ==, "value2");
 174
 175    qemu_opts_del(opts);
 176
 177    /* should not find anything at this point */
 178    opts = qemu_opts_find(list, NULL);
 179    g_assert(opts == NULL);
 180}
 181
 182static void test_qemu_opt_get_bool(void)
 183{
 184    Error *err = NULL;
 185    QemuOptsList *list;
 186    QemuOpts *opts;
 187    bool opt;
 188
 189    list = qemu_find_opts("opts_list_02");
 190    g_assert(list != NULL);
 191    g_assert(QTAILQ_EMPTY(&list->head));
 192    g_assert_cmpstr(list->name, ==, "opts_list_02");
 193
 194    /* should not find anything at this point */
 195    opts = qemu_opts_find(list, NULL);
 196    g_assert(opts == NULL);
 197
 198    /* create the opts */
 199    opts = qemu_opts_create(list, NULL, 0, &error_abort);
 200    g_assert(opts != NULL);
 201    g_assert(!QTAILQ_EMPTY(&list->head));
 202
 203    /* haven't set anything to bool1 yet, so defval should be returned */
 204    opt = qemu_opt_get_bool(opts, "bool1", false);
 205    g_assert(opt == false);
 206
 207    qemu_opt_set_bool(opts, "bool1", true, &err);
 208    g_assert(!err);
 209
 210    /* now we have set bool1, should know about it */
 211    opt = qemu_opt_get_bool(opts, "bool1", false);
 212    g_assert(opt == true);
 213
 214    /* having reset the value, opt should be the reset one not defval */
 215    qemu_opt_set_bool(opts, "bool1", false, &err);
 216    g_assert(!err);
 217
 218    opt = qemu_opt_get_bool(opts, "bool1", true);
 219    g_assert(opt == false);
 220
 221    qemu_opts_del(opts);
 222
 223    /* should not find anything at this point */
 224    opts = qemu_opts_find(list, NULL);
 225    g_assert(opts == NULL);
 226}
 227
 228static void test_qemu_opt_get_number(void)
 229{
 230    Error *err = NULL;
 231    QemuOptsList *list;
 232    QemuOpts *opts;
 233    uint64_t opt;
 234
 235    list = qemu_find_opts("opts_list_01");
 236    g_assert(list != NULL);
 237    g_assert(QTAILQ_EMPTY(&list->head));
 238    g_assert_cmpstr(list->name, ==, "opts_list_01");
 239
 240    /* should not find anything at this point */
 241    opts = qemu_opts_find(list, NULL);
 242    g_assert(opts == NULL);
 243
 244    /* create the opts */
 245    opts = qemu_opts_create(list, NULL, 0, &error_abort);
 246    g_assert(opts != NULL);
 247    g_assert(!QTAILQ_EMPTY(&list->head));
 248
 249    /* haven't set anything to number1 yet, so defval should be returned */
 250    opt = qemu_opt_get_number(opts, "number1", 5);
 251    g_assert(opt == 5);
 252
 253    qemu_opt_set_number(opts, "number1", 10, &err);
 254    g_assert(!err);
 255
 256    /* now we have set number1, should know about it */
 257    opt = qemu_opt_get_number(opts, "number1", 5);
 258    g_assert(opt == 10);
 259
 260    /* having reset it, the returned should be the reset one not defval */
 261    qemu_opt_set_number(opts, "number1", 15, &err);
 262    g_assert(!err);
 263
 264    opt = qemu_opt_get_number(opts, "number1", 5);
 265    g_assert(opt == 15);
 266
 267    qemu_opts_del(opts);
 268
 269    /* should not find anything at this point */
 270    opts = qemu_opts_find(list, NULL);
 271    g_assert(opts == NULL);
 272}
 273
 274static void test_qemu_opt_get_size(void)
 275{
 276    QemuOptsList *list;
 277    QemuOpts *opts;
 278    uint64_t opt;
 279    QDict *dict;
 280
 281    list = qemu_find_opts("opts_list_02");
 282    g_assert(list != NULL);
 283    g_assert(QTAILQ_EMPTY(&list->head));
 284    g_assert_cmpstr(list->name, ==, "opts_list_02");
 285
 286    /* should not find anything at this point */
 287    opts = qemu_opts_find(list, NULL);
 288    g_assert(opts == NULL);
 289
 290    /* create the opts */
 291    opts = qemu_opts_create(list, NULL, 0, &error_abort);
 292    g_assert(opts != NULL);
 293    g_assert(!QTAILQ_EMPTY(&list->head));
 294
 295    /* haven't set anything to size1 yet, so defval should be returned */
 296    opt = qemu_opt_get_size(opts, "size1", 5);
 297    g_assert(opt == 5);
 298
 299    dict = qdict_new();
 300    g_assert(dict != NULL);
 301
 302    qdict_put_str(dict, "size1", "10");
 303
 304    qemu_opts_absorb_qdict(opts, dict, &error_abort);
 305    g_assert(error_abort == NULL);
 306
 307    /* now we have set size1, should know about it */
 308    opt = qemu_opt_get_size(opts, "size1", 5);
 309    g_assert(opt == 10);
 310
 311    /* reset value */
 312    qdict_put_str(dict, "size1", "15");
 313
 314    qemu_opts_absorb_qdict(opts, dict, &error_abort);
 315    g_assert(error_abort == NULL);
 316
 317    /* test the reset value */
 318    opt = qemu_opt_get_size(opts, "size1", 5);
 319    g_assert(opt == 15);
 320
 321    qdict_del(dict, "size1");
 322    g_free(dict);
 323
 324    qemu_opts_del(opts);
 325
 326    /* should not find anything at this point */
 327    opts = qemu_opts_find(list, NULL);
 328    g_assert(opts == NULL);
 329}
 330
 331static void test_qemu_opt_unset(void)
 332{
 333    QemuOpts *opts;
 334    const char *value;
 335    int ret;
 336
 337    /* dynamically initialized (parsed) opts */
 338    opts = qemu_opts_parse(&opts_list_03, "key=value", false, NULL);
 339    g_assert(opts != NULL);
 340
 341    /* check default/parsed value */
 342    value = qemu_opt_get(opts, "key");
 343    g_assert_cmpstr(value, ==, "value");
 344
 345    /* reset it to value2 */
 346    qemu_opt_set(opts, "key", "value2", &error_abort);
 347
 348    value = qemu_opt_get(opts, "key");
 349    g_assert_cmpstr(value, ==, "value2");
 350
 351    /* unset, valid only for "accept any" */
 352    ret = qemu_opt_unset(opts, "key");
 353    g_assert(ret == 0);
 354
 355    /* after reset the value should be the parsed/default one */
 356    value = qemu_opt_get(opts, "key");
 357    g_assert_cmpstr(value, ==, "value");
 358
 359    qemu_opts_del(opts);
 360}
 361
 362static void test_qemu_opts_reset(void)
 363{
 364    Error *err = NULL;
 365    QemuOptsList *list;
 366    QemuOpts *opts;
 367    uint64_t opt;
 368
 369    list = qemu_find_opts("opts_list_01");
 370    g_assert(list != NULL);
 371    g_assert(QTAILQ_EMPTY(&list->head));
 372    g_assert_cmpstr(list->name, ==, "opts_list_01");
 373
 374    /* should not find anything at this point */
 375    opts = qemu_opts_find(list, NULL);
 376    g_assert(opts == NULL);
 377
 378    /* create the opts */
 379    opts = qemu_opts_create(list, NULL, 0, &error_abort);
 380    g_assert(opts != NULL);
 381    g_assert(!QTAILQ_EMPTY(&list->head));
 382
 383    /* haven't set anything to number1 yet, so defval should be returned */
 384    opt = qemu_opt_get_number(opts, "number1", 5);
 385    g_assert(opt == 5);
 386
 387    qemu_opt_set_number(opts, "number1", 10, &err);
 388    g_assert(!err);
 389
 390    /* now we have set number1, should know about it */
 391    opt = qemu_opt_get_number(opts, "number1", 5);
 392    g_assert(opt == 10);
 393
 394    qemu_opts_reset(list);
 395
 396    /* should not find anything at this point */
 397    opts = qemu_opts_find(list, NULL);
 398    g_assert(opts == NULL);
 399}
 400
 401static void test_qemu_opts_set(void)
 402{
 403    Error *err = NULL;
 404    QemuOptsList *list;
 405    QemuOpts *opts;
 406    const char *opt;
 407
 408    list = qemu_find_opts("opts_list_01");
 409    g_assert(list != NULL);
 410    g_assert(QTAILQ_EMPTY(&list->head));
 411    g_assert_cmpstr(list->name, ==, "opts_list_01");
 412
 413    /* should not find anything at this point */
 414    opts = qemu_opts_find(list, NULL);
 415    g_assert(opts == NULL);
 416
 417    /* implicitly create opts and set str3 value */
 418    qemu_opts_set(list, NULL, "str3", "value", &err);
 419    g_assert(!err);
 420    g_assert(!QTAILQ_EMPTY(&list->head));
 421
 422    /* get the just created opts */
 423    opts = qemu_opts_find(list, NULL);
 424    g_assert(opts != NULL);
 425
 426    /* check the str3 value */
 427    opt = qemu_opt_get(opts, "str3");
 428    g_assert_cmpstr(opt, ==, "value");
 429
 430    qemu_opts_del(opts);
 431
 432    /* should not find anything at this point */
 433    opts = qemu_opts_find(list, NULL);
 434    g_assert(opts == NULL);
 435}
 436
 437static int opts_count_iter(void *opaque, const char *name, const char *value,
 438                           Error **errp)
 439{
 440    (*(size_t *)opaque)++;
 441    return 0;
 442}
 443
 444static size_t opts_count(QemuOpts *opts)
 445{
 446    size_t n = 0;
 447
 448    qemu_opt_foreach(opts, opts_count_iter, &n, NULL);
 449    return n;
 450}
 451
 452static void test_opts_parse(void)
 453{
 454    Error *err = NULL;
 455    QemuOpts *opts;
 456    char long_key[129];
 457    char *params;
 458
 459    /* Nothing */
 460    opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort);
 461    g_assert_cmpuint(opts_count(opts), ==, 0);
 462
 463    /* Empty key */
 464    opts = qemu_opts_parse(&opts_list_03, "=val", false, &error_abort);
 465    g_assert_cmpuint(opts_count(opts), ==, 1);
 466    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
 467
 468    /* Long key */
 469    memset(long_key, 'a', 127);
 470    long_key[127] = 'z';
 471    long_key[128] = 0;
 472    params = g_strdup_printf("%s=v", long_key);
 473    opts = qemu_opts_parse(&opts_list_03, params + 1, NULL, &error_abort);
 474    g_assert_cmpuint(opts_count(opts), ==, 1);
 475    g_assert_cmpstr(qemu_opt_get(opts, long_key + 1), ==, "v");
 476
 477    /* Overlong key gets truncated */
 478    opts = qemu_opts_parse(&opts_list_03, params, NULL, &error_abort);
 479    g_assert(opts_count(opts) == 1);
 480    long_key[127] = 0;
 481    g_assert_cmpstr(qemu_opt_get(opts, long_key), ==, "v");
 482    g_free(params);
 483
 484    /* Multiple keys, last one wins */
 485    opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3",
 486                           false, &error_abort);
 487    g_assert_cmpuint(opts_count(opts), ==, 3);
 488    g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "3");
 489    g_assert_cmpstr(qemu_opt_get(opts, "b"), ==, "2,x");
 490
 491    /* Except when it doesn't */
 492    opts = qemu_opts_parse(&opts_list_03, "id=foo,id=bar",
 493                           false, &error_abort);
 494    g_assert_cmpuint(opts_count(opts), ==, 0);
 495    g_assert_cmpstr(qemu_opts_id(opts), ==, "foo");
 496
 497    /* TODO Cover low-level access to repeated keys */
 498
 499    /* Trailing comma is ignored */
 500    opts = qemu_opts_parse(&opts_list_03, "x=y,", false, &error_abort);
 501    g_assert_cmpuint(opts_count(opts), ==, 1);
 502    g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, "y");
 503
 504    /* Except when it isn't */
 505    opts = qemu_opts_parse(&opts_list_03, ",", false, &error_abort);
 506    g_assert_cmpuint(opts_count(opts), ==, 1);
 507    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "on");
 508
 509    /* Duplicate ID */
 510    opts = qemu_opts_parse(&opts_list_03, "x=y,id=foo", false, &err);
 511    error_free_or_abort(&err);
 512    g_assert(!opts);
 513    /* TODO Cover .merge_lists = true */
 514
 515    /* Buggy ID recognition */
 516    opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort);
 517    g_assert_cmpuint(opts_count(opts), ==, 1);
 518    g_assert_cmpstr(qemu_opts_id(opts), ==, "bar"); /* BUG */
 519    g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar");
 520
 521    /* Anti-social ID */
 522    opts = qemu_opts_parse(&opts_list_01, "id=666", false, &err);
 523    error_free_or_abort(&err);
 524    g_assert(!opts);
 525
 526    /* Implied value */
 527    opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=",
 528                           false, &error_abort);
 529    g_assert_cmpuint(opts_count(opts), ==, 3);
 530    g_assert_cmpstr(qemu_opt_get(opts, "an"), ==, "on");
 531    g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
 532    g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
 533
 534    /* Implied value, negated empty key */
 535    opts = qemu_opts_parse(&opts_list_03, "no", false, &error_abort);
 536    g_assert_cmpuint(opts_count(opts), ==, 1);
 537    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "off");
 538
 539    /* Implied key */
 540    opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", true,
 541                           &error_abort);
 542    g_assert_cmpuint(opts_count(opts), ==, 3);
 543    g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "an");
 544    g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off");
 545    g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, "");
 546
 547    /* Implied key with empty value */
 548    opts = qemu_opts_parse(&opts_list_03, ",", true, &error_abort);
 549    g_assert_cmpuint(opts_count(opts), ==, 1);
 550    g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "");
 551
 552    /* Implied key with comma value */
 553    opts = qemu_opts_parse(&opts_list_03, ",,,a=1", true, &error_abort);
 554    g_assert_cmpuint(opts_count(opts), ==, 2);
 555    g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ",");
 556    g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "1");
 557
 558    /* Empty key is not an implied key */
 559    opts = qemu_opts_parse(&opts_list_03, "=val", true, &error_abort);
 560    g_assert_cmpuint(opts_count(opts), ==, 1);
 561    g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val");
 562
 563    /* Unknown key */
 564    opts = qemu_opts_parse(&opts_list_01, "nonexistent=", false, &err);
 565    error_free_or_abort(&err);
 566    g_assert(!opts);
 567
 568    qemu_opts_reset(&opts_list_01);
 569    qemu_opts_reset(&opts_list_03);
 570}
 571
 572static void test_opts_parse_bool(void)
 573{
 574    Error *err = NULL;
 575    QemuOpts *opts;
 576
 577    opts = qemu_opts_parse(&opts_list_02, "bool1=on,bool2=off",
 578                           false, &error_abort);
 579    g_assert_cmpuint(opts_count(opts), ==, 2);
 580    g_assert(qemu_opt_get_bool(opts, "bool1", false));
 581    g_assert(!qemu_opt_get_bool(opts, "bool2", true));
 582
 583    opts = qemu_opts_parse(&opts_list_02, "bool1=offer", false, &err);
 584    error_free_or_abort(&err);
 585    g_assert(!opts);
 586
 587    qemu_opts_reset(&opts_list_02);
 588}
 589
 590static void test_opts_parse_number(void)
 591{
 592    Error *err = NULL;
 593    QemuOpts *opts;
 594
 595    /* Lower limit zero */
 596    opts = qemu_opts_parse(&opts_list_01, "number1=0", false, &error_abort);
 597    g_assert_cmpuint(opts_count(opts), ==, 1);
 598    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 0);
 599
 600    /* Upper limit 2^64-1 */
 601    opts = qemu_opts_parse(&opts_list_01,
 602                           "number1=18446744073709551615,number2=-1",
 603                           false, &error_abort);
 604    g_assert_cmpuint(opts_count(opts), ==, 2);
 605    g_assert_cmphex(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX);
 606    g_assert_cmphex(qemu_opt_get_number(opts, "number2", 0), ==, UINT64_MAX);
 607
 608    /* Above upper limit */
 609    opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616",
 610                           false, &err);
 611    error_free_or_abort(&err);
 612    g_assert(!opts);
 613
 614    /* Below lower limit */
 615    opts = qemu_opts_parse(&opts_list_01, "number1=-18446744073709551616",
 616                           false, &err);
 617    error_free_or_abort(&err);
 618    g_assert(!opts);
 619
 620    /* Hex and octal */
 621    opts = qemu_opts_parse(&opts_list_01, "number1=0x2a,number2=052",
 622                           false, &error_abort);
 623    g_assert_cmpuint(opts_count(opts), ==, 2);
 624    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
 625    g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), ==, 42);
 626
 627    /* Invalid */
 628    opts = qemu_opts_parse(&opts_list_01, "number1=", false, &err);
 629    error_free_or_abort(&err);
 630    g_assert(!opts);
 631    opts = qemu_opts_parse(&opts_list_01, "number1=eins", false, &err);
 632    error_free_or_abort(&err);
 633    g_assert(!opts);
 634
 635    /* Leading whitespace */
 636    opts = qemu_opts_parse(&opts_list_01, "number1= \t42",
 637                           false, &error_abort);
 638    g_assert_cmpuint(opts_count(opts), ==, 1);
 639    g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42);
 640
 641    /* Trailing crap */
 642    opts = qemu_opts_parse(&opts_list_01, "number1=3.14", false, &err);
 643    error_free_or_abort(&err);
 644    g_assert(!opts);
 645    opts = qemu_opts_parse(&opts_list_01, "number1=08", false, &err);
 646    error_free_or_abort(&err);
 647    g_assert(!opts);
 648    opts = qemu_opts_parse(&opts_list_01, "number1=0 ", false, &err);
 649    error_free_or_abort(&err);
 650    g_assert(!opts);
 651
 652    qemu_opts_reset(&opts_list_01);
 653}
 654
 655static void test_opts_parse_size(void)
 656{
 657    Error *err = NULL;
 658    QemuOpts *opts;
 659
 660    /* Lower limit zero */
 661    opts = qemu_opts_parse(&opts_list_02, "size1=0", false, &error_abort);
 662    g_assert_cmpuint(opts_count(opts), ==, 1);
 663    g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0);
 664
 665    /* Note: precision is 53 bits since we're parsing with strtod() */
 666
 667    /* Around limit of precision: 2^53-1, 2^53, 2^54 */
 668    opts = qemu_opts_parse(&opts_list_02,
 669                           "size1=9007199254740991,"
 670                           "size2=9007199254740992,"
 671                           "size3=9007199254740993",
 672                           false, &error_abort);
 673    g_assert_cmpuint(opts_count(opts), ==, 3);
 674    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
 675                     ==, 0x1fffffffffffff);
 676    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
 677                     ==, 0x20000000000000);
 678    g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1),
 679                     ==, 0x20000000000000);
 680
 681    /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */
 682    opts = qemu_opts_parse(&opts_list_02,
 683                           "size1=9223372036854774784," /* 7ffffffffffffc00 */
 684                           "size2=9223372036854775295", /* 7ffffffffffffdff */
 685                           false, &error_abort);
 686    g_assert_cmpuint(opts_count(opts), ==, 2);
 687    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
 688                     ==, 0x7ffffffffffffc00);
 689    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
 690                     ==, 0x7ffffffffffffc00);
 691
 692    /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */
 693    opts = qemu_opts_parse(&opts_list_02,
 694                           "size1=18446744073709549568," /* fffffffffffff800 */
 695                           "size2=18446744073709550591", /* fffffffffffffbff */
 696                           false, &error_abort);
 697    g_assert_cmpuint(opts_count(opts), ==, 2);
 698    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1),
 699                     ==, 0xfffffffffffff800);
 700    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1),
 701                     ==, 0xfffffffffffff800);
 702
 703    /* Beyond limits */
 704    opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err);
 705    error_free_or_abort(&err);
 706    g_assert(!opts);
 707    opts = qemu_opts_parse(&opts_list_02,
 708                           "size1=18446744073709550592", /* fffffffffffffc00 */
 709                           false, &err);
 710    error_free_or_abort(&err);
 711    g_assert(!opts);
 712
 713    /* Suffixes */
 714    opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M",
 715                           false, &error_abort);
 716    g_assert_cmpuint(opts_count(opts), ==, 3);
 717    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8);
 718    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536);
 719    g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * M_BYTE);
 720    opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T",
 721                           false, &error_abort);
 722    g_assert_cmpuint(opts_count(opts), ==, 2);
 723    g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, G_BYTE / 10);
 724    g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0),
 725                     ==, 16777215 * T_BYTE);
 726
 727    /* Beyond limit with suffix */
 728    opts = qemu_opts_parse(&opts_list_02, "size1=16777216T",
 729                           false, &err);
 730    error_free_or_abort(&err);
 731    g_assert(!opts);
 732
 733    /* Trailing crap */
 734    opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err);
 735    error_free_or_abort(&err);
 736    g_assert(!opts);
 737    opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &err);
 738    error_free_or_abort(&err);
 739    g_assert(!opts);
 740
 741    qemu_opts_reset(&opts_list_02);
 742}
 743
 744int main(int argc, char *argv[])
 745{
 746    register_opts();
 747    g_test_init(&argc, &argv, NULL);
 748    g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts);
 749    g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts);
 750    g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create);
 751    g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get);
 752    g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool);
 753    g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number);
 754    g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size);
 755    g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset);
 756    g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset);
 757    g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set);
 758    g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse);
 759    g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool);
 760    g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number);
 761    g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size);
 762    g_test_run();
 763    return 0;
 764}
 765