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