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