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 int opts_count_iter(void *opaque, const char *name, const char *value, 414 Error **errp) 415 { 416 (*(size_t *)opaque)++; 417 return 0; 418 } 419 420 static size_t opts_count(QemuOpts *opts) 421 { 422 size_t n = 0; 423 424 qemu_opt_foreach(opts, opts_count_iter, &n, NULL); 425 return n; 426 } 427 428 static void test_opts_parse(void) 429 { 430 Error *err = NULL; 431 QemuOpts *opts; 432 433 /* Nothing */ 434 opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort); 435 g_assert_cmpuint(opts_count(opts), ==, 0); 436 437 /* Empty key */ 438 opts = qemu_opts_parse(&opts_list_03, "=val", false, &error_abort); 439 g_assert_cmpuint(opts_count(opts), ==, 1); 440 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val"); 441 442 /* Multiple keys, last one wins */ 443 opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3", 444 false, &error_abort); 445 g_assert_cmpuint(opts_count(opts), ==, 3); 446 g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "3"); 447 g_assert_cmpstr(qemu_opt_get(opts, "b"), ==, "2,x"); 448 449 /* Except when it doesn't */ 450 opts = qemu_opts_parse(&opts_list_03, "id=foo,id=bar", 451 false, &error_abort); 452 g_assert_cmpuint(opts_count(opts), ==, 0); 453 g_assert_cmpstr(qemu_opts_id(opts), ==, "foo"); 454 455 /* TODO Cover low-level access to repeated keys */ 456 457 /* Trailing comma is ignored */ 458 opts = qemu_opts_parse(&opts_list_03, "x=y,", false, &error_abort); 459 g_assert_cmpuint(opts_count(opts), ==, 1); 460 g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, "y"); 461 462 /* Except when it isn't */ 463 opts = qemu_opts_parse(&opts_list_03, ",", false, &error_abort); 464 g_assert_cmpuint(opts_count(opts), ==, 1); 465 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "on"); 466 467 /* Duplicate ID */ 468 opts = qemu_opts_parse(&opts_list_03, "x=y,id=foo", false, &err); 469 error_free_or_abort(&err); 470 g_assert(!opts); 471 /* TODO Cover .merge_lists = true */ 472 473 /* Buggy ID recognition (fixed) */ 474 opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort); 475 g_assert_cmpuint(opts_count(opts), ==, 1); 476 g_assert(!qemu_opts_id(opts)); 477 g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar"); 478 479 /* Anti-social ID */ 480 opts = qemu_opts_parse(&opts_list_01, "id=666", false, &err); 481 error_free_or_abort(&err); 482 g_assert(!opts); 483 484 /* Implied value (qemu_opts_parse warns but accepts it) */ 485 opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", 486 false, &error_abort); 487 g_assert_cmpuint(opts_count(opts), ==, 3); 488 g_assert_cmpstr(qemu_opt_get(opts, "an"), ==, "on"); 489 g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off"); 490 g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, ""); 491 492 /* Implied value, negated empty key */ 493 opts = qemu_opts_parse(&opts_list_03, "no", false, &error_abort); 494 g_assert_cmpuint(opts_count(opts), ==, 1); 495 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "off"); 496 497 /* Implied key */ 498 opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", true, 499 &error_abort); 500 g_assert_cmpuint(opts_count(opts), ==, 3); 501 g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "an"); 502 g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off"); 503 g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, ""); 504 505 /* Implied key with empty value */ 506 opts = qemu_opts_parse(&opts_list_03, ",", true, &error_abort); 507 g_assert_cmpuint(opts_count(opts), ==, 1); 508 g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ""); 509 510 /* Implied key with comma value */ 511 opts = qemu_opts_parse(&opts_list_03, ",,,a=1", true, &error_abort); 512 g_assert_cmpuint(opts_count(opts), ==, 2); 513 g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ","); 514 g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "1"); 515 516 /* Empty key is not an implied key */ 517 opts = qemu_opts_parse(&opts_list_03, "=val", true, &error_abort); 518 g_assert_cmpuint(opts_count(opts), ==, 1); 519 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val"); 520 521 /* Unknown key */ 522 opts = qemu_opts_parse(&opts_list_01, "nonexistent=", false, &err); 523 error_free_or_abort(&err); 524 g_assert(!opts); 525 526 qemu_opts_reset(&opts_list_01); 527 qemu_opts_reset(&opts_list_03); 528 } 529 530 static void test_opts_parse_bool(void) 531 { 532 Error *err = NULL; 533 QemuOpts *opts; 534 535 opts = qemu_opts_parse(&opts_list_02, "bool1=on,bool2=off", 536 false, &error_abort); 537 g_assert_cmpuint(opts_count(opts), ==, 2); 538 g_assert(qemu_opt_get_bool(opts, "bool1", false)); 539 g_assert(!qemu_opt_get_bool(opts, "bool2", true)); 540 541 opts = qemu_opts_parse(&opts_list_02, "bool1=offer", false, &err); 542 error_free_or_abort(&err); 543 g_assert(!opts); 544 545 qemu_opts_reset(&opts_list_02); 546 } 547 548 static void test_opts_parse_number(void) 549 { 550 Error *err = NULL; 551 QemuOpts *opts; 552 553 /* Lower limit zero */ 554 opts = qemu_opts_parse(&opts_list_01, "number1=0", false, &error_abort); 555 g_assert_cmpuint(opts_count(opts), ==, 1); 556 g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 0); 557 558 /* Upper limit 2^64-1 */ 559 opts = qemu_opts_parse(&opts_list_01, 560 "number1=18446744073709551615,number2=-1", 561 false, &error_abort); 562 g_assert_cmpuint(opts_count(opts), ==, 2); 563 g_assert_cmphex(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX); 564 g_assert_cmphex(qemu_opt_get_number(opts, "number2", 0), ==, UINT64_MAX); 565 566 /* Above upper limit */ 567 opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616", 568 false, &err); 569 error_free_or_abort(&err); 570 g_assert(!opts); 571 572 /* Below lower limit */ 573 opts = qemu_opts_parse(&opts_list_01, "number1=-18446744073709551616", 574 false, &err); 575 error_free_or_abort(&err); 576 g_assert(!opts); 577 578 /* Hex and octal */ 579 opts = qemu_opts_parse(&opts_list_01, "number1=0x2a,number2=052", 580 false, &error_abort); 581 g_assert_cmpuint(opts_count(opts), ==, 2); 582 g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42); 583 g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), ==, 42); 584 585 /* Invalid */ 586 opts = qemu_opts_parse(&opts_list_01, "number1=", false, &err); 587 error_free_or_abort(&err); 588 g_assert(!opts); 589 opts = qemu_opts_parse(&opts_list_01, "number1=eins", false, &err); 590 error_free_or_abort(&err); 591 g_assert(!opts); 592 593 /* Leading whitespace */ 594 opts = qemu_opts_parse(&opts_list_01, "number1= \t42", 595 false, &error_abort); 596 g_assert_cmpuint(opts_count(opts), ==, 1); 597 g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42); 598 599 /* Trailing crap */ 600 opts = qemu_opts_parse(&opts_list_01, "number1=3.14", false, &err); 601 error_free_or_abort(&err); 602 g_assert(!opts); 603 opts = qemu_opts_parse(&opts_list_01, "number1=08", false, &err); 604 error_free_or_abort(&err); 605 g_assert(!opts); 606 opts = qemu_opts_parse(&opts_list_01, "number1=0 ", false, &err); 607 error_free_or_abort(&err); 608 g_assert(!opts); 609 610 qemu_opts_reset(&opts_list_01); 611 } 612 613 static void test_opts_parse_size(void) 614 { 615 Error *err = NULL; 616 QemuOpts *opts; 617 618 /* Lower limit zero */ 619 opts = qemu_opts_parse(&opts_list_02, "size1=0", false, &error_abort); 620 g_assert_cmpuint(opts_count(opts), ==, 1); 621 g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0); 622 623 /* Note: full 64 bits of precision */ 624 625 /* Around double limit of precision: 2^53-1, 2^53, 2^53+1 */ 626 opts = qemu_opts_parse(&opts_list_02, 627 "size1=9007199254740991," 628 "size2=9007199254740992," 629 "size3=9007199254740993", 630 false, &error_abort); 631 g_assert_cmpuint(opts_count(opts), ==, 3); 632 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), 633 ==, 0x1fffffffffffff); 634 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), 635 ==, 0x20000000000000); 636 g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1), 637 ==, 0x20000000000001); 638 639 /* Close to signed int limit: 2^63-1, 2^63, 2^63+1 */ 640 opts = qemu_opts_parse(&opts_list_02, 641 "size1=9223372036854775807," /* 7fffffffffffffff */ 642 "size2=9223372036854775808," /* 8000000000000000 */ 643 "size3=9223372036854775809", /* 8000000000000001 */ 644 false, &error_abort); 645 g_assert_cmpuint(opts_count(opts), ==, 3); 646 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), 647 ==, 0x7fffffffffffffff); 648 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), 649 ==, 0x8000000000000000); 650 g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1), 651 ==, 0x8000000000000001); 652 653 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ 654 opts = qemu_opts_parse(&opts_list_02, 655 "size1=18446744073709549568," /* fffffffffffff800 */ 656 "size2=18446744073709550591", /* fffffffffffffbff */ 657 false, &error_abort); 658 g_assert_cmpuint(opts_count(opts), ==, 2); 659 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), 660 ==, 0xfffffffffffff800); 661 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), 662 ==, 0xfffffffffffffbff); 663 664 /* Actual limit, 2^64-1 */ 665 opts = qemu_opts_parse(&opts_list_02, 666 "size1=18446744073709551615", /* ffffffffffffffff */ 667 false, &error_abort); 668 g_assert_cmpuint(opts_count(opts), ==, 1); 669 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), 670 ==, 0xffffffffffffffff); 671 672 /* Beyond limits */ 673 opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err); 674 error_free_or_abort(&err); 675 g_assert(!opts); 676 opts = qemu_opts_parse(&opts_list_02, 677 "size1=18446744073709551616", /* 2^64 */ 678 false, &err); 679 error_free_or_abort(&err); 680 g_assert(!opts); 681 682 /* Suffixes */ 683 opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M", 684 false, &error_abort); 685 g_assert_cmpuint(opts_count(opts), ==, 3); 686 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8); 687 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536); 688 g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * MiB); 689 opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T", 690 false, &error_abort); 691 g_assert_cmpuint(opts_count(opts), ==, 2); 692 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, GiB / 10); 693 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 16777215ULL * TiB); 694 695 /* Beyond limit with suffix */ 696 opts = qemu_opts_parse(&opts_list_02, "size1=16777216T", 697 false, &err); 698 error_free_or_abort(&err); 699 g_assert(!opts); 700 701 /* Trailing crap */ 702 opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err); 703 error_free_or_abort(&err); 704 g_assert(!opts); 705 opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &err); 706 error_free_or_abort(&err); 707 g_assert(!opts); 708 709 qemu_opts_reset(&opts_list_02); 710 } 711 712 static void test_has_help_option(void) 713 { 714 static const struct { 715 const char *params; 716 /* expected value of qemu_opt_has_help_opt() with implied=false */ 717 bool expect; 718 /* expected value of qemu_opt_has_help_opt() with implied=true */ 719 bool expect_implied; 720 } test[] = { 721 { "help", true, false }, 722 { "?", true, false }, 723 { "helpme", false, false }, 724 { "?me", false, false }, 725 { "a,help", true, true }, 726 { "a,?", true, true }, 727 { "a=0,help,b", true, true }, 728 { "a=0,?,b", true, true }, 729 { "help,b=1", true, false }, 730 { "?,b=1", true, false }, 731 { "a,b,,help", true, true }, 732 { "a,b,,?", true, true }, 733 }; 734 int i; 735 QemuOpts *opts; 736 737 for (i = 0; i < ARRAY_SIZE(test); i++) { 738 g_assert_cmpint(has_help_option(test[i].params), 739 ==, test[i].expect); 740 opts = qemu_opts_parse(&opts_list_03, test[i].params, false, 741 &error_abort); 742 g_assert_cmpint(qemu_opt_has_help_opt(opts), 743 ==, test[i].expect); 744 qemu_opts_del(opts); 745 opts = qemu_opts_parse(&opts_list_03, test[i].params, true, 746 &error_abort); 747 g_assert_cmpint(qemu_opt_has_help_opt(opts), 748 ==, test[i].expect_implied); 749 qemu_opts_del(opts); 750 } 751 } 752 753 static void append_verify_list_01(QemuOptDesc *desc, bool with_overlapping) 754 { 755 int i = 0; 756 757 if (with_overlapping) { 758 g_assert_cmpstr(desc[i].name, ==, "str1"); 759 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 760 g_assert_cmpstr(desc[i].help, ==, 761 "Help texts are preserved in qemu_opts_append"); 762 g_assert_cmpstr(desc[i].def_value_str, ==, "default"); 763 i++; 764 765 g_assert_cmpstr(desc[i].name, ==, "str2"); 766 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 767 g_assert_cmpstr(desc[i].help, ==, NULL); 768 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 769 i++; 770 } 771 772 g_assert_cmpstr(desc[i].name, ==, "str3"); 773 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 774 g_assert_cmpstr(desc[i].help, ==, NULL); 775 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 776 i++; 777 778 g_assert_cmpstr(desc[i].name, ==, "number1"); 779 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER); 780 g_assert_cmpstr(desc[i].help, ==, 781 "Having help texts only for some options is okay"); 782 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 783 i++; 784 785 g_assert_cmpstr(desc[i].name, ==, "number2"); 786 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_NUMBER); 787 g_assert_cmpstr(desc[i].help, ==, NULL); 788 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 789 i++; 790 791 g_assert_cmpstr(desc[i].name, ==, NULL); 792 } 793 794 static void append_verify_list_02(QemuOptDesc *desc) 795 { 796 int i = 0; 797 798 g_assert_cmpstr(desc[i].name, ==, "str1"); 799 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 800 g_assert_cmpstr(desc[i].help, ==, NULL); 801 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 802 i++; 803 804 g_assert_cmpstr(desc[i].name, ==, "str2"); 805 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_STRING); 806 g_assert_cmpstr(desc[i].help, ==, NULL); 807 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 808 i++; 809 810 g_assert_cmpstr(desc[i].name, ==, "bool1"); 811 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL); 812 g_assert_cmpstr(desc[i].help, ==, NULL); 813 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 814 i++; 815 816 g_assert_cmpstr(desc[i].name, ==, "bool2"); 817 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_BOOL); 818 g_assert_cmpstr(desc[i].help, ==, NULL); 819 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 820 i++; 821 822 g_assert_cmpstr(desc[i].name, ==, "size1"); 823 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE); 824 g_assert_cmpstr(desc[i].help, ==, NULL); 825 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 826 i++; 827 828 g_assert_cmpstr(desc[i].name, ==, "size2"); 829 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE); 830 g_assert_cmpstr(desc[i].help, ==, NULL); 831 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 832 i++; 833 834 g_assert_cmpstr(desc[i].name, ==, "size3"); 835 g_assert_cmpint(desc[i].type, ==, QEMU_OPT_SIZE); 836 g_assert_cmpstr(desc[i].help, ==, NULL); 837 g_assert_cmpstr(desc[i].def_value_str, ==, NULL); 838 } 839 840 static void test_opts_append_to_null(void) 841 { 842 QemuOptsList *merged; 843 844 merged = qemu_opts_append(NULL, &opts_list_01); 845 g_assert(merged != &opts_list_01); 846 847 g_assert_cmpstr(merged->name, ==, NULL); 848 g_assert_cmpstr(merged->implied_opt_name, ==, NULL); 849 g_assert_false(merged->merge_lists); 850 851 append_verify_list_01(merged->desc, true); 852 853 qemu_opts_free(merged); 854 } 855 856 static void test_opts_append(void) 857 { 858 QemuOptsList *first, *merged; 859 860 first = qemu_opts_append(NULL, &opts_list_02); 861 merged = qemu_opts_append(first, &opts_list_01); 862 g_assert(first != &opts_list_02); 863 g_assert(merged != &opts_list_01); 864 865 g_assert_cmpstr(merged->name, ==, NULL); 866 g_assert_cmpstr(merged->implied_opt_name, ==, NULL); 867 g_assert_false(merged->merge_lists); 868 869 append_verify_list_02(&merged->desc[0]); 870 append_verify_list_01(&merged->desc[7], false); 871 872 qemu_opts_free(merged); 873 } 874 875 static void test_opts_to_qdict_basic(void) 876 { 877 QemuOpts *opts; 878 QDict *dict; 879 880 opts = qemu_opts_parse(&opts_list_01, "str1=foo,str2=,str3=bar,number1=42", 881 false, &error_abort); 882 g_assert(opts != NULL); 883 884 dict = qemu_opts_to_qdict(opts, NULL); 885 g_assert(dict != NULL); 886 887 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo"); 888 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, ""); 889 g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar"); 890 g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42"); 891 g_assert_false(qdict_haskey(dict, "number2")); 892 893 qobject_unref(dict); 894 qemu_opts_del(opts); 895 } 896 897 static void test_opts_to_qdict_filtered(void) 898 { 899 QemuOptsList *first, *merged; 900 QemuOpts *opts; 901 QDict *dict; 902 903 first = qemu_opts_append(NULL, &opts_list_02); 904 merged = qemu_opts_append(first, &opts_list_01); 905 906 opts = qemu_opts_parse(merged, 907 "str1=foo,str2=,str3=bar,bool1=off,number1=42", 908 false, &error_abort); 909 g_assert(opts != NULL); 910 911 /* Convert to QDict without deleting from opts */ 912 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, false); 913 g_assert(dict != NULL); 914 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo"); 915 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, ""); 916 g_assert_cmpstr(qdict_get_str(dict, "str3"), ==, "bar"); 917 g_assert_cmpstr(qdict_get_str(dict, "number1"), ==, "42"); 918 g_assert_false(qdict_haskey(dict, "number2")); 919 g_assert_false(qdict_haskey(dict, "bool1")); 920 qobject_unref(dict); 921 922 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_02, false); 923 g_assert(dict != NULL); 924 g_assert_cmpstr(qdict_get_str(dict, "str1"), ==, "foo"); 925 g_assert_cmpstr(qdict_get_str(dict, "str2"), ==, ""); 926 g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off"); 927 g_assert_false(qdict_haskey(dict, "str3")); 928 g_assert_false(qdict_haskey(dict, "number1")); 929 g_assert_false(qdict_haskey(dict, "number2")); 930 qobject_unref(dict); 931 932 /* Now delete converted options from opts */ 933 dict = qemu_opts_to_qdict_filtered(opts, NULL, &opts_list_01, true); 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, true); 944 g_assert(dict != NULL); 945 g_assert_cmpstr(qdict_get_str(dict, "bool1"), ==, "off"); 946 g_assert_false(qdict_haskey(dict, "str1")); 947 g_assert_false(qdict_haskey(dict, "str2")); 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 g_assert_true(QTAILQ_EMPTY(&opts->head)); 954 955 qemu_opts_del(opts); 956 qemu_opts_free(merged); 957 } 958 959 static void test_opts_to_qdict_duplicates(void) 960 { 961 QemuOpts *opts; 962 QemuOpt *opt; 963 QDict *dict; 964 965 opts = qemu_opts_parse(&opts_list_03, "foo=a,foo=b", false, &error_abort); 966 g_assert(opts != NULL); 967 968 /* Verify that opts has two options with the same name */ 969 opt = QTAILQ_FIRST(&opts->head); 970 g_assert_cmpstr(opt->name, ==, "foo"); 971 g_assert_cmpstr(opt->str , ==, "a"); 972 973 opt = QTAILQ_NEXT(opt, next); 974 g_assert_cmpstr(opt->name, ==, "foo"); 975 g_assert_cmpstr(opt->str , ==, "b"); 976 977 opt = QTAILQ_NEXT(opt, next); 978 g_assert(opt == NULL); 979 980 /* In the conversion to QDict, the last one wins */ 981 dict = qemu_opts_to_qdict(opts, NULL); 982 g_assert(dict != NULL); 983 g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b"); 984 qobject_unref(dict); 985 986 /* The last one still wins if entries are deleted, and both are deleted */ 987 dict = qemu_opts_to_qdict_filtered(opts, NULL, NULL, true); 988 g_assert(dict != NULL); 989 g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "b"); 990 qobject_unref(dict); 991 992 g_assert_true(QTAILQ_EMPTY(&opts->head)); 993 994 qemu_opts_del(opts); 995 } 996 997 int main(int argc, char *argv[]) 998 { 999 register_opts(); 1000 g_test_init(&argc, &argv, NULL); 1001 g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts); 1002 g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts); 1003 g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create); 1004 g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get); 1005 g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool); 1006 g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number); 1007 g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size); 1008 g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset); 1009 g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset); 1010 g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse); 1011 g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool); 1012 g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number); 1013 g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size); 1014 g_test_add_func("/qemu-opts/has_help_option", test_has_help_option); 1015 g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null); 1016 g_test_add_func("/qemu-opts/append", test_opts_append); 1017 g_test_add_func("/qemu-opts/to_qdict/basic", test_opts_to_qdict_basic); 1018 g_test_add_func("/qemu-opts/to_qdict/filtered", test_opts_to_qdict_filtered); 1019 g_test_add_func("/qemu-opts/to_qdict/duplicates", test_opts_to_qdict_duplicates); 1020 g_test_run(); 1021 return 0; 1022 } 1023