1d454dbe0SMarkus Armbruster /* 2d454dbe0SMarkus Armbruster * Unit tests for parsing of KEY=VALUE,... strings 3d454dbe0SMarkus Armbruster * 4d454dbe0SMarkus Armbruster * Copyright (C) 2017 Red Hat Inc. 5d454dbe0SMarkus Armbruster * 6d454dbe0SMarkus Armbruster * Authors: 7d454dbe0SMarkus Armbruster * Markus Armbruster <armbru@redhat.com>, 8d454dbe0SMarkus Armbruster * 9d454dbe0SMarkus Armbruster * This work is licensed under the terms of the GNU GPL, version 2 or later. 10d454dbe0SMarkus Armbruster * See the COPYING file in the top-level directory. 11d454dbe0SMarkus Armbruster */ 12d454dbe0SMarkus Armbruster 13d454dbe0SMarkus Armbruster #include "qemu/osdep.h" 14d23b6caaSPhilippe Mathieu-Daudé #include "qemu/units.h" 15d454dbe0SMarkus Armbruster #include "qapi/error.h" 16452fcdbcSMarkus Armbruster #include "qapi/qmp/qdict.h" 1747e6b297SMarkus Armbruster #include "qapi/qmp/qlist.h" 180b2c1beeSMarkus Armbruster #include "qapi/qmp/qstring.h" 199e3943f8SMarkus Armbruster #include "qapi/qobject-input-visitor.h" 20599c156bSMarkus Armbruster #include "test-qapi-visit.h" 219e3943f8SMarkus Armbruster #include "qemu/cutils.h" 22*9ca9c893SMarc-André Lureau #include "qemu/keyval.h" 23d454dbe0SMarkus Armbruster 24d454dbe0SMarkus Armbruster static void test_keyval_parse(void) 25d454dbe0SMarkus Armbruster { 26d454dbe0SMarkus Armbruster Error *err = NULL; 27d454dbe0SMarkus Armbruster QDict *qdict, *sub_qdict; 28d454dbe0SMarkus Armbruster char long_key[129]; 29d454dbe0SMarkus Armbruster char *params; 308bf12c4fSKevin Wolf bool help; 31d454dbe0SMarkus Armbruster 32d454dbe0SMarkus Armbruster /* Nothing */ 338bf12c4fSKevin Wolf qdict = keyval_parse("", NULL, NULL, &error_abort); 34d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 0); 35cb3e7f08SMarc-André Lureau qobject_unref(qdict); 36d454dbe0SMarkus Armbruster 37d454dbe0SMarkus Armbruster /* Empty key (qemu_opts_parse() accepts this) */ 388bf12c4fSKevin Wolf qdict = keyval_parse("=val", NULL, NULL, &err); 39d454dbe0SMarkus Armbruster error_free_or_abort(&err); 40d454dbe0SMarkus Armbruster g_assert(!qdict); 41d454dbe0SMarkus Armbruster 42d454dbe0SMarkus Armbruster /* Empty key fragment */ 438bf12c4fSKevin Wolf qdict = keyval_parse(".", NULL, NULL, &err); 44d454dbe0SMarkus Armbruster error_free_or_abort(&err); 45d454dbe0SMarkus Armbruster g_assert(!qdict); 468bf12c4fSKevin Wolf qdict = keyval_parse("key.", NULL, NULL, &err); 47d454dbe0SMarkus Armbruster error_free_or_abort(&err); 48d454dbe0SMarkus Armbruster g_assert(!qdict); 49d454dbe0SMarkus Armbruster 50f7400483SMarkus Armbruster /* Invalid non-empty key (qemu_opts_parse() doesn't care) */ 518bf12c4fSKevin Wolf qdict = keyval_parse("7up=val", NULL, NULL, &err); 52f7400483SMarkus Armbruster error_free_or_abort(&err); 53f7400483SMarkus Armbruster g_assert(!qdict); 54f7400483SMarkus Armbruster 55d454dbe0SMarkus Armbruster /* Overlong key */ 56d454dbe0SMarkus Armbruster memset(long_key, 'a', 127); 57d454dbe0SMarkus Armbruster long_key[127] = 'z'; 58d454dbe0SMarkus Armbruster long_key[128] = 0; 59d454dbe0SMarkus Armbruster params = g_strdup_printf("k.%s=v", long_key); 608bf12c4fSKevin Wolf qdict = keyval_parse(params + 2, NULL, NULL, &err); 61d454dbe0SMarkus Armbruster error_free_or_abort(&err); 62d454dbe0SMarkus Armbruster g_assert(!qdict); 63d454dbe0SMarkus Armbruster 64d454dbe0SMarkus Armbruster /* Overlong key fragment */ 658bf12c4fSKevin Wolf qdict = keyval_parse(params, NULL, NULL, &err); 66d454dbe0SMarkus Armbruster error_free_or_abort(&err); 67d454dbe0SMarkus Armbruster g_assert(!qdict); 68d454dbe0SMarkus Armbruster g_free(params); 69d454dbe0SMarkus Armbruster 70d454dbe0SMarkus Armbruster /* Long key (qemu_opts_parse() accepts and truncates silently) */ 71d454dbe0SMarkus Armbruster params = g_strdup_printf("k.%s=v", long_key + 1); 728bf12c4fSKevin Wolf qdict = keyval_parse(params + 2, NULL, NULL, &error_abort); 73d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 74d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, long_key + 1), ==, "v"); 75cb3e7f08SMarc-André Lureau qobject_unref(qdict); 76d454dbe0SMarkus Armbruster 77d454dbe0SMarkus Armbruster /* Long key fragment */ 788bf12c4fSKevin Wolf qdict = keyval_parse(params, NULL, NULL, &error_abort); 79d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 80d454dbe0SMarkus Armbruster sub_qdict = qdict_get_qdict(qdict, "k"); 81d454dbe0SMarkus Armbruster g_assert(sub_qdict); 82d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 83d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(sub_qdict, long_key + 1), ==, "v"); 84cb3e7f08SMarc-André Lureau qobject_unref(qdict); 85d454dbe0SMarkus Armbruster g_free(params); 86d454dbe0SMarkus Armbruster 87f7400483SMarkus Armbruster /* Crap after valid key */ 888bf12c4fSKevin Wolf qdict = keyval_parse("key[0]=val", NULL, NULL, &err); 89f7400483SMarkus Armbruster error_free_or_abort(&err); 90f7400483SMarkus Armbruster g_assert(!qdict); 91f7400483SMarkus Armbruster 92d454dbe0SMarkus Armbruster /* Multiple keys, last one wins */ 938bf12c4fSKevin Wolf qdict = keyval_parse("a=1,b=2,,x,a=3", NULL, NULL, &error_abort); 94d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 2); 95d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "a"), ==, "3"); 96d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "b"), ==, "2,x"); 97cb3e7f08SMarc-André Lureau qobject_unref(qdict); 98d454dbe0SMarkus Armbruster 99d454dbe0SMarkus Armbruster /* Even when it doesn't in qemu_opts_parse() */ 1008bf12c4fSKevin Wolf qdict = keyval_parse("id=foo,id=bar", NULL, NULL, &error_abort); 101d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 102d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "bar"); 103cb3e7f08SMarc-André Lureau qobject_unref(qdict); 104d454dbe0SMarkus Armbruster 105d454dbe0SMarkus Armbruster /* Dotted keys */ 1068bf12c4fSKevin Wolf qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, NULL, &error_abort); 107d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 2); 108d454dbe0SMarkus Armbruster sub_qdict = qdict_get_qdict(qdict, "a"); 109d454dbe0SMarkus Armbruster g_assert(sub_qdict); 110d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 111d454dbe0SMarkus Armbruster sub_qdict = qdict_get_qdict(sub_qdict, "b"); 112d454dbe0SMarkus Armbruster g_assert(sub_qdict); 113d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 114d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(sub_qdict, "c"), ==, "2"); 115d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "d"), ==, "3"); 116cb3e7f08SMarc-André Lureau qobject_unref(qdict); 117d454dbe0SMarkus Armbruster 118d454dbe0SMarkus Armbruster /* Inconsistent dotted keys */ 1198bf12c4fSKevin Wolf qdict = keyval_parse("a.b=1,a=2", NULL, NULL, &err); 120d454dbe0SMarkus Armbruster error_free_or_abort(&err); 121d454dbe0SMarkus Armbruster g_assert(!qdict); 1228bf12c4fSKevin Wolf qdict = keyval_parse("a.b=1,a.b.c=2", NULL, NULL, &err); 123d454dbe0SMarkus Armbruster error_free_or_abort(&err); 124d454dbe0SMarkus Armbruster g_assert(!qdict); 125d454dbe0SMarkus Armbruster 126d454dbe0SMarkus Armbruster /* Trailing comma is ignored */ 1278bf12c4fSKevin Wolf qdict = keyval_parse("x=y,", NULL, NULL, &error_abort); 128d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 129d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, "y"); 130cb3e7f08SMarc-André Lureau qobject_unref(qdict); 131d454dbe0SMarkus Armbruster 132d454dbe0SMarkus Armbruster /* Except when it isn't */ 1338bf12c4fSKevin Wolf qdict = keyval_parse(",", NULL, NULL, &err); 134d454dbe0SMarkus Armbruster error_free_or_abort(&err); 135d454dbe0SMarkus Armbruster g_assert(!qdict); 136d454dbe0SMarkus Armbruster 137d454dbe0SMarkus Armbruster /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */ 1388bf12c4fSKevin Wolf qdict = keyval_parse("x=,,id=bar", NULL, NULL, &error_abort); 139d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 140d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, ",id=bar"); 141cb3e7f08SMarc-André Lureau qobject_unref(qdict); 142d454dbe0SMarkus Armbruster 143d454dbe0SMarkus Armbruster /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */ 1448bf12c4fSKevin Wolf qdict = keyval_parse("id=666", NULL, NULL, &error_abort); 145d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 146d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "666"); 147cb3e7f08SMarc-André Lureau qobject_unref(qdict); 148d454dbe0SMarkus Armbruster 149d454dbe0SMarkus Armbruster /* Implied value not supported (unlike qemu_opts_parse()) */ 1508bf12c4fSKevin Wolf qdict = keyval_parse("an,noaus,noaus=", NULL, NULL, &err); 151d454dbe0SMarkus Armbruster error_free_or_abort(&err); 152d454dbe0SMarkus Armbruster g_assert(!qdict); 153d454dbe0SMarkus Armbruster 154d454dbe0SMarkus Armbruster /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */ 1558bf12c4fSKevin Wolf qdict = keyval_parse("no", NULL, NULL, &err); 156d454dbe0SMarkus Armbruster error_free_or_abort(&err); 157d454dbe0SMarkus Armbruster g_assert(!qdict); 158d454dbe0SMarkus Armbruster 159d454dbe0SMarkus Armbruster /* Implied key */ 1608bf12c4fSKevin Wolf qdict = keyval_parse("an,aus=off,noaus=", "implied", NULL, &error_abort); 161d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 3); 162d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "an"); 163d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "aus"), ==, "off"); 164d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "noaus"), ==, ""); 165cb3e7f08SMarc-André Lureau qobject_unref(qdict); 166d454dbe0SMarkus Armbruster 167d454dbe0SMarkus Armbruster /* Implied dotted key */ 1688bf12c4fSKevin Wolf qdict = keyval_parse("val", "eins.zwei", NULL, &error_abort); 169d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 170d454dbe0SMarkus Armbruster sub_qdict = qdict_get_qdict(qdict, "eins"); 171d454dbe0SMarkus Armbruster g_assert(sub_qdict); 172d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 173d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(sub_qdict, "zwei"), ==, "val"); 174cb3e7f08SMarc-André Lureau qobject_unref(qdict); 175d454dbe0SMarkus Armbruster 176d454dbe0SMarkus Armbruster /* Implied key with empty value (qemu_opts_parse() accepts this) */ 1778bf12c4fSKevin Wolf qdict = keyval_parse(",", "implied", NULL, &err); 178d454dbe0SMarkus Armbruster error_free_or_abort(&err); 179d454dbe0SMarkus Armbruster g_assert(!qdict); 180d454dbe0SMarkus Armbruster 181d454dbe0SMarkus Armbruster /* Likewise (qemu_opts_parse(): implied key with comma value) */ 1828bf12c4fSKevin Wolf qdict = keyval_parse(",,,a=1", "implied", NULL, &err); 183d454dbe0SMarkus Armbruster error_free_or_abort(&err); 184d454dbe0SMarkus Armbruster g_assert(!qdict); 185d454dbe0SMarkus Armbruster 186ce40cbf1SMarkus Armbruster /* Implied key's value can't have comma (qemu_opts_parse(): it can) */ 1878bf12c4fSKevin Wolf qdict = keyval_parse("val,,ue", "implied", NULL, &err); 1887051ae6cSMarkus Armbruster error_free_or_abort(&err); 1897051ae6cSMarkus Armbruster g_assert(!qdict); 190ce40cbf1SMarkus Armbruster 191d454dbe0SMarkus Armbruster /* Empty key is not an implied key */ 1928bf12c4fSKevin Wolf qdict = keyval_parse("=val", "implied", NULL, &err); 193d454dbe0SMarkus Armbruster error_free_or_abort(&err); 194d454dbe0SMarkus Armbruster g_assert(!qdict); 1958bf12c4fSKevin Wolf 1968bf12c4fSKevin Wolf /* "help" by itself, without implied key */ 1978bf12c4fSKevin Wolf qdict = keyval_parse("help", NULL, &help, &error_abort); 1988bf12c4fSKevin Wolf g_assert_cmpuint(qdict_size(qdict), ==, 0); 1998bf12c4fSKevin Wolf g_assert(help); 2008bf12c4fSKevin Wolf qobject_unref(qdict); 2018bf12c4fSKevin Wolf 2028bf12c4fSKevin Wolf /* "help" by itself, with implied key */ 2038bf12c4fSKevin Wolf qdict = keyval_parse("help", "implied", &help, &error_abort); 2048bf12c4fSKevin Wolf g_assert_cmpuint(qdict_size(qdict), ==, 0); 2058bf12c4fSKevin Wolf g_assert(help); 2068bf12c4fSKevin Wolf qobject_unref(qdict); 2078bf12c4fSKevin Wolf 2088bf12c4fSKevin Wolf /* "help" when no help is available, without implied key */ 2098bf12c4fSKevin Wolf qdict = keyval_parse("help", NULL, NULL, &err); 2108bf12c4fSKevin Wolf error_free_or_abort(&err); 2118bf12c4fSKevin Wolf g_assert(!qdict); 2128bf12c4fSKevin Wolf 2138bf12c4fSKevin Wolf /* "help" when no help is available, with implied key */ 2148bf12c4fSKevin Wolf qdict = keyval_parse("help", "implied", NULL, &err); 2158bf12c4fSKevin Wolf error_free_or_abort(&err); 2168bf12c4fSKevin Wolf g_assert(!qdict); 2178bf12c4fSKevin Wolf 2188bf12c4fSKevin Wolf /* Key "help" */ 2198bf12c4fSKevin Wolf qdict = keyval_parse("help=on", NULL, &help, &error_abort); 2208bf12c4fSKevin Wolf g_assert_cmpuint(qdict_size(qdict), ==, 1); 2218bf12c4fSKevin Wolf g_assert_cmpstr(qdict_get_try_str(qdict, "help"), ==, "on"); 2228bf12c4fSKevin Wolf g_assert(!help); 2238bf12c4fSKevin Wolf qobject_unref(qdict); 2248bf12c4fSKevin Wolf 2258bf12c4fSKevin Wolf /* "help" followed by crap, without implied key */ 2268bf12c4fSKevin Wolf qdict = keyval_parse("help.abc", NULL, &help, &err); 2278bf12c4fSKevin Wolf error_free_or_abort(&err); 2288bf12c4fSKevin Wolf g_assert(!qdict); 2298bf12c4fSKevin Wolf 2308bf12c4fSKevin Wolf /* "help" followed by crap, with implied key */ 2318bf12c4fSKevin Wolf qdict = keyval_parse("help.abc", "implied", &help, &err); 2328bf12c4fSKevin Wolf g_assert_cmpuint(qdict_size(qdict), ==, 1); 2338bf12c4fSKevin Wolf g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "help.abc"); 2348bf12c4fSKevin Wolf g_assert(!help); 2358bf12c4fSKevin Wolf qobject_unref(qdict); 2368bf12c4fSKevin Wolf 2378bf12c4fSKevin Wolf /* "help" with other stuff, without implied key */ 2388bf12c4fSKevin Wolf qdict = keyval_parse("number=42,help,foo=bar", NULL, &help, &error_abort); 2398bf12c4fSKevin Wolf g_assert_cmpuint(qdict_size(qdict), ==, 2); 2408bf12c4fSKevin Wolf g_assert_cmpstr(qdict_get_try_str(qdict, "number"), ==, "42"); 2418bf12c4fSKevin Wolf g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar"); 2428bf12c4fSKevin Wolf g_assert(help); 2438bf12c4fSKevin Wolf qobject_unref(qdict); 2448bf12c4fSKevin Wolf 2458bf12c4fSKevin Wolf /* "help" with other stuff, with implied key */ 2468bf12c4fSKevin Wolf qdict = keyval_parse("val,help,foo=bar", "implied", &help, &error_abort); 2478bf12c4fSKevin Wolf g_assert_cmpuint(qdict_size(qdict), ==, 2); 2488bf12c4fSKevin Wolf g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "val"); 2498bf12c4fSKevin Wolf g_assert_cmpstr(qdict_get_try_str(qdict, "foo"), ==, "bar"); 2508bf12c4fSKevin Wolf g_assert(help); 2518bf12c4fSKevin Wolf qobject_unref(qdict); 252d454dbe0SMarkus Armbruster } 253d454dbe0SMarkus Armbruster 2540b2c1beeSMarkus Armbruster static void check_list012(QList *qlist) 2550b2c1beeSMarkus Armbruster { 2560b2c1beeSMarkus Armbruster static const char *expected[] = { "null", "eins", "zwei" }; 2570b2c1beeSMarkus Armbruster int i; 2580b2c1beeSMarkus Armbruster QString *qstr; 2590b2c1beeSMarkus Armbruster 2600b2c1beeSMarkus Armbruster g_assert(qlist); 2610b2c1beeSMarkus Armbruster for (i = 0; i < ARRAY_SIZE(expected); i++) { 2627dc847ebSMax Reitz qstr = qobject_to(QString, qlist_pop(qlist)); 2630b2c1beeSMarkus Armbruster g_assert(qstr); 2640b2c1beeSMarkus Armbruster g_assert_cmpstr(qstring_get_str(qstr), ==, expected[i]); 265cb3e7f08SMarc-André Lureau qobject_unref(qstr); 2660b2c1beeSMarkus Armbruster } 2670b2c1beeSMarkus Armbruster g_assert(qlist_empty(qlist)); 2680b2c1beeSMarkus Armbruster } 2690b2c1beeSMarkus Armbruster 2700b2c1beeSMarkus Armbruster static void test_keyval_parse_list(void) 2710b2c1beeSMarkus Armbruster { 2720b2c1beeSMarkus Armbruster Error *err = NULL; 2730b2c1beeSMarkus Armbruster QDict *qdict, *sub_qdict; 2740b2c1beeSMarkus Armbruster 2750b2c1beeSMarkus Armbruster /* Root can't be a list */ 2768bf12c4fSKevin Wolf qdict = keyval_parse("0=1", NULL, NULL, &err); 2770b2c1beeSMarkus Armbruster error_free_or_abort(&err); 2780b2c1beeSMarkus Armbruster g_assert(!qdict); 2790b2c1beeSMarkus Armbruster 2800b2c1beeSMarkus Armbruster /* List elements need not be in order */ 2818bf12c4fSKevin Wolf qdict = keyval_parse("list.0=null,list.2=zwei,list.1=eins", NULL, NULL, 2828bf12c4fSKevin Wolf &error_abort); 2830b2c1beeSMarkus Armbruster g_assert_cmpint(qdict_size(qdict), ==, 1); 2840b2c1beeSMarkus Armbruster check_list012(qdict_get_qlist(qdict, "list")); 285cb3e7f08SMarc-André Lureau qobject_unref(qdict); 2860b2c1beeSMarkus Armbruster 2870b2c1beeSMarkus Armbruster /* Multiple indexes, last one wins */ 288b2cd5b92SMarkus Armbruster qdict = keyval_parse("list.1=goner,list.0=null,list.01=eins,list.2=zwei", 2898bf12c4fSKevin Wolf NULL, NULL, &error_abort); 2900b2c1beeSMarkus Armbruster g_assert_cmpint(qdict_size(qdict), ==, 1); 2910b2c1beeSMarkus Armbruster check_list012(qdict_get_qlist(qdict, "list")); 292cb3e7f08SMarc-André Lureau qobject_unref(qdict); 2930b2c1beeSMarkus Armbruster 2940b2c1beeSMarkus Armbruster /* List at deeper nesting */ 2958bf12c4fSKevin Wolf qdict = keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei", NULL, 2960b2c1beeSMarkus Armbruster NULL, &error_abort); 2970b2c1beeSMarkus Armbruster g_assert_cmpint(qdict_size(qdict), ==, 1); 2980b2c1beeSMarkus Armbruster sub_qdict = qdict_get_qdict(qdict, "a"); 2990b2c1beeSMarkus Armbruster g_assert_cmpint(qdict_size(sub_qdict), ==, 1); 3000b2c1beeSMarkus Armbruster check_list012(qdict_get_qlist(sub_qdict, "list")); 301cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3020b2c1beeSMarkus Armbruster 3030b2c1beeSMarkus Armbruster /* Inconsistent dotted keys: both list and dictionary */ 3048bf12c4fSKevin Wolf qdict = keyval_parse("a.b.c=1,a.b.0=2", NULL, NULL, &err); 3050b2c1beeSMarkus Armbruster error_free_or_abort(&err); 3060b2c1beeSMarkus Armbruster g_assert(!qdict); 3078bf12c4fSKevin Wolf qdict = keyval_parse("a.0.c=1,a.b.c=2", NULL, NULL, &err); 3080b2c1beeSMarkus Armbruster error_free_or_abort(&err); 3090b2c1beeSMarkus Armbruster g_assert(!qdict); 3100b2c1beeSMarkus Armbruster 3110b2c1beeSMarkus Armbruster /* Missing list indexes */ 3128bf12c4fSKevin Wolf qdict = keyval_parse("list.1=lonely", NULL, NULL, &err); 3130b2c1beeSMarkus Armbruster error_free_or_abort(&err); 3140b2c1beeSMarkus Armbruster g_assert(!qdict); 3158bf12c4fSKevin Wolf qdict = keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL, NULL, 3168bf12c4fSKevin Wolf &err); 3170b2c1beeSMarkus Armbruster error_free_or_abort(&err); 3180b2c1beeSMarkus Armbruster g_assert(!qdict); 3190b2c1beeSMarkus Armbruster } 3200b2c1beeSMarkus Armbruster 3219e3943f8SMarkus Armbruster static void test_keyval_visit_bool(void) 3229e3943f8SMarkus Armbruster { 3239e3943f8SMarkus Armbruster Error *err = NULL; 3249e3943f8SMarkus Armbruster Visitor *v; 3259e3943f8SMarkus Armbruster QDict *qdict; 3269e3943f8SMarkus Armbruster bool b; 3279e3943f8SMarkus Armbruster 3288bf12c4fSKevin Wolf qdict = keyval_parse("bool1=on,bool2=off", NULL, NULL, &error_abort); 3299e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 330cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3319e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3329e3943f8SMarkus Armbruster visit_type_bool(v, "bool1", &b, &error_abort); 3339e3943f8SMarkus Armbruster g_assert(b); 3349e3943f8SMarkus Armbruster visit_type_bool(v, "bool2", &b, &error_abort); 3359e3943f8SMarkus Armbruster g_assert(!b); 3369e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 3379e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3389e3943f8SMarkus Armbruster visit_free(v); 3399e3943f8SMarkus Armbruster 3408bf12c4fSKevin Wolf qdict = keyval_parse("bool1=offer", NULL, NULL, &error_abort); 3419e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 342cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3439e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3449e3943f8SMarkus Armbruster visit_type_bool(v, "bool1", &b, &err); 3459e3943f8SMarkus Armbruster error_free_or_abort(&err); 3469e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3479e3943f8SMarkus Armbruster visit_free(v); 3489e3943f8SMarkus Armbruster } 3499e3943f8SMarkus Armbruster 3509e3943f8SMarkus Armbruster static void test_keyval_visit_number(void) 3519e3943f8SMarkus Armbruster { 3529e3943f8SMarkus Armbruster Error *err = NULL; 3539e3943f8SMarkus Armbruster Visitor *v; 3549e3943f8SMarkus Armbruster QDict *qdict; 3559e3943f8SMarkus Armbruster uint64_t u; 3569e3943f8SMarkus Armbruster 3579e3943f8SMarkus Armbruster /* Lower limit zero */ 3588bf12c4fSKevin Wolf qdict = keyval_parse("number1=0", NULL, NULL, &error_abort); 3599e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 360cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3619e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3629e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &error_abort); 3639e3943f8SMarkus Armbruster g_assert_cmpuint(u, ==, 0); 3649e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 3659e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3669e3943f8SMarkus Armbruster visit_free(v); 3679e3943f8SMarkus Armbruster 3689e3943f8SMarkus Armbruster /* Upper limit 2^64-1 */ 3698bf12c4fSKevin Wolf qdict = keyval_parse("number1=18446744073709551615,number2=-1", NULL, 3709e3943f8SMarkus Armbruster NULL, &error_abort); 3719e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 372cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3739e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3749e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &error_abort); 3759e3943f8SMarkus Armbruster g_assert_cmphex(u, ==, UINT64_MAX); 3769e3943f8SMarkus Armbruster visit_type_uint64(v, "number2", &u, &error_abort); 3779e3943f8SMarkus Armbruster g_assert_cmphex(u, ==, UINT64_MAX); 3789e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 3799e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3809e3943f8SMarkus Armbruster visit_free(v); 3819e3943f8SMarkus Armbruster 3829e3943f8SMarkus Armbruster /* Above upper limit */ 3838bf12c4fSKevin Wolf qdict = keyval_parse("number1=18446744073709551616", NULL, NULL, 3848bf12c4fSKevin Wolf &error_abort); 3859e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 386cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3879e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3889e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &err); 3899e3943f8SMarkus Armbruster error_free_or_abort(&err); 3909e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3919e3943f8SMarkus Armbruster visit_free(v); 3929e3943f8SMarkus Armbruster 3939e3943f8SMarkus Armbruster /* Below lower limit */ 3948bf12c4fSKevin Wolf qdict = keyval_parse("number1=-18446744073709551616", NULL, NULL, 3958bf12c4fSKevin Wolf &error_abort); 3969e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 397cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3989e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3999e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &err); 4009e3943f8SMarkus Armbruster error_free_or_abort(&err); 4019e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4029e3943f8SMarkus Armbruster visit_free(v); 4039e3943f8SMarkus Armbruster 4049e3943f8SMarkus Armbruster /* Hex and octal */ 4058bf12c4fSKevin Wolf qdict = keyval_parse("number1=0x2a,number2=052", NULL, NULL, &error_abort); 4069e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 407cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4089e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4099e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &error_abort); 4109e3943f8SMarkus Armbruster g_assert_cmpuint(u, ==, 42); 4119e3943f8SMarkus Armbruster visit_type_uint64(v, "number2", &u, &error_abort); 4129e3943f8SMarkus Armbruster g_assert_cmpuint(u, ==, 42); 4139e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 4149e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4159e3943f8SMarkus Armbruster visit_free(v); 4169e3943f8SMarkus Armbruster 4179e3943f8SMarkus Armbruster /* Trailing crap */ 4188bf12c4fSKevin Wolf qdict = keyval_parse("number1=3.14,number2=08", NULL, NULL, &error_abort); 4199e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 420cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4219e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4229e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &err); 4239e3943f8SMarkus Armbruster error_free_or_abort(&err); 4249e3943f8SMarkus Armbruster visit_type_uint64(v, "number2", &u, &err); 4259e3943f8SMarkus Armbruster error_free_or_abort(&err); 4269e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4279e3943f8SMarkus Armbruster visit_free(v); 4289e3943f8SMarkus Armbruster } 4299e3943f8SMarkus Armbruster 4309e3943f8SMarkus Armbruster static void test_keyval_visit_size(void) 4319e3943f8SMarkus Armbruster { 4329e3943f8SMarkus Armbruster Error *err = NULL; 4339e3943f8SMarkus Armbruster Visitor *v; 4349e3943f8SMarkus Armbruster QDict *qdict; 4359e3943f8SMarkus Armbruster uint64_t sz; 4369e3943f8SMarkus Armbruster 4379e3943f8SMarkus Armbruster /* Lower limit zero */ 4388bf12c4fSKevin Wolf qdict = keyval_parse("sz1=0", NULL, NULL, &error_abort); 4399e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 440cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4419e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4429e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 4439e3943f8SMarkus Armbruster g_assert_cmpuint(sz, ==, 0); 4449e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 4459e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4469e3943f8SMarkus Armbruster visit_free(v); 4479e3943f8SMarkus Armbruster 448cf923b78SEric Blake /* Note: full 64 bits of precision */ 4499e3943f8SMarkus Armbruster 450cf923b78SEric Blake /* Around double limit of precision: 2^53-1, 2^53, 2^53+1 */ 4519e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=9007199254740991," 4529e3943f8SMarkus Armbruster "sz2=9007199254740992," 4539e3943f8SMarkus Armbruster "sz3=9007199254740993", 4548bf12c4fSKevin Wolf NULL, NULL, &error_abort); 4559e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 456cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4579e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4589e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 4599e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0x1fffffffffffff); 4609e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &error_abort); 4619e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0x20000000000000); 4629e3943f8SMarkus Armbruster visit_type_size(v, "sz3", &sz, &error_abort); 463cf923b78SEric Blake g_assert_cmphex(sz, ==, 0x20000000000001); 4649e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 4659e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4669e3943f8SMarkus Armbruster visit_free(v); 4679e3943f8SMarkus Armbruster 468cf923b78SEric Blake /* Close to signed integer limit 2^63 */ 469cf923b78SEric Blake qdict = keyval_parse("sz1=9223372036854775807," /* 7fffffffffffffff */ 470cf923b78SEric Blake "sz2=9223372036854775808," /* 8000000000000000 */ 471cf923b78SEric Blake "sz3=9223372036854775809", /* 8000000000000001 */ 4728bf12c4fSKevin Wolf NULL, NULL, &error_abort); 4739e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 474cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4759e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4769e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 477cf923b78SEric Blake g_assert_cmphex(sz, ==, 0x7fffffffffffffff); 4789e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &error_abort); 479cf923b78SEric Blake g_assert_cmphex(sz, ==, 0x8000000000000000); 480cf923b78SEric Blake visit_type_size(v, "sz3", &sz, &error_abort); 481cf923b78SEric Blake g_assert_cmphex(sz, ==, 0x8000000000000001); 4829e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 4839e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4849e3943f8SMarkus Armbruster visit_free(v); 4859e3943f8SMarkus Armbruster 4869e3943f8SMarkus Armbruster /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ 4879e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */ 4889e3943f8SMarkus Armbruster "sz2=18446744073709550591", /* fffffffffffffbff */ 4898bf12c4fSKevin Wolf NULL, NULL, &error_abort); 4909e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 491cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4929e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4939e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 4949e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0xfffffffffffff800); 4959e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &error_abort); 496cf923b78SEric Blake g_assert_cmphex(sz, ==, 0xfffffffffffffbff); 497cf923b78SEric Blake visit_check_struct(v, &error_abort); 498cf923b78SEric Blake visit_end_struct(v, NULL); 499cf923b78SEric Blake visit_free(v); 500cf923b78SEric Blake 501cf923b78SEric Blake /* Actual limit 2^64-1*/ 502cf923b78SEric Blake qdict = keyval_parse("sz1=18446744073709551615", /* ffffffffffffffff */ 503cf923b78SEric Blake NULL, NULL, &error_abort); 504cf923b78SEric Blake v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 505cf923b78SEric Blake qobject_unref(qdict); 506cf923b78SEric Blake visit_start_struct(v, NULL, NULL, 0, &error_abort); 507cf923b78SEric Blake visit_type_size(v, "sz1", &sz, &error_abort); 508cf923b78SEric Blake g_assert_cmphex(sz, ==, 0xffffffffffffffff); 5099e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 5109e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5119e3943f8SMarkus Armbruster visit_free(v); 5129e3943f8SMarkus Armbruster 5139e3943f8SMarkus Armbruster /* Beyond limits */ 5149e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=-1," 515cf923b78SEric Blake "sz2=18446744073709551616", /* 2^64 */ 5168bf12c4fSKevin Wolf NULL, NULL, &error_abort); 5179e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 518cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5199e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5209e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &err); 5219e3943f8SMarkus Armbruster error_free_or_abort(&err); 5229e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &err); 5239e3943f8SMarkus Armbruster error_free_or_abort(&err); 5249e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5259e3943f8SMarkus Armbruster visit_free(v); 5269e3943f8SMarkus Armbruster 5279e3943f8SMarkus Armbruster /* Suffixes */ 5289e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T", 5298bf12c4fSKevin Wolf NULL, NULL, &error_abort); 5309e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 531cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5329e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5339e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 5349e3943f8SMarkus Armbruster g_assert_cmpuint(sz, ==, 8); 5359e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &error_abort); 5369e3943f8SMarkus Armbruster g_assert_cmpuint(sz, ==, 1536); 5379e3943f8SMarkus Armbruster visit_type_size(v, "sz3", &sz, &error_abort); 538d23b6caaSPhilippe Mathieu-Daudé g_assert_cmphex(sz, ==, 2 * MiB); 5399e3943f8SMarkus Armbruster visit_type_size(v, "sz4", &sz, &error_abort); 540d23b6caaSPhilippe Mathieu-Daudé g_assert_cmphex(sz, ==, GiB / 10); 5419e3943f8SMarkus Armbruster visit_type_size(v, "sz5", &sz, &error_abort); 542d23b6caaSPhilippe Mathieu-Daudé g_assert_cmphex(sz, ==, 16777215ULL * TiB); 5439e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 5449e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5459e3943f8SMarkus Armbruster visit_free(v); 5469e3943f8SMarkus Armbruster 5479e3943f8SMarkus Armbruster /* Beyond limit with suffix */ 5488bf12c4fSKevin Wolf qdict = keyval_parse("sz1=16777216T", NULL, NULL, &error_abort); 5499e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 550cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5519e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5529e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &err); 5539e3943f8SMarkus Armbruster error_free_or_abort(&err); 5549e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5559e3943f8SMarkus Armbruster visit_free(v); 5569e3943f8SMarkus Armbruster 5579e3943f8SMarkus Armbruster /* Trailing crap */ 5588bf12c4fSKevin Wolf qdict = keyval_parse("sz1=0Z,sz2=16Gi", NULL, NULL, &error_abort); 5599e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 560cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5619e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5629e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &err); 5639e3943f8SMarkus Armbruster error_free_or_abort(&err); 5649e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &err); 5659e3943f8SMarkus Armbruster error_free_or_abort(&err); 5669e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5679e3943f8SMarkus Armbruster visit_free(v); 5689e3943f8SMarkus Armbruster } 5699e3943f8SMarkus Armbruster 5709e3943f8SMarkus Armbruster static void test_keyval_visit_dict(void) 5719e3943f8SMarkus Armbruster { 5729e3943f8SMarkus Armbruster Error *err = NULL; 5739e3943f8SMarkus Armbruster Visitor *v; 5749e3943f8SMarkus Armbruster QDict *qdict; 5759e3943f8SMarkus Armbruster int64_t i; 5769e3943f8SMarkus Armbruster 5778bf12c4fSKevin Wolf qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, NULL, &error_abort); 5789e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 579cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5809e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5819e3943f8SMarkus Armbruster visit_start_struct(v, "a", NULL, 0, &error_abort); 5829e3943f8SMarkus Armbruster visit_start_struct(v, "b", NULL, 0, &error_abort); 5839e3943f8SMarkus Armbruster visit_type_int(v, "c", &i, &error_abort); 5849e3943f8SMarkus Armbruster g_assert_cmpint(i, ==, 2); 5859e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 5869e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5879e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 5889e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5899e3943f8SMarkus Armbruster visit_type_int(v, "d", &i, &error_abort); 5909e3943f8SMarkus Armbruster g_assert_cmpint(i, ==, 3); 5919e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 5929e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5939e3943f8SMarkus Armbruster visit_free(v); 5949e3943f8SMarkus Armbruster 5958bf12c4fSKevin Wolf qdict = keyval_parse("a.b=", NULL, NULL, &error_abort); 5969e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 597cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5989e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5999e3943f8SMarkus Armbruster visit_start_struct(v, "a", NULL, 0, &error_abort); 6009e3943f8SMarkus Armbruster visit_type_int(v, "c", &i, &err); /* a.c missing */ 6019e3943f8SMarkus Armbruster error_free_or_abort(&err); 6029e3943f8SMarkus Armbruster visit_check_struct(v, &err); 6039e3943f8SMarkus Armbruster error_free_or_abort(&err); /* a.b unexpected */ 6049e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 6059e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 6069e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 6079e3943f8SMarkus Armbruster visit_free(v); 6089e3943f8SMarkus Armbruster } 6099e3943f8SMarkus Armbruster 6100b2c1beeSMarkus Armbruster static void test_keyval_visit_list(void) 6110b2c1beeSMarkus Armbruster { 6120b2c1beeSMarkus Armbruster Error *err = NULL; 6130b2c1beeSMarkus Armbruster Visitor *v; 6140b2c1beeSMarkus Armbruster QDict *qdict; 6150b2c1beeSMarkus Armbruster char *s; 6160b2c1beeSMarkus Armbruster 6178bf12c4fSKevin Wolf qdict = keyval_parse("a.0=,a.1=I,a.2.0=II", NULL, NULL, &error_abort); 6180b2c1beeSMarkus Armbruster /* TODO empty list */ 6190b2c1beeSMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 620cb3e7f08SMarc-André Lureau qobject_unref(qdict); 6210b2c1beeSMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 6220b2c1beeSMarkus Armbruster visit_start_list(v, "a", NULL, 0, &error_abort); 6230b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &error_abort); 6240b2c1beeSMarkus Armbruster g_assert_cmpstr(s, ==, ""); 6250b2c1beeSMarkus Armbruster g_free(s); 6260b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &error_abort); 6270b2c1beeSMarkus Armbruster g_assert_cmpstr(s, ==, "I"); 6280b2c1beeSMarkus Armbruster g_free(s); 6290b2c1beeSMarkus Armbruster visit_start_list(v, NULL, NULL, 0, &error_abort); 6300b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &error_abort); 6310b2c1beeSMarkus Armbruster g_assert_cmpstr(s, ==, "II"); 6320b2c1beeSMarkus Armbruster g_free(s); 6330b2c1beeSMarkus Armbruster visit_check_list(v, &error_abort); 6340b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 6350b2c1beeSMarkus Armbruster visit_check_list(v, &error_abort); 6360b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 6370b2c1beeSMarkus Armbruster visit_check_struct(v, &error_abort); 6380b2c1beeSMarkus Armbruster visit_end_struct(v, NULL); 6390b2c1beeSMarkus Armbruster visit_free(v); 6400b2c1beeSMarkus Armbruster 6418bf12c4fSKevin Wolf qdict = keyval_parse("a.0=,b.0.0=head", NULL, NULL, &error_abort); 6420b2c1beeSMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 643cb3e7f08SMarc-André Lureau qobject_unref(qdict); 6440b2c1beeSMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 6450b2c1beeSMarkus Armbruster visit_start_list(v, "a", NULL, 0, &error_abort); 6460b2c1beeSMarkus Armbruster visit_check_list(v, &err); /* a[0] unexpected */ 6470b2c1beeSMarkus Armbruster error_free_or_abort(&err); 6480b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 6490b2c1beeSMarkus Armbruster visit_start_list(v, "b", NULL, 0, &error_abort); 6500b2c1beeSMarkus Armbruster visit_start_list(v, NULL, NULL, 0, &error_abort); 6510b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &error_abort); 6520b2c1beeSMarkus Armbruster g_assert_cmpstr(s, ==, "head"); 6530b2c1beeSMarkus Armbruster g_free(s); 6540b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &err); /* b[0][1] missing */ 6550b2c1beeSMarkus Armbruster error_free_or_abort(&err); 6560b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 6570b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 6580b2c1beeSMarkus Armbruster visit_check_struct(v, &error_abort); 6590b2c1beeSMarkus Armbruster visit_end_struct(v, NULL); 6600b2c1beeSMarkus Armbruster visit_free(v); 6610b2c1beeSMarkus Armbruster } 6620b2c1beeSMarkus Armbruster 6639e3943f8SMarkus Armbruster static void test_keyval_visit_optional(void) 6649e3943f8SMarkus Armbruster { 6659e3943f8SMarkus Armbruster Visitor *v; 6669e3943f8SMarkus Armbruster QDict *qdict; 6679e3943f8SMarkus Armbruster bool present; 6689e3943f8SMarkus Armbruster int64_t i; 6699e3943f8SMarkus Armbruster 6708bf12c4fSKevin Wolf qdict = keyval_parse("a.b=1", NULL, NULL, &error_abort); 6719e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 672cb3e7f08SMarc-André Lureau qobject_unref(qdict); 6739e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 6749e3943f8SMarkus Armbruster visit_optional(v, "b", &present); 6759e3943f8SMarkus Armbruster g_assert(!present); /* b missing */ 6769e3943f8SMarkus Armbruster visit_optional(v, "a", &present); 6779e3943f8SMarkus Armbruster g_assert(present); /* a present */ 6789e3943f8SMarkus Armbruster visit_start_struct(v, "a", NULL, 0, &error_abort); 6799e3943f8SMarkus Armbruster visit_optional(v, "b", &present); 6809e3943f8SMarkus Armbruster g_assert(present); /* a.b present */ 6819e3943f8SMarkus Armbruster visit_type_int(v, "b", &i, &error_abort); 6829e3943f8SMarkus Armbruster g_assert_cmpint(i, ==, 1); 6839e3943f8SMarkus Armbruster visit_optional(v, "a", &present); 6849e3943f8SMarkus Armbruster g_assert(!present); /* a.a missing */ 6859e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 6869e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 6879e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 6889e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 6899e3943f8SMarkus Armbruster visit_free(v); 6909e3943f8SMarkus Armbruster } 6919e3943f8SMarkus Armbruster 692599c156bSMarkus Armbruster static void test_keyval_visit_alternate(void) 693599c156bSMarkus Armbruster { 694599c156bSMarkus Armbruster Error *err = NULL; 695599c156bSMarkus Armbruster Visitor *v; 696599c156bSMarkus Armbruster QDict *qdict; 697c0644771SMarkus Armbruster AltStrObj *aso; 6987c877c80SMarc-André Lureau AltNumEnum *ane; 699c0644771SMarkus Armbruster AltEnumBool *aeb; 700599c156bSMarkus Armbruster 701599c156bSMarkus Armbruster /* 702599c156bSMarkus Armbruster * Can't do scalar alternate variants other than string. You get 703599c156bSMarkus Armbruster * the string variant if there is one, else an error. 704c0644771SMarkus Armbruster * TODO make it work for unambiguous cases like AltEnumBool below 705599c156bSMarkus Armbruster */ 7068bf12c4fSKevin Wolf qdict = keyval_parse("a=1,b=2,c=on", NULL, NULL, &error_abort); 707599c156bSMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 708cb3e7f08SMarc-André Lureau qobject_unref(qdict); 709599c156bSMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 710c0644771SMarkus Armbruster visit_type_AltStrObj(v, "a", &aso, &error_abort); 711c0644771SMarkus Armbruster g_assert_cmpint(aso->type, ==, QTYPE_QSTRING); 712c0644771SMarkus Armbruster g_assert_cmpstr(aso->u.s, ==, "1"); 713c0644771SMarkus Armbruster qapi_free_AltStrObj(aso); 7147c877c80SMarc-André Lureau visit_type_AltNumEnum(v, "b", &ane, &err); 715c0644771SMarkus Armbruster error_free_or_abort(&err); 716c0644771SMarkus Armbruster visit_type_AltEnumBool(v, "c", &aeb, &err); 717599c156bSMarkus Armbruster error_free_or_abort(&err); 718599c156bSMarkus Armbruster visit_end_struct(v, NULL); 719599c156bSMarkus Armbruster visit_free(v); 720599c156bSMarkus Armbruster } 721599c156bSMarkus Armbruster 722599c156bSMarkus Armbruster static void test_keyval_visit_any(void) 723599c156bSMarkus Armbruster { 724599c156bSMarkus Armbruster Visitor *v; 725599c156bSMarkus Armbruster QDict *qdict; 726599c156bSMarkus Armbruster QObject *any; 727599c156bSMarkus Armbruster QList *qlist; 728599c156bSMarkus Armbruster QString *qstr; 729599c156bSMarkus Armbruster 7308bf12c4fSKevin Wolf qdict = keyval_parse("a.0=null,a.1=1", NULL, NULL, &error_abort); 731599c156bSMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 732cb3e7f08SMarc-André Lureau qobject_unref(qdict); 733599c156bSMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 734599c156bSMarkus Armbruster visit_type_any(v, "a", &any, &error_abort); 7357dc847ebSMax Reitz qlist = qobject_to(QList, any); 736599c156bSMarkus Armbruster g_assert(qlist); 7377dc847ebSMax Reitz qstr = qobject_to(QString, qlist_pop(qlist)); 738599c156bSMarkus Armbruster g_assert_cmpstr(qstring_get_str(qstr), ==, "null"); 739cb3e7f08SMarc-André Lureau qobject_unref(qstr); 7407dc847ebSMax Reitz qstr = qobject_to(QString, qlist_pop(qlist)); 741599c156bSMarkus Armbruster g_assert_cmpstr(qstring_get_str(qstr), ==, "1"); 742599c156bSMarkus Armbruster g_assert(qlist_empty(qlist)); 743cb3e7f08SMarc-André Lureau qobject_unref(qstr); 744cb3e7f08SMarc-André Lureau qobject_unref(any); 745599c156bSMarkus Armbruster visit_check_struct(v, &error_abort); 746599c156bSMarkus Armbruster visit_end_struct(v, NULL); 747599c156bSMarkus Armbruster visit_free(v); 748599c156bSMarkus Armbruster } 749599c156bSMarkus Armbruster 7509176e800SPaolo Bonzini static void test_keyval_merge_dict(void) 7519176e800SPaolo Bonzini { 7529176e800SPaolo Bonzini QDict *first = keyval_parse("opt1=abc,opt2.sub1=def,opt2.sub2=ghi,opt3=xyz", 7539176e800SPaolo Bonzini NULL, NULL, &error_abort); 7549176e800SPaolo Bonzini QDict *second = keyval_parse("opt1=ABC,opt2.sub2=GHI,opt2.sub3=JKL", 7559176e800SPaolo Bonzini NULL, NULL, &error_abort); 7569176e800SPaolo Bonzini QDict *combined = keyval_parse("opt1=ABC,opt2.sub1=def,opt2.sub2=GHI,opt2.sub3=JKL,opt3=xyz", 7579176e800SPaolo Bonzini NULL, NULL, &error_abort); 7589176e800SPaolo Bonzini Error *err = NULL; 7599176e800SPaolo Bonzini 7609176e800SPaolo Bonzini keyval_merge(first, second, &err); 7619176e800SPaolo Bonzini g_assert(!err); 7629176e800SPaolo Bonzini g_assert(qobject_is_equal(QOBJECT(combined), QOBJECT(first))); 7639176e800SPaolo Bonzini qobject_unref(first); 7649176e800SPaolo Bonzini qobject_unref(second); 7659176e800SPaolo Bonzini qobject_unref(combined); 7669176e800SPaolo Bonzini } 7679176e800SPaolo Bonzini 7689176e800SPaolo Bonzini static void test_keyval_merge_list(void) 7699176e800SPaolo Bonzini { 7709176e800SPaolo Bonzini QDict *first = keyval_parse("opt1.0=abc,opt2.0=xyz", 7719176e800SPaolo Bonzini NULL, NULL, &error_abort); 7729176e800SPaolo Bonzini QDict *second = keyval_parse("opt1.0=def", 7739176e800SPaolo Bonzini NULL, NULL, &error_abort); 7749176e800SPaolo Bonzini QDict *combined = keyval_parse("opt1.0=abc,opt1.1=def,opt2.0=xyz", 7759176e800SPaolo Bonzini NULL, NULL, &error_abort); 7769176e800SPaolo Bonzini Error *err = NULL; 7779176e800SPaolo Bonzini 7789176e800SPaolo Bonzini keyval_merge(first, second, &err); 7799176e800SPaolo Bonzini g_assert(!err); 7809176e800SPaolo Bonzini g_assert(qobject_is_equal(QOBJECT(combined), QOBJECT(first))); 7819176e800SPaolo Bonzini qobject_unref(first); 7829176e800SPaolo Bonzini qobject_unref(second); 7839176e800SPaolo Bonzini qobject_unref(combined); 7849176e800SPaolo Bonzini } 7859176e800SPaolo Bonzini 7869176e800SPaolo Bonzini static void test_keyval_merge_conflict(void) 7879176e800SPaolo Bonzini { 7889176e800SPaolo Bonzini QDict *first = keyval_parse("opt2=ABC", 7899176e800SPaolo Bonzini NULL, NULL, &error_abort); 7909176e800SPaolo Bonzini QDict *second = keyval_parse("opt2.sub1=def,opt2.sub2=ghi", 7919176e800SPaolo Bonzini NULL, NULL, &error_abort); 7929176e800SPaolo Bonzini QDict *third = qdict_clone_shallow(first); 7939176e800SPaolo Bonzini Error *err = NULL; 7949176e800SPaolo Bonzini 7959176e800SPaolo Bonzini keyval_merge(first, second, &err); 7969176e800SPaolo Bonzini error_free_or_abort(&err); 7979176e800SPaolo Bonzini keyval_merge(second, third, &err); 7989176e800SPaolo Bonzini error_free_or_abort(&err); 7999176e800SPaolo Bonzini 8009176e800SPaolo Bonzini qobject_unref(first); 8019176e800SPaolo Bonzini qobject_unref(second); 8029176e800SPaolo Bonzini qobject_unref(third); 8039176e800SPaolo Bonzini } 8049176e800SPaolo Bonzini 805d454dbe0SMarkus Armbruster int main(int argc, char *argv[]) 806d454dbe0SMarkus Armbruster { 807d454dbe0SMarkus Armbruster g_test_init(&argc, &argv, NULL); 808d454dbe0SMarkus Armbruster g_test_add_func("/keyval/keyval_parse", test_keyval_parse); 8090b2c1beeSMarkus Armbruster g_test_add_func("/keyval/keyval_parse/list", test_keyval_parse_list); 8109e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool); 8119e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/number", test_keyval_visit_number); 8129e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/size", test_keyval_visit_size); 8139e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict); 8140b2c1beeSMarkus Armbruster g_test_add_func("/keyval/visit/list", test_keyval_visit_list); 8159e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional); 816599c156bSMarkus Armbruster g_test_add_func("/keyval/visit/alternate", test_keyval_visit_alternate); 817599c156bSMarkus Armbruster g_test_add_func("/keyval/visit/any", test_keyval_visit_any); 8189176e800SPaolo Bonzini g_test_add_func("/keyval/merge/dict", test_keyval_merge_dict); 8199176e800SPaolo Bonzini g_test_add_func("/keyval/merge/list", test_keyval_merge_list); 8209176e800SPaolo Bonzini g_test_add_func("/keyval/merge/conflict", test_keyval_merge_conflict); 821d454dbe0SMarkus Armbruster g_test_run(); 822d454dbe0SMarkus Armbruster return 0; 823d454dbe0SMarkus Armbruster } 824