1 /* 2 * Unit tests for parsing of KEY=VALUE,... strings 3 * 4 * Copyright (C) 2017 Red Hat Inc. 5 * 6 * Authors: 7 * Markus Armbruster <armbru@redhat.com>, 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 #include "qemu/units.h" 15 #include "qapi/error.h" 16 #include "qapi/qmp/qdict.h" 17 #include "qapi/qmp/qlist.h" 18 #include "qapi/qmp/qstring.h" 19 #include "qapi/qobject-input-visitor.h" 20 #include "test-qapi-visit.h" 21 #include "qemu/cutils.h" 22 #include "qemu/keyval.h" 23 24 static void test_keyval_parse(void) 25 { 26 Error *err = NULL; 27 QDict *qdict, *sub_qdict; 28 char long_key[129]; 29 char *params; 30 bool help; 31 32 /* Nothing */ 33 qdict = keyval_parse("", NULL, NULL, &error_abort); 34 g_assert_cmpuint(qdict_size(qdict), ==, 0); 35 qobject_unref(qdict); 36 37 /* Empty key (qemu_opts_parse() accepts this) */ 38 qdict = keyval_parse("=val", NULL, NULL, &err); 39 error_free_or_abort(&err); 40 g_assert(!qdict); 41 42 /* Empty key fragment */ 43 qdict = keyval_parse(".", NULL, NULL, &err); 44 error_free_or_abort(&err); 45 g_assert(!qdict); 46 qdict = keyval_parse("key.", NULL, NULL, &err); 47 error_free_or_abort(&err); 48 g_assert(!qdict); 49 50 /* Invalid non-empty key (qemu_opts_parse() doesn't care) */ 51 qdict = keyval_parse("7up=val", NULL, NULL, &err); 52 error_free_or_abort(&err); 53 g_assert(!qdict); 54 55 /* Overlong key */ 56 memset(long_key, 'a', 127); 57 long_key[127] = 'z'; 58 long_key[128] = 0; 59 params = g_strdup_printf("k.%s=v", long_key); 60 qdict = keyval_parse(params + 2, NULL, NULL, &err); 61 error_free_or_abort(&err); 62 g_assert(!qdict); 63 64 /* Overlong key fragment */ 65 qdict = keyval_parse(params, NULL, NULL, &err); 66 error_free_or_abort(&err); 67 g_assert(!qdict); 68 g_free(params); 69 70 /* Long key (qemu_opts_parse() accepts and truncates silently) */ 71 params = g_strdup_printf("k.%s=v", long_key + 1); 72 qdict = keyval_parse(params + 2, NULL, NULL, &error_abort); 73 g_assert_cmpuint(qdict_size(qdict), ==, 1); 74 g_assert_cmpstr(qdict_get_try_str(qdict, long_key + 1), ==, "v"); 75 qobject_unref(qdict); 76 77 /* Long key fragment */ 78 qdict = keyval_parse(params, NULL, NULL, &error_abort); 79 g_assert_cmpuint(qdict_size(qdict), ==, 1); 80 sub_qdict = qdict_get_qdict(qdict, "k"); 81 g_assert(sub_qdict); 82 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 83 g_assert_cmpstr(qdict_get_try_str(sub_qdict, long_key + 1), ==, "v"); 84 qobject_unref(qdict); 85 g_free(params); 86 87 /* Crap after valid key */ 88 qdict = keyval_parse("key[0]=val", NULL, NULL, &err); 89 error_free_or_abort(&err); 90 g_assert(!qdict); 91 92 /* Multiple keys, last one wins */ 93 qdict = keyval_parse("a=1,b=2,,x,a=3", NULL, NULL, &error_abort); 94 g_assert_cmpuint(qdict_size(qdict), ==, 2); 95 g_assert_cmpstr(qdict_get_try_str(qdict, "a"), ==, "3"); 96 g_assert_cmpstr(qdict_get_try_str(qdict, "b"), ==, "2,x"); 97 qobject_unref(qdict); 98 99 /* Even when it doesn't in qemu_opts_parse() */ 100 qdict = keyval_parse("id=foo,id=bar", NULL, NULL, &error_abort); 101 g_assert_cmpuint(qdict_size(qdict), ==, 1); 102 g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "bar"); 103 qobject_unref(qdict); 104 105 /* Dotted keys */ 106 qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, NULL, &error_abort); 107 g_assert_cmpuint(qdict_size(qdict), ==, 2); 108 sub_qdict = qdict_get_qdict(qdict, "a"); 109 g_assert(sub_qdict); 110 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 111 sub_qdict = qdict_get_qdict(sub_qdict, "b"); 112 g_assert(sub_qdict); 113 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 114 g_assert_cmpstr(qdict_get_try_str(sub_qdict, "c"), ==, "2"); 115 g_assert_cmpstr(qdict_get_try_str(qdict, "d"), ==, "3"); 116 qobject_unref(qdict); 117 118 /* Inconsistent dotted keys */ 119 qdict = keyval_parse("a.b=1,a=2", NULL, NULL, &err); 120 error_free_or_abort(&err); 121 g_assert(!qdict); 122 qdict = keyval_parse("a.b=1,a.b.c=2", NULL, NULL, &err); 123 error_free_or_abort(&err); 124 g_assert(!qdict); 125 126 /* Trailing comma is ignored */ 127 qdict = keyval_parse("x=y,", NULL, NULL, &error_abort); 128 g_assert_cmpuint(qdict_size(qdict), ==, 1); 129 g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, "y"); 130 qobject_unref(qdict); 131 132 /* Except when it isn't */ 133 qdict = keyval_parse(",", NULL, NULL, &err); 134 error_free_or_abort(&err); 135 g_assert(!qdict); 136 137 /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */ 138 qdict = keyval_parse("x=,,id=bar", NULL, NULL, &error_abort); 139 g_assert_cmpuint(qdict_size(qdict), ==, 1); 140 g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, ",id=bar"); 141 qobject_unref(qdict); 142 143 /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */ 144 qdict = keyval_parse("id=666", NULL, NULL, &error_abort); 145 g_assert_cmpuint(qdict_size(qdict), ==, 1); 146 g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "666"); 147 qobject_unref(qdict); 148 149 /* Implied value not supported (unlike qemu_opts_parse()) */ 150 qdict = keyval_parse("an,noaus,noaus=", NULL, NULL, &err); 151 error_free_or_abort(&err); 152 g_assert(!qdict); 153 154 /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */ 155 qdict = keyval_parse("no", NULL, NULL, &err); 156 error_free_or_abort(&err); 157 g_assert(!qdict); 158 159 /* Implied key */ 160 qdict = keyval_parse("an,aus=off,noaus=", "implied", NULL, &error_abort); 161 g_assert_cmpuint(qdict_size(qdict), ==, 3); 162 g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "an"); 163 g_assert_cmpstr(qdict_get_try_str(qdict, "aus"), ==, "off"); 164 g_assert_cmpstr(qdict_get_try_str(qdict, "noaus"), ==, ""); 165 qobject_unref(qdict); 166 167 /* Implied dotted key */ 168 qdict = keyval_parse("val", "eins.zwei", NULL, &error_abort); 169 g_assert_cmpuint(qdict_size(qdict), ==, 1); 170 sub_qdict = qdict_get_qdict(qdict, "eins"); 171 g_assert(sub_qdict); 172 g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 173 g_assert_cmpstr(qdict_get_try_str(sub_qdict, "zwei"), ==, "val"); 174 qobject_unref(qdict); 175 176 /* Implied key with empty value (qemu_opts_parse() accepts this) */ 177 qdict = keyval_parse(",", "implied", NULL, &err); 178 error_free_or_abort(&err); 179 g_assert(!qdict); 180 181 /* Likewise (qemu_opts_parse(): implied key with comma value) */ 182 qdict = keyval_parse(",,,a=1", "implied", NULL, &err); 183 error_free_or_abort(&err); 184 g_assert(!qdict); 185 186 /* Implied key's value can't have comma (qemu_opts_parse(): it can) */ 187 qdict = keyval_parse("val,,ue", "implied", NULL, &err); 188 error_free_or_abort(&err); 189 g_assert(!qdict); 190 191 /* Empty key is not an implied key */ 192 qdict = keyval_parse("=val", "implied", NULL, &err); 193 error_free_or_abort(&err); 194 g_assert(!qdict); 195 196 /* "help" by itself, without implied key */ 197 qdict = keyval_parse("help", NULL, &help, &error_abort); 198 g_assert_cmpuint(qdict_size(qdict), ==, 0); 199 g_assert(help); 200 qobject_unref(qdict); 201 202 /* "help" by itself, with implied key */ 203 qdict = keyval_parse("help", "implied", &help, &error_abort); 204 g_assert_cmpuint(qdict_size(qdict), ==, 0); 205 g_assert(help); 206 qobject_unref(qdict); 207 208 /* "help" when no help is available, without implied key */ 209 qdict = keyval_parse("help", NULL, NULL, &err); 210 error_free_or_abort(&err); 211 g_assert(!qdict); 212 213 /* "help" when no help is available, with implied key */ 214 qdict = keyval_parse("help", "implied", NULL, &err); 215 error_free_or_abort(&err); 216 g_assert(!qdict); 217 218 /* Key "help" */ 219 qdict = keyval_parse("help=on", NULL, &help, &error_abort); 220 g_assert_cmpuint(qdict_size(qdict), ==, 1); 221 g_assert_cmpstr(qdict_get_try_str(qdict, "help"), ==, "on"); 222 g_assert(!help); 223 qobject_unref(qdict); 224 225 /* "help" followed by crap, without implied key */ 226 qdict = keyval_parse("help.abc", NULL, &help, &err); 227 error_free_or_abort(&err); 228 g_assert(!qdict); 229 230 /* "help" followed by crap, with implied key */ 231 qdict = keyval_parse("help.abc", "implied", &help, &err); 232 g_assert_cmpuint(qdict_size(qdict), ==, 1); 233 g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "help.abc"); 234 g_assert(!help); 235 qobject_unref(qdict); 236 237 /* "help" with other stuff, without implied key */ 238 qdict = keyval_parse("number=42,help,foo=bar", NULL, &help, &error_abort); 239 g_assert_cmpuint(qdict_size(qdict), ==, 2); 240 g_assert_cmpstr(qdict_get_try_str(qdict, "number"), ==, "42"); 241 g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar"); 242 g_assert(help); 243 qobject_unref(qdict); 244 245 /* "help" with other stuff, with implied key */ 246 qdict = keyval_parse("val,help,foo=bar", "implied", &help, &error_abort); 247 g_assert_cmpuint(qdict_size(qdict), ==, 2); 248 g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "val"); 249 g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar"); 250 g_assert(help); 251 qobject_unref(qdict); 252 } 253 254 static void check_list012(QList *qlist) 255 { 256 static const char *expected[] = { "null", "eins", "zwei" }; 257 int i; 258 QString *qstr; 259 260 g_assert(qlist); 261 for (i = 0; i < ARRAY_SIZE(expected); i++) { 262 qstr = qobject_to(QString, qlist_pop(qlist)); 263 g_assert(qstr); 264 g_assert_cmpstr(qstring_get_str(qstr), ==, expected[i]); 265 qobject_unref(qstr); 266 } 267 g_assert(qlist_empty(qlist)); 268 } 269 270 static void test_keyval_parse_list(void) 271 { 272 Error *err = NULL; 273 QDict *qdict, *sub_qdict; 274 275 /* Root can't be a list */ 276 qdict = keyval_parse("0=1", NULL, NULL, &err); 277 error_free_or_abort(&err); 278 g_assert(!qdict); 279 280 /* List elements need not be in order */ 281 qdict = keyval_parse("list.0=null,list.2=zwei,list.1=eins", NULL, NULL, 282 &error_abort); 283 g_assert_cmpint(qdict_size(qdict), ==, 1); 284 check_list012(qdict_get_qlist(qdict, "list")); 285 qobject_unref(qdict); 286 287 /* Multiple indexes, last one wins */ 288 qdict = keyval_parse("list.1=goner,list.0=null,list.01=eins,list.2=zwei", 289 NULL, NULL, &error_abort); 290 g_assert_cmpint(qdict_size(qdict), ==, 1); 291 check_list012(qdict_get_qlist(qdict, "list")); 292 qobject_unref(qdict); 293 294 /* List at deeper nesting */ 295 qdict = keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei", NULL, 296 NULL, &error_abort); 297 g_assert_cmpint(qdict_size(qdict), ==, 1); 298 sub_qdict = qdict_get_qdict(qdict, "a"); 299 g_assert_cmpint(qdict_size(sub_qdict), ==, 1); 300 check_list012(qdict_get_qlist(sub_qdict, "list")); 301 qobject_unref(qdict); 302 303 /* Inconsistent dotted keys: both list and dictionary */ 304 qdict = keyval_parse("a.b.c=1,a.b.0=2", NULL, NULL, &err); 305 error_free_or_abort(&err); 306 g_assert(!qdict); 307 qdict = keyval_parse("a.0.c=1,a.b.c=2", NULL, NULL, &err); 308 error_free_or_abort(&err); 309 g_assert(!qdict); 310 311 /* Missing list indexes */ 312 qdict = keyval_parse("list.1=lonely", NULL, NULL, &err); 313 error_free_or_abort(&err); 314 g_assert(!qdict); 315 qdict = keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL, NULL, 316 &err); 317 error_free_or_abort(&err); 318 g_assert(!qdict); 319 } 320 321 static void test_keyval_visit_bool(void) 322 { 323 Error *err = NULL; 324 Visitor *v; 325 QDict *qdict; 326 bool b; 327 328 qdict = keyval_parse("bool1=on,bool2=off", NULL, NULL, &error_abort); 329 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 330 qobject_unref(qdict); 331 visit_start_struct(v, NULL, NULL, 0, &error_abort); 332 visit_type_bool(v, "bool1", &b, &error_abort); 333 g_assert(b); 334 visit_type_bool(v, "bool2", &b, &error_abort); 335 g_assert(!b); 336 visit_check_struct(v, &error_abort); 337 visit_end_struct(v, NULL); 338 visit_free(v); 339 340 qdict = keyval_parse("bool1=offer", NULL, NULL, &error_abort); 341 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 342 qobject_unref(qdict); 343 visit_start_struct(v, NULL, NULL, 0, &error_abort); 344 visit_type_bool(v, "bool1", &b, &err); 345 error_free_or_abort(&err); 346 visit_end_struct(v, NULL); 347 visit_free(v); 348 } 349 350 static void test_keyval_visit_number(void) 351 { 352 Error *err = NULL; 353 Visitor *v; 354 QDict *qdict; 355 uint64_t u; 356 357 /* Lower limit zero */ 358 qdict = keyval_parse("number1=0", NULL, NULL, &error_abort); 359 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 360 qobject_unref(qdict); 361 visit_start_struct(v, NULL, NULL, 0, &error_abort); 362 visit_type_uint64(v, "number1", &u, &error_abort); 363 g_assert_cmpuint(u, ==, 0); 364 visit_check_struct(v, &error_abort); 365 visit_end_struct(v, NULL); 366 visit_free(v); 367 368 /* Upper limit 2^64-1 */ 369 qdict = keyval_parse("number1=18446744073709551615,number2=-1", NULL, 370 NULL, &error_abort); 371 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 372 qobject_unref(qdict); 373 visit_start_struct(v, NULL, NULL, 0, &error_abort); 374 visit_type_uint64(v, "number1", &u, &error_abort); 375 g_assert_cmphex(u, ==, UINT64_MAX); 376 visit_type_uint64(v, "number2", &u, &error_abort); 377 g_assert_cmphex(u, ==, UINT64_MAX); 378 visit_check_struct(v, &error_abort); 379 visit_end_struct(v, NULL); 380 visit_free(v); 381 382 /* Above upper limit */ 383 qdict = keyval_parse("number1=18446744073709551616", NULL, NULL, 384 &error_abort); 385 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 386 qobject_unref(qdict); 387 visit_start_struct(v, NULL, NULL, 0, &error_abort); 388 visit_type_uint64(v, "number1", &u, &err); 389 error_free_or_abort(&err); 390 visit_end_struct(v, NULL); 391 visit_free(v); 392 393 /* Below lower limit */ 394 qdict = keyval_parse("number1=-18446744073709551616", NULL, NULL, 395 &error_abort); 396 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 397 qobject_unref(qdict); 398 visit_start_struct(v, NULL, NULL, 0, &error_abort); 399 visit_type_uint64(v, "number1", &u, &err); 400 error_free_or_abort(&err); 401 visit_end_struct(v, NULL); 402 visit_free(v); 403 404 /* Hex and octal */ 405 qdict = keyval_parse("number1=0x2a,number2=052", NULL, NULL, &error_abort); 406 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 407 qobject_unref(qdict); 408 visit_start_struct(v, NULL, NULL, 0, &error_abort); 409 visit_type_uint64(v, "number1", &u, &error_abort); 410 g_assert_cmpuint(u, ==, 42); 411 visit_type_uint64(v, "number2", &u, &error_abort); 412 g_assert_cmpuint(u, ==, 42); 413 visit_check_struct(v, &error_abort); 414 visit_end_struct(v, NULL); 415 visit_free(v); 416 417 /* Trailing crap */ 418 qdict = keyval_parse("number1=3.14,number2=08", NULL, NULL, &error_abort); 419 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 420 qobject_unref(qdict); 421 visit_start_struct(v, NULL, NULL, 0, &error_abort); 422 visit_type_uint64(v, "number1", &u, &err); 423 error_free_or_abort(&err); 424 visit_type_uint64(v, "number2", &u, &err); 425 error_free_or_abort(&err); 426 visit_end_struct(v, NULL); 427 visit_free(v); 428 } 429 430 static void test_keyval_visit_size(void) 431 { 432 Error *err = NULL; 433 Visitor *v; 434 QDict *qdict; 435 uint64_t sz; 436 437 /* Lower limit zero */ 438 qdict = keyval_parse("sz1=0", NULL, NULL, &error_abort); 439 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 440 qobject_unref(qdict); 441 visit_start_struct(v, NULL, NULL, 0, &error_abort); 442 visit_type_size(v, "sz1", &sz, &error_abort); 443 g_assert_cmpuint(sz, ==, 0); 444 visit_check_struct(v, &error_abort); 445 visit_end_struct(v, NULL); 446 visit_free(v); 447 448 /* Note: full 64 bits of precision */ 449 450 /* Around double limit of precision: 2^53-1, 2^53, 2^53+1 */ 451 qdict = keyval_parse("sz1=9007199254740991," 452 "sz2=9007199254740992," 453 "sz3=9007199254740993", 454 NULL, NULL, &error_abort); 455 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 456 qobject_unref(qdict); 457 visit_start_struct(v, NULL, NULL, 0, &error_abort); 458 visit_type_size(v, "sz1", &sz, &error_abort); 459 g_assert_cmphex(sz, ==, 0x1fffffffffffff); 460 visit_type_size(v, "sz2", &sz, &error_abort); 461 g_assert_cmphex(sz, ==, 0x20000000000000); 462 visit_type_size(v, "sz3", &sz, &error_abort); 463 g_assert_cmphex(sz, ==, 0x20000000000001); 464 visit_check_struct(v, &error_abort); 465 visit_end_struct(v, NULL); 466 visit_free(v); 467 468 /* Close to signed integer limit 2^63 */ 469 qdict = keyval_parse("sz1=9223372036854775807," /* 7fffffffffffffff */ 470 "sz2=9223372036854775808," /* 8000000000000000 */ 471 "sz3=9223372036854775809", /* 8000000000000001 */ 472 NULL, NULL, &error_abort); 473 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 474 qobject_unref(qdict); 475 visit_start_struct(v, NULL, NULL, 0, &error_abort); 476 visit_type_size(v, "sz1", &sz, &error_abort); 477 g_assert_cmphex(sz, ==, 0x7fffffffffffffff); 478 visit_type_size(v, "sz2", &sz, &error_abort); 479 g_assert_cmphex(sz, ==, 0x8000000000000000); 480 visit_type_size(v, "sz3", &sz, &error_abort); 481 g_assert_cmphex(sz, ==, 0x8000000000000001); 482 visit_check_struct(v, &error_abort); 483 visit_end_struct(v, NULL); 484 visit_free(v); 485 486 /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ 487 qdict = keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */ 488 "sz2=18446744073709550591", /* fffffffffffffbff */ 489 NULL, NULL, &error_abort); 490 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 491 qobject_unref(qdict); 492 visit_start_struct(v, NULL, NULL, 0, &error_abort); 493 visit_type_size(v, "sz1", &sz, &error_abort); 494 g_assert_cmphex(sz, ==, 0xfffffffffffff800); 495 visit_type_size(v, "sz2", &sz, &error_abort); 496 g_assert_cmphex(sz, ==, 0xfffffffffffffbff); 497 visit_check_struct(v, &error_abort); 498 visit_end_struct(v, NULL); 499 visit_free(v); 500 501 /* Actual limit 2^64-1*/ 502 qdict = keyval_parse("sz1=18446744073709551615", /* ffffffffffffffff */ 503 NULL, NULL, &error_abort); 504 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 505 qobject_unref(qdict); 506 visit_start_struct(v, NULL, NULL, 0, &error_abort); 507 visit_type_size(v, "sz1", &sz, &error_abort); 508 g_assert_cmphex(sz, ==, 0xffffffffffffffff); 509 visit_check_struct(v, &error_abort); 510 visit_end_struct(v, NULL); 511 visit_free(v); 512 513 /* Beyond limits */ 514 qdict = keyval_parse("sz1=-1," 515 "sz2=18446744073709551616", /* 2^64 */ 516 NULL, NULL, &error_abort); 517 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 518 qobject_unref(qdict); 519 visit_start_struct(v, NULL, NULL, 0, &error_abort); 520 visit_type_size(v, "sz1", &sz, &err); 521 error_free_or_abort(&err); 522 visit_type_size(v, "sz2", &sz, &err); 523 error_free_or_abort(&err); 524 visit_end_struct(v, NULL); 525 visit_free(v); 526 527 /* Suffixes */ 528 qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T", 529 NULL, NULL, &error_abort); 530 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 531 qobject_unref(qdict); 532 visit_start_struct(v, NULL, NULL, 0, &error_abort); 533 visit_type_size(v, "sz1", &sz, &error_abort); 534 g_assert_cmpuint(sz, ==, 8); 535 visit_type_size(v, "sz2", &sz, &error_abort); 536 g_assert_cmpuint(sz, ==, 1536); 537 visit_type_size(v, "sz3", &sz, &error_abort); 538 g_assert_cmphex(sz, ==, 2 * MiB); 539 visit_type_size(v, "sz4", &sz, &error_abort); 540 g_assert_cmphex(sz, ==, GiB / 10); 541 visit_type_size(v, "sz5", &sz, &error_abort); 542 g_assert_cmphex(sz, ==, 16777215ULL * TiB); 543 visit_check_struct(v, &error_abort); 544 visit_end_struct(v, NULL); 545 visit_free(v); 546 547 /* Beyond limit with suffix */ 548 qdict = keyval_parse("sz1=16777216T", NULL, NULL, &error_abort); 549 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 550 qobject_unref(qdict); 551 visit_start_struct(v, NULL, NULL, 0, &error_abort); 552 visit_type_size(v, "sz1", &sz, &err); 553 error_free_or_abort(&err); 554 visit_end_struct(v, NULL); 555 visit_free(v); 556 557 /* Trailing crap */ 558 qdict = keyval_parse("sz1=0Z,sz2=16Gi", NULL, NULL, &error_abort); 559 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 560 qobject_unref(qdict); 561 visit_start_struct(v, NULL, NULL, 0, &error_abort); 562 visit_type_size(v, "sz1", &sz, &err); 563 error_free_or_abort(&err); 564 visit_type_size(v, "sz2", &sz, &err); 565 error_free_or_abort(&err); 566 visit_end_struct(v, NULL); 567 visit_free(v); 568 } 569 570 static void test_keyval_visit_dict(void) 571 { 572 Error *err = NULL; 573 Visitor *v; 574 QDict *qdict; 575 int64_t i; 576 577 qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, NULL, &error_abort); 578 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 579 qobject_unref(qdict); 580 visit_start_struct(v, NULL, NULL, 0, &error_abort); 581 visit_start_struct(v, "a", NULL, 0, &error_abort); 582 visit_start_struct(v, "b", NULL, 0, &error_abort); 583 visit_type_int(v, "c", &i, &error_abort); 584 g_assert_cmpint(i, ==, 2); 585 visit_check_struct(v, &error_abort); 586 visit_end_struct(v, NULL); 587 visit_check_struct(v, &error_abort); 588 visit_end_struct(v, NULL); 589 visit_type_int(v, "d", &i, &error_abort); 590 g_assert_cmpint(i, ==, 3); 591 visit_check_struct(v, &error_abort); 592 visit_end_struct(v, NULL); 593 visit_free(v); 594 595 qdict = keyval_parse("a.b=", NULL, NULL, &error_abort); 596 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 597 qobject_unref(qdict); 598 visit_start_struct(v, NULL, NULL, 0, &error_abort); 599 visit_start_struct(v, "a", NULL, 0, &error_abort); 600 visit_type_int(v, "c", &i, &err); /* a.c missing */ 601 error_free_or_abort(&err); 602 visit_check_struct(v, &err); 603 error_free_or_abort(&err); /* a.b unexpected */ 604 visit_end_struct(v, NULL); 605 visit_check_struct(v, &error_abort); 606 visit_end_struct(v, NULL); 607 visit_free(v); 608 } 609 610 static void test_keyval_visit_list(void) 611 { 612 Error *err = NULL; 613 Visitor *v; 614 QDict *qdict; 615 char *s; 616 617 qdict = keyval_parse("a.0=,a.1=I,a.2.0=II", NULL, NULL, &error_abort); 618 /* TODO empty list */ 619 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 620 qobject_unref(qdict); 621 visit_start_struct(v, NULL, NULL, 0, &error_abort); 622 visit_start_list(v, "a", NULL, 0, &error_abort); 623 visit_type_str(v, NULL, &s, &error_abort); 624 g_assert_cmpstr(s, ==, ""); 625 g_free(s); 626 visit_type_str(v, NULL, &s, &error_abort); 627 g_assert_cmpstr(s, ==, "I"); 628 g_free(s); 629 visit_start_list(v, NULL, NULL, 0, &error_abort); 630 visit_type_str(v, NULL, &s, &error_abort); 631 g_assert_cmpstr(s, ==, "II"); 632 g_free(s); 633 visit_check_list(v, &error_abort); 634 visit_end_list(v, NULL); 635 visit_check_list(v, &error_abort); 636 visit_end_list(v, NULL); 637 visit_check_struct(v, &error_abort); 638 visit_end_struct(v, NULL); 639 visit_free(v); 640 641 qdict = keyval_parse("a.0=,b.0.0=head", NULL, NULL, &error_abort); 642 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 643 qobject_unref(qdict); 644 visit_start_struct(v, NULL, NULL, 0, &error_abort); 645 visit_start_list(v, "a", NULL, 0, &error_abort); 646 visit_check_list(v, &err); /* a[0] unexpected */ 647 error_free_or_abort(&err); 648 visit_end_list(v, NULL); 649 visit_start_list(v, "b", NULL, 0, &error_abort); 650 visit_start_list(v, NULL, NULL, 0, &error_abort); 651 visit_type_str(v, NULL, &s, &error_abort); 652 g_assert_cmpstr(s, ==, "head"); 653 g_free(s); 654 visit_type_str(v, NULL, &s, &err); /* b[0][1] missing */ 655 error_free_or_abort(&err); 656 visit_end_list(v, NULL); 657 visit_end_list(v, NULL); 658 visit_check_struct(v, &error_abort); 659 visit_end_struct(v, NULL); 660 visit_free(v); 661 } 662 663 static void test_keyval_visit_optional(void) 664 { 665 Visitor *v; 666 QDict *qdict; 667 bool present; 668 int64_t i; 669 670 qdict = keyval_parse("a.b=1", NULL, NULL, &error_abort); 671 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 672 qobject_unref(qdict); 673 visit_start_struct(v, NULL, NULL, 0, &error_abort); 674 visit_optional(v, "b", &present); 675 g_assert(!present); /* b missing */ 676 visit_optional(v, "a", &present); 677 g_assert(present); /* a present */ 678 visit_start_struct(v, "a", NULL, 0, &error_abort); 679 visit_optional(v, "b", &present); 680 g_assert(present); /* a.b present */ 681 visit_type_int(v, "b", &i, &error_abort); 682 g_assert_cmpint(i, ==, 1); 683 visit_optional(v, "a", &present); 684 g_assert(!present); /* a.a missing */ 685 visit_check_struct(v, &error_abort); 686 visit_end_struct(v, NULL); 687 visit_check_struct(v, &error_abort); 688 visit_end_struct(v, NULL); 689 visit_free(v); 690 } 691 692 static void test_keyval_visit_alternate(void) 693 { 694 Error *err = NULL; 695 Visitor *v; 696 QDict *qdict; 697 AltStrObj *aso; 698 AltNumEnum *ane; 699 AltEnumBool *aeb; 700 701 /* 702 * Can't do scalar alternate variants other than string. You get 703 * the string variant if there is one, else an error. 704 * TODO make it work for unambiguous cases like AltEnumBool below 705 */ 706 qdict = keyval_parse("a=1,b=2,c=on", NULL, NULL, &error_abort); 707 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 708 qobject_unref(qdict); 709 visit_start_struct(v, NULL, NULL, 0, &error_abort); 710 visit_type_AltStrObj(v, "a", &aso, &error_abort); 711 g_assert_cmpint(aso->type, ==, QTYPE_QSTRING); 712 g_assert_cmpstr(aso->u.s, ==, "1"); 713 qapi_free_AltStrObj(aso); 714 visit_type_AltNumEnum(v, "b", &ane, &err); 715 error_free_or_abort(&err); 716 visit_type_AltEnumBool(v, "c", &aeb, &err); 717 error_free_or_abort(&err); 718 visit_end_struct(v, NULL); 719 visit_free(v); 720 } 721 722 static void test_keyval_visit_any(void) 723 { 724 Visitor *v; 725 QDict *qdict; 726 QObject *any; 727 QList *qlist; 728 QString *qstr; 729 730 qdict = keyval_parse("a.0=null,a.1=1", NULL, NULL, &error_abort); 731 v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 732 qobject_unref(qdict); 733 visit_start_struct(v, NULL, NULL, 0, &error_abort); 734 visit_type_any(v, "a", &any, &error_abort); 735 qlist = qobject_to(QList, any); 736 g_assert(qlist); 737 qstr = qobject_to(QString, qlist_pop(qlist)); 738 g_assert_cmpstr(qstring_get_str(qstr), ==, "null"); 739 qobject_unref(qstr); 740 qstr = qobject_to(QString, qlist_pop(qlist)); 741 g_assert_cmpstr(qstring_get_str(qstr), ==, "1"); 742 g_assert(qlist_empty(qlist)); 743 qobject_unref(qstr); 744 qobject_unref(any); 745 visit_check_struct(v, &error_abort); 746 visit_end_struct(v, NULL); 747 visit_free(v); 748 } 749 750 static void test_keyval_merge_dict(void) 751 { 752 QDict *first = keyval_parse("opt1=abc,opt2.sub1=def,opt2.sub2=ghi,opt3=xyz", 753 NULL, NULL, &error_abort); 754 QDict *second = keyval_parse("opt1=ABC,opt2.sub2=GHI,opt2.sub3=JKL", 755 NULL, NULL, &error_abort); 756 QDict *combined = keyval_parse("opt1=ABC,opt2.sub1=def,opt2.sub2=GHI,opt2.sub3=JKL,opt3=xyz", 757 NULL, NULL, &error_abort); 758 Error *err = NULL; 759 760 keyval_merge(first, second, &err); 761 g_assert(!err); 762 g_assert(qobject_is_equal(QOBJECT(combined), QOBJECT(first))); 763 qobject_unref(first); 764 qobject_unref(second); 765 qobject_unref(combined); 766 } 767 768 static void test_keyval_merge_list(void) 769 { 770 QDict *first = keyval_parse("opt1.0=abc,opt2.0=xyz", 771 NULL, NULL, &error_abort); 772 QDict *second = keyval_parse("opt1.0=def", 773 NULL, NULL, &error_abort); 774 QDict *combined = keyval_parse("opt1.0=abc,opt1.1=def,opt2.0=xyz", 775 NULL, NULL, &error_abort); 776 Error *err = NULL; 777 778 keyval_merge(first, second, &err); 779 g_assert(!err); 780 g_assert(qobject_is_equal(QOBJECT(combined), QOBJECT(first))); 781 qobject_unref(first); 782 qobject_unref(second); 783 qobject_unref(combined); 784 } 785 786 static void test_keyval_merge_conflict(void) 787 { 788 QDict *first = keyval_parse("opt2=ABC", 789 NULL, NULL, &error_abort); 790 QDict *second = keyval_parse("opt2.sub1=def,opt2.sub2=ghi", 791 NULL, NULL, &error_abort); 792 QDict *third = qdict_clone_shallow(first); 793 Error *err = NULL; 794 795 keyval_merge(first, second, &err); 796 error_free_or_abort(&err); 797 keyval_merge(second, third, &err); 798 error_free_or_abort(&err); 799 800 qobject_unref(first); 801 qobject_unref(second); 802 qobject_unref(third); 803 } 804 805 int main(int argc, char *argv[]) 806 { 807 g_test_init(&argc, &argv, NULL); 808 g_test_add_func("/keyval/keyval_parse", test_keyval_parse); 809 g_test_add_func("/keyval/keyval_parse/list", test_keyval_parse_list); 810 g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool); 811 g_test_add_func("/keyval/visit/number", test_keyval_visit_number); 812 g_test_add_func("/keyval/visit/size", test_keyval_visit_size); 813 g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict); 814 g_test_add_func("/keyval/visit/list", test_keyval_visit_list); 815 g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional); 816 g_test_add_func("/keyval/visit/alternate", test_keyval_visit_alternate); 817 g_test_add_func("/keyval/visit/any", test_keyval_visit_any); 818 g_test_add_func("/keyval/merge/dict", test_keyval_merge_dict); 819 g_test_add_func("/keyval/merge/list", test_keyval_merge_list); 820 g_test_add_func("/keyval/merge/conflict", test_keyval_merge_conflict); 821 g_test_run(); 822 return 0; 823 } 824