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: precision is 53 bits since we're parsing with strtod() */ 658 659 /* Around limit of precision: 2^53-1, 2^53, 2^54 */ 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 ==, 0x20000000000000); 672 673 /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */ 674 opts = qemu_opts_parse(&opts_list_02, 675 "size1=9223372036854774784," /* 7ffffffffffffc00 */ 676 "size2=9223372036854775295", /* 7ffffffffffffdff */ 677 false, &error_abort); 678 g_assert_cmpuint(opts_count(opts), ==, 2); 679 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), 680 ==, 0x7ffffffffffffc00); 681 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), 682 ==, 0x7ffffffffffffc00); 683 684 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ 685 opts = qemu_opts_parse(&opts_list_02, 686 "size1=18446744073709549568," /* fffffffffffff800 */ 687 "size2=18446744073709550591", /* fffffffffffffbff */ 688 false, &error_abort); 689 g_assert_cmpuint(opts_count(opts), ==, 2); 690 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), 691 ==, 0xfffffffffffff800); 692 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), 693 ==, 0xfffffffffffff800); 694 695 /* Beyond limits */ 696 opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err); 697 error_free_or_abort(&err); 698 g_assert(!opts); 699 opts = qemu_opts_parse(&opts_list_02, 700 "size1=18446744073709550592", /* fffffffffffffc00 */ 701 false, &err); 702 error_free_or_abort(&err); 703 g_assert(!opts); 704 705 /* Suffixes */ 706 opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M", 707 false, &error_abort); 708 g_assert_cmpuint(opts_count(opts), ==, 3); 709 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8); 710 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536); 711 g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * MiB); 712 opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T", 713 false, &error_abort); 714 g_assert_cmpuint(opts_count(opts), ==, 2); 715 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 10); 716 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 16777215ULL * TiB); 717 718 /* Beyond limit with suffix */ 719 opts = qemu_opts_parse(&opts_list_02, "size1=16777216T", 720 false, &err); 721 error_free_or_abort(&err); 722 g_assert(!opts); 723 724 /* Trailing crap */ 725 opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err); 726 error_free_or_abort(&err); 727 g_assert(!opts); 728 opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &err); 729 error_free_or_abort(&err); 730 g_assert(!opts); 731 732 qemu_opts_reset(&opts_list_02); 733 } 734 735 static void test_has_help_option(void) 736 { 737 static const struct { 738 const char *params; 739 /* expected value of qemu_opt_has_help_opt() with implied=false */ 740 bool expect; 741 /* expected value of qemu_opt_has_help_opt() with implied=true */ 742 bool expect_implied; 743 } test[] = { 744 { "help", true, false }, 745 { "?", true, false }, 746 { "helpme", false, false }, 747 { "?me", false, false }, 748 { "a,help", true, true }, 749 { "a,?", true, true }, 750 { "a=0,help,b", true, true }, 751 { "a=0,?,b", true, true }, 752 { "help,b=1", true, false }, 753 { "?,b=1", true, false }, 754 { "a,b,,help", true, true }, 755 { "a,b,,?", true, true }, 756 }; 757 int i; 758 QemuOpts *opts; 759 760 for (i = 0; i < ARRAY_SIZE(test); i++) { 761 g_assert_cmpint(has_help_option(test[i].params), 762 ==, test[i].expect); 763 opts = qemu_opts_parse(&opts_list_03, test[i].params, false, 764 &error_abort); 765 g_assert_cmpint(qemu_opt_has_help_opt(opts), 766 ==, test[i].expect); 767 qemu_opts_del(opts); 768 opts = qemu_opts_parse(&opts_list_03, test[i].params, true, 769 &error_abort); 770 g_assert_cmpint(qemu_opt_has_help_opt(opts), 771 ==, test[i].expect_implied); 772 qemu_opts_del(opts); 773 } 774 } 775 776 static void append_verify_list_01(QemuOptDesc *desc, bool with_overlapping) 777 { 778 int i = 0; 779 780 if (with_overlapping) { 781 g_assert_cmpstr(desc[i].name, ==, "str1"); 782 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 783 g_assert_cmpstr(desc[i].help, ==, 784 "Help texts are preserved in qemu_opts_append"); 785 g_assert_cmpstr(desc[i].def_value_str, ==, "default"); 786 i++; 787 788 g_assert_cmpstr(desc[i].name, ==, "str2"); 789 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 790 g_assert_cmpstr(desc[i].help, ==, NULL); 791 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 792 i++; 793 } 794 795 g_assert_cmpstr(desc[i].name, ==, "str3"); 796 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 797 g_assert_cmpstr(desc[i].help, ==, NULL); 798 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 799 i++; 800 801 g_assert_cmpstr(desc[i].name, ==, "number1"); 802 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER); 803 g_assert_cmpstr(desc[i].help, ==, 804 "Having help texts only for some options is okay"); 805 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 806 i++; 807 808 g_assert_cmpstr(desc[i].name, ==, "number2"); 809 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER); 810 g_assert_cmpstr(desc[i].help, ==, NULL); 811 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 812 i++; 813 814 g_assert_cmpstr(desc[i].name, ==, NULL); 815 } 816 817 static void append_verify_list_02(QemuOptDesc *desc) 818 { 819 int i = 0; 820 821 g_assert_cmpstr(desc[i].name, ==, "str1"); 822 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 823 g_assert_cmpstr(desc[i].help, ==, NULL); 824 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 825 i++; 826 827 g_assert_cmpstr(desc[i].name, ==, "str2"); 828 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 829 g_assert_cmpstr(desc[i].help, ==, NULL); 830 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 831 i++; 832 833 g_assert_cmpstr(desc[i].name, ==, "bool1"); 834 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL); 835 g_assert_cmpstr(desc[i].help, ==, NULL); 836 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 837 i++; 838 839 g_assert_cmpstr(desc[i].name, ==, "bool2"); 840 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL); 841 g_assert_cmpstr(desc[i].help, ==, NULL); 842 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 843 i++; 844 845 g_assert_cmpstr(desc[i].name, ==, "size1"); 846 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE); 847 g_assert_cmpstr(desc[i].help, ==, NULL); 848 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 849 i++; 850 851 g_assert_cmpstr(desc[i].name, ==, "size2"); 852 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE); 853 g_assert_cmpstr(desc[i].help, ==, NULL); 854 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 855 i++; 856 857 g_assert_cmpstr(desc[i].name, ==, "size3"); 858 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE); 859 g_assert_cmpstr(desc[i].help, ==, NULL); 860 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 861 } 862 863 static void test_opts_append_to_null(void) 864 { 865 QemuOptsList *merged; 866 867 merged = qemu_opts_append(NULL, &opts_list_01); 868 g_assert(merged != &opts_list_01); 869 870 g_assert_cmpstr(merged->name, ==, NULL); 871 g_assert_cmpstr(merged->implied_opt_name, ==, NULL); 872 g_assert_false(merged->merge_lists); 873 874 append_verify_list_01(merged->desc, true); 875 876 qemu_opts_free(merged); 877 } 878 879 static void test_opts_append(void) 880 { 881 QemuOptsList *first, *merged; 882 883 first = qemu_opts_append(NULL, &opts_list_02); 884 merged = qemu_opts_append(first, &opts_list_01); 885 g_assert(first != &opts_list_02); 886 g_assert(merged != &opts_list_01); 887 888 g_assert_cmpstr(merged->name, ==, NULL); 889 g_assert_cmpstr(merged->implied_opt_name, ==, NULL); 890 g_assert_false(merged->merge_lists); 891 892 append_verify_list_02(&merged->desc[0]); 893 append_verify_list_01(&merged->desc[7], false); 894 895 qemu_opts_free(merged); 896 } 897 898 static void test_opts_to_qdict_basic(void) 899 { 900 QemuOpts *opts; 901 QDict *dict; 902 903 opts = qemu_opts_parse(&opts_list_01, "str1=foo,str2=,str3=bar,number1=42", 904 false, &error_abort); 905 g_assert(opts != NULL); 906 907 dict = qemu_opts_to_qdict(opts, NULL); 908 g_assert(dict != NULL); 909 910 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo"); 911 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, ""); 912 g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar"); 913 g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42"); 914 g_assert_false(qdict_haskey(dict, "number2")); 915 916 qobject_unref(dict); 917 qemu_opts_del(opts); 918 } 919 920 static void test_opts_to_qdict_filtered(void) 921 { 922 QemuOptsList *first, *merged; 923 QemuOpts *opts; 924 QDict *dict; 925 926 first = qemu_opts_append(NULL, &opts_list_02); 927 merged = qemu_opts_append(first, &opts_list_01); 928 929 opts = qemu_opts_parse(merged, 930 "str1=foo,str2=,str3=bar,bool1=off,number1=42", 931 false, &error_abort); 932 g_assert(opts != NULL); 933 934 /* Convert to QDict without deleting from opts */ 935 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, false); 936 g_assert(dict != NULL); 937 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo"); 938 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, ""); 939 g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar"); 940 g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42"); 941 g_assert_false(qdict_haskey(dict, "number2")); 942 g_assert_false(qdict_haskey(dict, "bool1")); 943 qobject_unref(dict); 944 945 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, false); 946 g_assert(dict != NULL); 947 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo"); 948 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, ""); 949 g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off"); 950 g_assert_false(qdict_haskey(dict, "str3")); 951 g_assert_false(qdict_haskey(dict, "number1")); 952 g_assert_false(qdict_haskey(dict, "number2")); 953 qobject_unref(dict); 954 955 /* Now delete converted options from opts */ 956 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, true); 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, "str3"), ==, "bar"); 961 g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42"); 962 g_assert_false(qdict_haskey(dict, "number2")); 963 g_assert_false(qdict_haskey(dict, "bool1")); 964 qobject_unref(dict); 965 966 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, true); 967 g_assert(dict != NULL); 968 g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off"); 969 g_assert_false(qdict_haskey(dict, "str1")); 970 g_assert_false(qdict_haskey(dict, "str2")); 971 g_assert_false(qdict_haskey(dict, "str3")); 972 g_assert_false(qdict_haskey(dict, "number1")); 973 g_assert_false(qdict_haskey(dict, "number2")); 974 qobject_unref(dict); 975 976 g_assert_true(QTAILQ_EMPTY(&opts->head)); 977 978 qemu_opts_del(opts); 979 qemu_opts_free(merged); 980 } 981 982 static void test_opts_to_qdict_duplicates(void) 983 { 984 QemuOpts *opts; 985 QemuOpt *opt; 986 QDict *dict; 987 988 opts = qemu_opts_parse(&opts_list_03, "foo=a,foo=b", false, &error_abort); 989 g_assert(opts != NULL); 990 991 /* Verify that opts has two options with the same name */ 992 opt = QTAILQ_FIRST(&opts->head); 993 g_assert_cmpstr(opt->name, ==, "foo"); 994 g_assert_cmpstr(opt->str , ==, "a"); 995 996 opt = QTAILQ_NEXT(opt, next); 997 g_assert_cmpstr(opt->name, ==, "foo"); 998 g_assert_cmpstr(opt->str , ==, "b"); 999 1000 opt = QTAILQ_NEXT(opt, next); 1001 g_assert(opt == NULL); 1002 1003 /* In the conversion to QDict, the last one wins */ 1004 dict = qemu_opts_to_qdict(opts, NULL); 1005 g_assert(dict != NULL); 1006 g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b"); 1007 qobject_unref(dict); 1008 1009 /* The last one still wins if entries are deleted, and both are deleted */ 1010 dict = qemu_opts_to_qdict_filtered(opts, NULL, NULL, true); 1011 g_assert(dict != NULL); 1012 g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b"); 1013 qobject_unref(dict); 1014 1015 g_assert_true(QTAILQ_EMPTY(&opts->head)); 1016 1017 qemu_opts_del(opts); 1018 } 1019 1020 int main(int argc, char *argv[]) 1021 { 1022 register_opts(); 1023 g_test_init(&argc, &argv, NULL); 1024 g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts); 1025 g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts); 1026 g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create); 1027 g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get); 1028 g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool); 1029 g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number); 1030 g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size); 1031 g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset); 1032 g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset); 1033 g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set); 1034 g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse); 1035 g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool); 1036 g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number); 1037 g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size); 1038 g_test_add_func("/qemu-opts/has_help_option", test_has_help_option); 1039 g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null); 1040 g_test_add_func("/qemu-opts/append", test_opts_append); 1041 g_test_add_func("/qemu-opts/to_qdict/basic", test_opts_to_qdict_basic); 1042 g_test_add_func("/qemu-opts/to_qdict/filtered", test_opts_to_qdict_filtered); 1043 g_test_add_func("/qemu-opts/to_qdict/duplicates", test_opts_to_qdict_duplicates); 1044 g_test_run(); 1045 return 0; 1046 } 1047