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