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 "qapi/error.h" 13 #include "qapi/qmp/qstring.h" 14 #include "qemu/config-file.h" 15 16 17 static QemuOptsList opts_list_01 = { 18 .name = "opts_list_01", 19 .head = QTAILQ_HEAD_INITIALIZER(opts_list_01.head), 20 .desc = { 21 { 22 .name = "str1", 23 .type = QEMU_OPT_STRING, 24 },{ 25 .name = "str2", 26 .type = QEMU_OPT_STRING, 27 },{ 28 .name = "str3", 29 .type = QEMU_OPT_STRING, 30 },{ 31 .name = "number1", 32 .type = QEMU_OPT_NUMBER, 33 },{ 34 .name = "number2", 35 .type = QEMU_OPT_NUMBER, 36 }, 37 { /* end of list */ } 38 }, 39 }; 40 41 static QemuOptsList opts_list_02 = { 42 .name = "opts_list_02", 43 .head = QTAILQ_HEAD_INITIALIZER(opts_list_02.head), 44 .desc = { 45 { 46 .name = "str1", 47 .type = QEMU_OPT_STRING, 48 },{ 49 .name = "str2", 50 .type = QEMU_OPT_STRING, 51 },{ 52 .name = "bool1", 53 .type = QEMU_OPT_BOOL, 54 },{ 55 .name = "bool2", 56 .type = QEMU_OPT_BOOL, 57 },{ 58 .name = "size1", 59 .type = QEMU_OPT_SIZE, 60 },{ 61 .name = "size2", 62 .type = QEMU_OPT_SIZE, 63 },{ 64 .name = "size3", 65 .type = QEMU_OPT_SIZE, 66 }, 67 { /* end of list */ } 68 }, 69 }; 70 71 static QemuOptsList opts_list_03 = { 72 .name = "opts_list_03", 73 .implied_opt_name = "implied", 74 .head = QTAILQ_HEAD_INITIALIZER(opts_list_03.head), 75 .desc = { 76 /* no elements => accept any params */ 77 { /* end of list */ } 78 }, 79 }; 80 81 static void register_opts(void) 82 { 83 qemu_add_opts(&opts_list_01); 84 qemu_add_opts(&opts_list_02); 85 qemu_add_opts(&opts_list_03); 86 } 87 88 static void test_find_unknown_opts(void) 89 { 90 QemuOptsList *list; 91 Error *err = NULL; 92 93 /* should not return anything, we don't have an "unknown" option */ 94 list = qemu_find_opts_err("unknown", &err); 95 g_assert(list == NULL); 96 error_free_or_abort(&err); 97 } 98 99 static void test_qemu_find_opts(void) 100 { 101 QemuOptsList *list; 102 103 /* we have an "opts_list_01" option, should return it */ 104 list = qemu_find_opts("opts_list_01"); 105 g_assert(list != NULL); 106 g_assert_cmpstr(list->name, ==, "opts_list_01"); 107 } 108 109 static void test_qemu_opts_create(void) 110 { 111 QemuOptsList *list; 112 QemuOpts *opts; 113 114 list = qemu_find_opts("opts_list_01"); 115 g_assert(list != NULL); 116 g_assert(QTAILQ_EMPTY(&list->head)); 117 g_assert_cmpstr(list->name, ==, "opts_list_01"); 118 119 /* should not find anything at this point */ 120 opts = qemu_opts_find(list, NULL); 121 g_assert(opts == NULL); 122 123 /* create the opts */ 124 opts = qemu_opts_create(list, NULL, 0, &error_abort); 125 g_assert(opts != NULL); 126 g_assert(!QTAILQ_EMPTY(&list->head)); 127 128 /* now we've create the opts, must find it */ 129 opts = qemu_opts_find(list, NULL); 130 g_assert(opts != NULL); 131 132 qemu_opts_del(opts); 133 134 /* should not find anything at this point */ 135 opts = qemu_opts_find(list, NULL); 136 g_assert(opts == NULL); 137 } 138 139 static void test_qemu_opt_get(void) 140 { 141 QemuOptsList *list; 142 QemuOpts *opts; 143 const char *opt = NULL; 144 145 list = qemu_find_opts("opts_list_01"); 146 g_assert(list != NULL); 147 g_assert(QTAILQ_EMPTY(&list->head)); 148 g_assert_cmpstr(list->name, ==, "opts_list_01"); 149 150 /* should not find anything at this point */ 151 opts = qemu_opts_find(list, NULL); 152 g_assert(opts == NULL); 153 154 /* create the opts */ 155 opts = qemu_opts_create(list, NULL, 0, &error_abort); 156 g_assert(opts != NULL); 157 g_assert(!QTAILQ_EMPTY(&list->head)); 158 159 /* haven't set anything to str2 yet */ 160 opt = qemu_opt_get(opts, "str2"); 161 g_assert(opt == NULL); 162 163 qemu_opt_set(opts, "str2", "value", &error_abort); 164 165 /* now we have set str2, should know about it */ 166 opt = qemu_opt_get(opts, "str2"); 167 g_assert_cmpstr(opt, ==, "value"); 168 169 qemu_opt_set(opts, "str2", "value2", &error_abort); 170 171 /* having reset the value, the returned should be the reset one */ 172 opt = qemu_opt_get(opts, "str2"); 173 g_assert_cmpstr(opt, ==, "value2"); 174 175 qemu_opts_del(opts); 176 177 /* should not find anything at this point */ 178 opts = qemu_opts_find(list, NULL); 179 g_assert(opts == NULL); 180 } 181 182 static void test_qemu_opt_get_bool(void) 183 { 184 Error *err = NULL; 185 QemuOptsList *list; 186 QemuOpts *opts; 187 bool opt; 188 189 list = qemu_find_opts("opts_list_02"); 190 g_assert(list != NULL); 191 g_assert(QTAILQ_EMPTY(&list->head)); 192 g_assert_cmpstr(list->name, ==, "opts_list_02"); 193 194 /* should not find anything at this point */ 195 opts = qemu_opts_find(list, NULL); 196 g_assert(opts == NULL); 197 198 /* create the opts */ 199 opts = qemu_opts_create(list, NULL, 0, &error_abort); 200 g_assert(opts != NULL); 201 g_assert(!QTAILQ_EMPTY(&list->head)); 202 203 /* haven't set anything to bool1 yet, so defval should be returned */ 204 opt = qemu_opt_get_bool(opts, "bool1", false); 205 g_assert(opt == false); 206 207 qemu_opt_set_bool(opts, "bool1", true, &err); 208 g_assert(!err); 209 210 /* now we have set bool1, should know about it */ 211 opt = qemu_opt_get_bool(opts, "bool1", false); 212 g_assert(opt == true); 213 214 /* having reset the value, opt should be the reset one not defval */ 215 qemu_opt_set_bool(opts, "bool1", false, &err); 216 g_assert(!err); 217 218 opt = qemu_opt_get_bool(opts, "bool1", true); 219 g_assert(opt == false); 220 221 qemu_opts_del(opts); 222 223 /* should not find anything at this point */ 224 opts = qemu_opts_find(list, NULL); 225 g_assert(opts == NULL); 226 } 227 228 static void test_qemu_opt_get_number(void) 229 { 230 Error *err = NULL; 231 QemuOptsList *list; 232 QemuOpts *opts; 233 uint64_t opt; 234 235 list = qemu_find_opts("opts_list_01"); 236 g_assert(list != NULL); 237 g_assert(QTAILQ_EMPTY(&list->head)); 238 g_assert_cmpstr(list->name, ==, "opts_list_01"); 239 240 /* should not find anything at this point */ 241 opts = qemu_opts_find(list, NULL); 242 g_assert(opts == NULL); 243 244 /* create the opts */ 245 opts = qemu_opts_create(list, NULL, 0, &error_abort); 246 g_assert(opts != NULL); 247 g_assert(!QTAILQ_EMPTY(&list->head)); 248 249 /* haven't set anything to number1 yet, so defval should be returned */ 250 opt = qemu_opt_get_number(opts, "number1", 5); 251 g_assert(opt == 5); 252 253 qemu_opt_set_number(opts, "number1", 10, &err); 254 g_assert(!err); 255 256 /* now we have set number1, should know about it */ 257 opt = qemu_opt_get_number(opts, "number1", 5); 258 g_assert(opt == 10); 259 260 /* having reset it, the returned should be the reset one not defval */ 261 qemu_opt_set_number(opts, "number1", 15, &err); 262 g_assert(!err); 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(dict, "size1", qstring_from_str("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(dict, "size1", qstring_from_str("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 Error *err = NULL; 365 QemuOptsList *list; 366 QemuOpts *opts; 367 uint64_t opt; 368 369 list = qemu_find_opts("opts_list_01"); 370 g_assert(list != NULL); 371 g_assert(QTAILQ_EMPTY(&list->head)); 372 g_assert_cmpstr(list->name, ==, "opts_list_01"); 373 374 /* should not find anything at this point */ 375 opts = qemu_opts_find(list, NULL); 376 g_assert(opts == NULL); 377 378 /* create the opts */ 379 opts = qemu_opts_create(list, NULL, 0, &error_abort); 380 g_assert(opts != NULL); 381 g_assert(!QTAILQ_EMPTY(&list->head)); 382 383 /* haven't set anything to number1 yet, so defval should be returned */ 384 opt = qemu_opt_get_number(opts, "number1", 5); 385 g_assert(opt == 5); 386 387 qemu_opt_set_number(opts, "number1", 10, &err); 388 g_assert(!err); 389 390 /* now we have set number1, should know about it */ 391 opt = qemu_opt_get_number(opts, "number1", 5); 392 g_assert(opt == 10); 393 394 qemu_opts_reset(list); 395 396 /* should not find anything at this point */ 397 opts = qemu_opts_find(list, NULL); 398 g_assert(opts == NULL); 399 } 400 401 static void test_qemu_opts_set(void) 402 { 403 Error *err = NULL; 404 QemuOptsList *list; 405 QemuOpts *opts; 406 const char *opt; 407 408 list = qemu_find_opts("opts_list_01"); 409 g_assert(list != NULL); 410 g_assert(QTAILQ_EMPTY(&list->head)); 411 g_assert_cmpstr(list->name, ==, "opts_list_01"); 412 413 /* should not find anything at this point */ 414 opts = qemu_opts_find(list, NULL); 415 g_assert(opts == NULL); 416 417 /* implicitly create opts and set str3 value */ 418 qemu_opts_set(list, NULL, "str3", "value", &err); 419 g_assert(!err); 420 g_assert(!QTAILQ_EMPTY(&list->head)); 421 422 /* get the just created opts */ 423 opts = qemu_opts_find(list, NULL); 424 g_assert(opts != NULL); 425 426 /* check the str3 value */ 427 opt = qemu_opt_get(opts, "str3"); 428 g_assert_cmpstr(opt, ==, "value"); 429 430 qemu_opts_del(opts); 431 432 /* should not find anything at this point */ 433 opts = qemu_opts_find(list, NULL); 434 g_assert(opts == NULL); 435 } 436 437 static int opts_count_iter(void *opaque, const char *name, const char *value, 438 Error **errp) 439 { 440 (*(size_t *)opaque)++; 441 return 0; 442 } 443 444 static size_t opts_count(QemuOpts *opts) 445 { 446 size_t n = 0; 447 448 qemu_opt_foreach(opts, opts_count_iter, &n, NULL); 449 return n; 450 } 451 452 static void test_opts_parse(void) 453 { 454 Error *err = NULL; 455 QemuOpts *opts; 456 char long_key[129]; 457 char *params; 458 459 /* Nothing */ 460 opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort); 461 g_assert_cmpuint(opts_count(opts), ==, 0); 462 463 /* Empty key */ 464 opts = qemu_opts_parse(&opts_list_03, "=val", false, &error_abort); 465 g_assert_cmpuint(opts_count(opts), ==, 1); 466 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val"); 467 468 /* Long key */ 469 memset(long_key, 'a', 127); 470 long_key[127] = 'z'; 471 long_key[128] = 0; 472 params = g_strdup_printf("%s=v", long_key); 473 opts = qemu_opts_parse(&opts_list_03, params + 1, NULL, &error_abort); 474 g_assert_cmpuint(opts_count(opts), ==, 1); 475 g_assert_cmpstr(qemu_opt_get(opts, long_key + 1), ==, "v"); 476 477 /* Overlong key gets truncated */ 478 opts = qemu_opts_parse(&opts_list_03, params, NULL, &error_abort); 479 g_assert(opts_count(opts) == 1); 480 long_key[127] = 0; 481 g_assert_cmpstr(qemu_opt_get(opts, long_key), ==, "v"); 482 g_free(params); 483 484 /* Multiple keys, last one wins */ 485 opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3", 486 false, &error_abort); 487 g_assert_cmpuint(opts_count(opts), ==, 3); 488 g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "3"); 489 g_assert_cmpstr(qemu_opt_get(opts, "b"), ==, "2,x"); 490 491 /* Except when it doesn't */ 492 opts = qemu_opts_parse(&opts_list_03, "id=foo,id=bar", 493 false, &error_abort); 494 g_assert_cmpuint(opts_count(opts), ==, 0); 495 g_assert_cmpstr(qemu_opts_id(opts), ==, "foo"); 496 497 /* TODO Cover low-level access to repeated keys */ 498 499 /* Trailing comma is ignored */ 500 opts = qemu_opts_parse(&opts_list_03, "x=y,", false, &error_abort); 501 g_assert_cmpuint(opts_count(opts), ==, 1); 502 g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, "y"); 503 504 /* Except when it isn't */ 505 opts = qemu_opts_parse(&opts_list_03, ",", false, &error_abort); 506 g_assert_cmpuint(opts_count(opts), ==, 1); 507 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "on"); 508 509 /* Duplicate ID */ 510 opts = qemu_opts_parse(&opts_list_03, "x=y,id=foo", false, &err); 511 error_free_or_abort(&err); 512 g_assert(!opts); 513 /* TODO Cover .merge_lists = true */ 514 515 /* Buggy ID recognition */ 516 opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort); 517 g_assert_cmpuint(opts_count(opts), ==, 1); 518 g_assert_cmpstr(qemu_opts_id(opts), ==, "bar"); /* BUG */ 519 g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar"); 520 521 /* Anti-social ID */ 522 opts = qemu_opts_parse(&opts_list_01, "id=666", false, &err); 523 error_free_or_abort(&err); 524 g_assert(!opts); 525 526 /* Implied value */ 527 opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", 528 false, &error_abort); 529 g_assert_cmpuint(opts_count(opts), ==, 3); 530 g_assert_cmpstr(qemu_opt_get(opts, "an"), ==, "on"); 531 g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off"); 532 g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, ""); 533 534 /* Implied value, negated empty key */ 535 opts = qemu_opts_parse(&opts_list_03, "no", false, &error_abort); 536 g_assert_cmpuint(opts_count(opts), ==, 1); 537 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "off"); 538 539 /* Implied key */ 540 opts = qemu_opts_parse(&opts_list_03, "an,noaus,noaus=", true, 541 &error_abort); 542 g_assert_cmpuint(opts_count(opts), ==, 3); 543 g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, "an"); 544 g_assert_cmpstr(qemu_opt_get(opts, "aus"), ==, "off"); 545 g_assert_cmpstr(qemu_opt_get(opts, "noaus"), ==, ""); 546 547 /* Implied key with empty value */ 548 opts = qemu_opts_parse(&opts_list_03, ",", true, &error_abort); 549 g_assert_cmpuint(opts_count(opts), ==, 1); 550 g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ""); 551 552 /* Implied key with comma value */ 553 opts = qemu_opts_parse(&opts_list_03, ",,,a=1", true, &error_abort); 554 g_assert_cmpuint(opts_count(opts), ==, 2); 555 g_assert_cmpstr(qemu_opt_get(opts, "implied"), ==, ","); 556 g_assert_cmpstr(qemu_opt_get(opts, "a"), ==, "1"); 557 558 /* Empty key is not an implied key */ 559 opts = qemu_opts_parse(&opts_list_03, "=val", true, &error_abort); 560 g_assert_cmpuint(opts_count(opts), ==, 1); 561 g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val"); 562 563 /* Unknown key */ 564 opts = qemu_opts_parse(&opts_list_01, "nonexistent=", false, &err); 565 error_free_or_abort(&err); 566 g_assert(!opts); 567 568 qemu_opts_reset(&opts_list_01); 569 qemu_opts_reset(&opts_list_03); 570 } 571 572 static void test_opts_parse_bool(void) 573 { 574 Error *err = NULL; 575 QemuOpts *opts; 576 577 opts = qemu_opts_parse(&opts_list_02, "bool1=on,bool2=off", 578 false, &error_abort); 579 g_assert_cmpuint(opts_count(opts), ==, 2); 580 g_assert(qemu_opt_get_bool(opts, "bool1", false)); 581 g_assert(!qemu_opt_get_bool(opts, "bool2", true)); 582 583 opts = qemu_opts_parse(&opts_list_02, "bool1=offer", false, &err); 584 error_free_or_abort(&err); 585 g_assert(!opts); 586 587 qemu_opts_reset(&opts_list_02); 588 } 589 590 static void test_opts_parse_number(void) 591 { 592 Error *err = NULL; 593 QemuOpts *opts; 594 595 /* Lower limit zero */ 596 opts = qemu_opts_parse(&opts_list_01, "number1=0", false, &error_abort); 597 g_assert_cmpuint(opts_count(opts), ==, 1); 598 g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 0); 599 600 /* Upper limit 2^64-1 */ 601 opts = qemu_opts_parse(&opts_list_01, 602 "number1=18446744073709551615,number2=-1", 603 false, &error_abort); 604 g_assert_cmpuint(opts_count(opts), ==, 2); 605 g_assert_cmphex(qemu_opt_get_number(opts, "number1", 1), ==, UINT64_MAX); 606 g_assert_cmphex(qemu_opt_get_number(opts, "number2", 0), ==, UINT64_MAX); 607 608 /* Above upper limit */ 609 opts = qemu_opts_parse(&opts_list_01, "number1=18446744073709551616", 610 false, &err); 611 error_free_or_abort(&err); 612 g_assert(!opts); 613 614 /* Below lower 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 /* Hex and octal */ 621 opts = qemu_opts_parse(&opts_list_01, "number1=0x2a,number2=052", 622 false, &error_abort); 623 g_assert_cmpuint(opts_count(opts), ==, 2); 624 g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42); 625 g_assert_cmpuint(qemu_opt_get_number(opts, "number2", 0), ==, 42); 626 627 /* Invalid */ 628 opts = qemu_opts_parse(&opts_list_01, "number1=", false, &err); 629 error_free_or_abort(&err); 630 g_assert(!opts); 631 opts = qemu_opts_parse(&opts_list_01, "number1=eins", false, &err); 632 error_free_or_abort(&err); 633 g_assert(!opts); 634 635 /* Leading whitespace */ 636 opts = qemu_opts_parse(&opts_list_01, "number1= \t42", 637 false, &error_abort); 638 g_assert_cmpuint(opts_count(opts), ==, 1); 639 g_assert_cmpuint(qemu_opt_get_number(opts, "number1", 1), ==, 42); 640 641 /* Trailing crap */ 642 opts = qemu_opts_parse(&opts_list_01, "number1=3.14", false, &err); 643 error_free_or_abort(&err); 644 g_assert(!opts); 645 opts = qemu_opts_parse(&opts_list_01, "number1=08", false, &err); 646 error_free_or_abort(&err); 647 g_assert(!opts); 648 opts = qemu_opts_parse(&opts_list_01, "number1=0 ", false, &err); 649 error_free_or_abort(&err); 650 g_assert(!opts); 651 652 qemu_opts_reset(&opts_list_01); 653 } 654 655 static void test_opts_parse_size(void) 656 { 657 Error *err = NULL; 658 QemuOpts *opts; 659 660 /* Lower limit zero */ 661 opts = qemu_opts_parse(&opts_list_02, "size1=0", false, &error_abort); 662 g_assert_cmpuint(opts_count(opts), ==, 1); 663 g_assert_cmpuint(qemu_opt_get_size(opts, "size1", 1), ==, 0); 664 665 /* Note: precision is 53 bits since we're parsing with strtod() */ 666 667 /* Around limit of precision: 2^53-1, 2^53, 2^54 */ 668 opts = qemu_opts_parse(&opts_list_02, 669 "size1=9007199254740991," 670 "size2=9007199254740992," 671 "size3=9007199254740993", 672 false, &error_abort); 673 g_assert_cmpuint(opts_count(opts), ==, 3); 674 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), 675 ==, 0x1fffffffffffff); 676 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), 677 ==, 0x20000000000000); 678 g_assert_cmphex(qemu_opt_get_size(opts, "size3", 1), 679 ==, 0x20000000000000); 680 681 /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */ 682 opts = qemu_opts_parse(&opts_list_02, 683 "size1=9223372036854774784," /* 7ffffffffffffc00 */ 684 "size2=9223372036854775295", /* 7ffffffffffffdff */ 685 false, &error_abort); 686 g_assert_cmpuint(opts_count(opts), ==, 2); 687 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), 688 ==, 0x7ffffffffffffc00); 689 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), 690 ==, 0x7ffffffffffffc00); 691 692 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ 693 opts = qemu_opts_parse(&opts_list_02, 694 "size1=18446744073709549568," /* fffffffffffff800 */ 695 "size2=18446744073709550591", /* fffffffffffffbff */ 696 false, &error_abort); 697 g_assert_cmpuint(opts_count(opts), ==, 2); 698 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 1), 699 ==, 0xfffffffffffff800); 700 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 1), 701 ==, 0xfffffffffffff800); 702 703 /* Beyond limits */ 704 opts = qemu_opts_parse(&opts_list_02, "size1=-1", false, &err); 705 error_free_or_abort(&err); 706 g_assert(!opts); 707 opts = qemu_opts_parse(&opts_list_02, 708 "size1=18446744073709550592", /* fffffffffffffc00 */ 709 false, &err); 710 error_free_or_abort(&err); 711 g_assert(!opts); 712 713 /* Suffixes */ 714 opts = qemu_opts_parse(&opts_list_02, "size1=8b,size2=1.5k,size3=2M", 715 false, &error_abort); 716 g_assert_cmpuint(opts_count(opts), ==, 3); 717 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, 8); 718 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), ==, 1536); 719 g_assert_cmphex(qemu_opt_get_size(opts, "size3", 0), ==, 2 * M_BYTE); 720 opts = qemu_opts_parse(&opts_list_02, "size1=0.1G,size2=16777215T", 721 false, &error_abort); 722 g_assert_cmpuint(opts_count(opts), ==, 2); 723 g_assert_cmphex(qemu_opt_get_size(opts, "size1", 0), ==, G_BYTE / 10); 724 g_assert_cmphex(qemu_opt_get_size(opts, "size2", 0), 725 ==, 16777215 * T_BYTE); 726 727 /* Beyond limit with suffix */ 728 opts = qemu_opts_parse(&opts_list_02, "size1=16777216T", 729 false, &err); 730 error_free_or_abort(&err); 731 g_assert(!opts); 732 733 /* Trailing crap */ 734 opts = qemu_opts_parse(&opts_list_02, "size1=16E", false, &err); 735 error_free_or_abort(&err); 736 g_assert(!opts); 737 opts = qemu_opts_parse(&opts_list_02, "size1=16Gi", false, &err); 738 error_free_or_abort(&err); 739 g_assert(!opts); 740 741 qemu_opts_reset(&opts_list_02); 742 } 743 744 int main(int argc, char *argv[]) 745 { 746 register_opts(); 747 g_test_init(&argc, &argv, NULL); 748 g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts); 749 g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts); 750 g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create); 751 g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get); 752 g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool); 753 g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number); 754 g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size); 755 g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset); 756 g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset); 757 g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set); 758 g_test_add_func("/qemu-opts/opts_parse/general", test_opts_parse); 759 g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool); 760 g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number); 761 g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size); 762 g_test_run(); 763 return 0; 764 } 765