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