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