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" 22d454dbe0SMarkus Armbruster #include "qemu/option.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; 30d454dbe0SMarkus Armbruster 31d454dbe0SMarkus Armbruster /* Nothing */ 32d454dbe0SMarkus Armbruster qdict = keyval_parse("", NULL, &error_abort); 33d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 0); 34cb3e7f08SMarc-André Lureau qobject_unref(qdict); 35d454dbe0SMarkus Armbruster 36d454dbe0SMarkus Armbruster /* Empty key (qemu_opts_parse() accepts this) */ 37d454dbe0SMarkus Armbruster qdict = keyval_parse("=val", NULL, &err); 38d454dbe0SMarkus Armbruster error_free_or_abort(&err); 39d454dbe0SMarkus Armbruster g_assert(!qdict); 40d454dbe0SMarkus Armbruster 41d454dbe0SMarkus Armbruster /* Empty key fragment */ 42d454dbe0SMarkus Armbruster qdict = keyval_parse(".", NULL, &err); 43d454dbe0SMarkus Armbruster error_free_or_abort(&err); 44d454dbe0SMarkus Armbruster g_assert(!qdict); 45d454dbe0SMarkus Armbruster qdict = keyval_parse("key.", NULL, &err); 46d454dbe0SMarkus Armbruster error_free_or_abort(&err); 47d454dbe0SMarkus Armbruster g_assert(!qdict); 48d454dbe0SMarkus Armbruster 49f7400483SMarkus Armbruster /* Invalid non-empty key (qemu_opts_parse() doesn't care) */ 50f7400483SMarkus Armbruster qdict = keyval_parse("7up=val", NULL, &err); 51f7400483SMarkus Armbruster error_free_or_abort(&err); 52f7400483SMarkus Armbruster g_assert(!qdict); 53f7400483SMarkus Armbruster 54d454dbe0SMarkus Armbruster /* Overlong key */ 55d454dbe0SMarkus Armbruster memset(long_key, 'a', 127); 56d454dbe0SMarkus Armbruster long_key[127] = 'z'; 57d454dbe0SMarkus Armbruster long_key[128] = 0; 58d454dbe0SMarkus Armbruster params = g_strdup_printf("k.%s=v", long_key); 59d454dbe0SMarkus Armbruster qdict = keyval_parse(params + 2, NULL, &err); 60d454dbe0SMarkus Armbruster error_free_or_abort(&err); 61d454dbe0SMarkus Armbruster g_assert(!qdict); 62d454dbe0SMarkus Armbruster 63d454dbe0SMarkus Armbruster /* Overlong key fragment */ 64d454dbe0SMarkus Armbruster qdict = keyval_parse(params, NULL, &err); 65d454dbe0SMarkus Armbruster error_free_or_abort(&err); 66d454dbe0SMarkus Armbruster g_assert(!qdict); 67d454dbe0SMarkus Armbruster g_free(params); 68d454dbe0SMarkus Armbruster 69d454dbe0SMarkus Armbruster /* Long key (qemu_opts_parse() accepts and truncates silently) */ 70d454dbe0SMarkus Armbruster params = g_strdup_printf("k.%s=v", long_key + 1); 71d454dbe0SMarkus Armbruster qdict = keyval_parse(params + 2, NULL, &error_abort); 72d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 73d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, long_key + 1), ==, "v"); 74cb3e7f08SMarc-André Lureau qobject_unref(qdict); 75d454dbe0SMarkus Armbruster 76d454dbe0SMarkus Armbruster /* Long key fragment */ 77d454dbe0SMarkus Armbruster qdict = keyval_parse(params, NULL, &error_abort); 78d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 79d454dbe0SMarkus Armbruster sub_qdict = qdict_get_qdict(qdict, "k"); 80d454dbe0SMarkus Armbruster g_assert(sub_qdict); 81d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 82d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(sub_qdict, long_key + 1), ==, "v"); 83cb3e7f08SMarc-André Lureau qobject_unref(qdict); 84d454dbe0SMarkus Armbruster g_free(params); 85d454dbe0SMarkus Armbruster 86f7400483SMarkus Armbruster /* Crap after valid key */ 87f7400483SMarkus Armbruster qdict = keyval_parse("key[0]=val", NULL, &err); 88f7400483SMarkus Armbruster error_free_or_abort(&err); 89f7400483SMarkus Armbruster g_assert(!qdict); 90f7400483SMarkus Armbruster 91d454dbe0SMarkus Armbruster /* Multiple keys, last one wins */ 92d454dbe0SMarkus Armbruster qdict = keyval_parse("a=1,b=2,,x,a=3", NULL, &error_abort); 93d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 2); 94d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "a"), ==, "3"); 95d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "b"), ==, "2,x"); 96cb3e7f08SMarc-André Lureau qobject_unref(qdict); 97d454dbe0SMarkus Armbruster 98d454dbe0SMarkus Armbruster /* Even when it doesn't in qemu_opts_parse() */ 99d454dbe0SMarkus Armbruster qdict = keyval_parse("id=foo,id=bar", NULL, &error_abort); 100d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 101d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "bar"); 102cb3e7f08SMarc-André Lureau qobject_unref(qdict); 103d454dbe0SMarkus Armbruster 104d454dbe0SMarkus Armbruster /* Dotted keys */ 105d454dbe0SMarkus Armbruster qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, &error_abort); 106d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 2); 107d454dbe0SMarkus Armbruster sub_qdict = qdict_get_qdict(qdict, "a"); 108d454dbe0SMarkus Armbruster g_assert(sub_qdict); 109d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 110d454dbe0SMarkus Armbruster sub_qdict = qdict_get_qdict(sub_qdict, "b"); 111d454dbe0SMarkus Armbruster g_assert(sub_qdict); 112d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 113d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(sub_qdict, "c"), ==, "2"); 114d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "d"), ==, "3"); 115cb3e7f08SMarc-André Lureau qobject_unref(qdict); 116d454dbe0SMarkus Armbruster 117d454dbe0SMarkus Armbruster /* Inconsistent dotted keys */ 118d454dbe0SMarkus Armbruster qdict = keyval_parse("a.b=1,a=2", NULL, &err); 119d454dbe0SMarkus Armbruster error_free_or_abort(&err); 120d454dbe0SMarkus Armbruster g_assert(!qdict); 121d454dbe0SMarkus Armbruster qdict = keyval_parse("a.b=1,a.b.c=2", NULL, &err); 122d454dbe0SMarkus Armbruster error_free_or_abort(&err); 123d454dbe0SMarkus Armbruster g_assert(!qdict); 124d454dbe0SMarkus Armbruster 125d454dbe0SMarkus Armbruster /* Trailing comma is ignored */ 126d454dbe0SMarkus Armbruster qdict = keyval_parse("x=y,", NULL, &error_abort); 127d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 128d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, "y"); 129cb3e7f08SMarc-André Lureau qobject_unref(qdict); 130d454dbe0SMarkus Armbruster 131d454dbe0SMarkus Armbruster /* Except when it isn't */ 132d454dbe0SMarkus Armbruster qdict = keyval_parse(",", NULL, &err); 133d454dbe0SMarkus Armbruster error_free_or_abort(&err); 134d454dbe0SMarkus Armbruster g_assert(!qdict); 135d454dbe0SMarkus Armbruster 136d454dbe0SMarkus Armbruster /* Value containing ,id= not misinterpreted as qemu_opts_parse() does */ 137d454dbe0SMarkus Armbruster qdict = keyval_parse("x=,,id=bar", NULL, &error_abort); 138d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 139d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "x"), ==, ",id=bar"); 140cb3e7f08SMarc-André Lureau qobject_unref(qdict); 141d454dbe0SMarkus Armbruster 142d454dbe0SMarkus Armbruster /* Anti-social ID is left to caller (qemu_opts_parse() rejects it) */ 143d454dbe0SMarkus Armbruster qdict = keyval_parse("id=666", NULL, &error_abort); 144d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 145d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "id"), ==, "666"); 146cb3e7f08SMarc-André Lureau qobject_unref(qdict); 147d454dbe0SMarkus Armbruster 148d454dbe0SMarkus Armbruster /* Implied value not supported (unlike qemu_opts_parse()) */ 149d454dbe0SMarkus Armbruster qdict = keyval_parse("an,noaus,noaus=", NULL, &err); 150d454dbe0SMarkus Armbruster error_free_or_abort(&err); 151d454dbe0SMarkus Armbruster g_assert(!qdict); 152d454dbe0SMarkus Armbruster 153d454dbe0SMarkus Armbruster /* Implied value, key "no" (qemu_opts_parse(): negated empty key) */ 154d454dbe0SMarkus Armbruster qdict = keyval_parse("no", NULL, &err); 155d454dbe0SMarkus Armbruster error_free_or_abort(&err); 156d454dbe0SMarkus Armbruster g_assert(!qdict); 157d454dbe0SMarkus Armbruster 158d454dbe0SMarkus Armbruster /* Implied key */ 159d454dbe0SMarkus Armbruster qdict = keyval_parse("an,aus=off,noaus=", "implied", &error_abort); 160d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 3); 161d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "an"); 162d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "aus"), ==, "off"); 163d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "noaus"), ==, ""); 164cb3e7f08SMarc-André Lureau qobject_unref(qdict); 165d454dbe0SMarkus Armbruster 166d454dbe0SMarkus Armbruster /* Implied dotted key */ 167d454dbe0SMarkus Armbruster qdict = keyval_parse("val", "eins.zwei", &error_abort); 168d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 169d454dbe0SMarkus Armbruster sub_qdict = qdict_get_qdict(qdict, "eins"); 170d454dbe0SMarkus Armbruster g_assert(sub_qdict); 171d454dbe0SMarkus Armbruster g_assert_cmpuint(qdict_size(sub_qdict), ==, 1); 172d454dbe0SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(sub_qdict, "zwei"), ==, "val"); 173cb3e7f08SMarc-André Lureau qobject_unref(qdict); 174d454dbe0SMarkus Armbruster 175d454dbe0SMarkus Armbruster /* Implied key with empty value (qemu_opts_parse() accepts this) */ 176d454dbe0SMarkus Armbruster qdict = keyval_parse(",", "implied", &err); 177d454dbe0SMarkus Armbruster error_free_or_abort(&err); 178d454dbe0SMarkus Armbruster g_assert(!qdict); 179d454dbe0SMarkus Armbruster 180d454dbe0SMarkus Armbruster /* Likewise (qemu_opts_parse(): implied key with comma value) */ 181d454dbe0SMarkus Armbruster qdict = keyval_parse(",,,a=1", "implied", &err); 182d454dbe0SMarkus Armbruster error_free_or_abort(&err); 183d454dbe0SMarkus Armbruster g_assert(!qdict); 184d454dbe0SMarkus Armbruster 185*ce40cbf1SMarkus Armbruster /* Implied key's value can't have comma (qemu_opts_parse(): it can) */ 186*ce40cbf1SMarkus Armbruster /* BUG: it can */ 187*ce40cbf1SMarkus Armbruster qdict = keyval_parse("val,,ue", "implied", &error_abort); 188*ce40cbf1SMarkus Armbruster g_assert_cmpuint(qdict_size(qdict), ==, 1); 189*ce40cbf1SMarkus Armbruster g_assert_cmpstr(qdict_get_try_str(qdict, "implied"), ==, "val,ue"); 190*ce40cbf1SMarkus Armbruster qobject_unref(qdict); 191*ce40cbf1SMarkus Armbruster 192d454dbe0SMarkus Armbruster /* Empty key is not an implied key */ 193d454dbe0SMarkus Armbruster qdict = keyval_parse("=val", "implied", &err); 194d454dbe0SMarkus Armbruster error_free_or_abort(&err); 195d454dbe0SMarkus Armbruster g_assert(!qdict); 196d454dbe0SMarkus Armbruster } 197d454dbe0SMarkus Armbruster 1980b2c1beeSMarkus Armbruster static void check_list012(QList *qlist) 1990b2c1beeSMarkus Armbruster { 2000b2c1beeSMarkus Armbruster static const char *expected[] = { "null", "eins", "zwei" }; 2010b2c1beeSMarkus Armbruster int i; 2020b2c1beeSMarkus Armbruster QString *qstr; 2030b2c1beeSMarkus Armbruster 2040b2c1beeSMarkus Armbruster g_assert(qlist); 2050b2c1beeSMarkus Armbruster for (i = 0; i < ARRAY_SIZE(expected); i++) { 2067dc847ebSMax Reitz qstr = qobject_to(QString, qlist_pop(qlist)); 2070b2c1beeSMarkus Armbruster g_assert(qstr); 2080b2c1beeSMarkus Armbruster g_assert_cmpstr(qstring_get_str(qstr), ==, expected[i]); 209cb3e7f08SMarc-André Lureau qobject_unref(qstr); 2100b2c1beeSMarkus Armbruster } 2110b2c1beeSMarkus Armbruster g_assert(qlist_empty(qlist)); 2120b2c1beeSMarkus Armbruster } 2130b2c1beeSMarkus Armbruster 2140b2c1beeSMarkus Armbruster static void test_keyval_parse_list(void) 2150b2c1beeSMarkus Armbruster { 2160b2c1beeSMarkus Armbruster Error *err = NULL; 2170b2c1beeSMarkus Armbruster QDict *qdict, *sub_qdict; 2180b2c1beeSMarkus Armbruster 2190b2c1beeSMarkus Armbruster /* Root can't be a list */ 2200b2c1beeSMarkus Armbruster qdict = keyval_parse("0=1", NULL, &err); 2210b2c1beeSMarkus Armbruster error_free_or_abort(&err); 2220b2c1beeSMarkus Armbruster g_assert(!qdict); 2230b2c1beeSMarkus Armbruster 2240b2c1beeSMarkus Armbruster /* List elements need not be in order */ 2250b2c1beeSMarkus Armbruster qdict = keyval_parse("list.0=null,list.2=zwei,list.1=eins", 2260b2c1beeSMarkus Armbruster NULL, &error_abort); 2270b2c1beeSMarkus Armbruster g_assert_cmpint(qdict_size(qdict), ==, 1); 2280b2c1beeSMarkus Armbruster check_list012(qdict_get_qlist(qdict, "list")); 229cb3e7f08SMarc-André Lureau qobject_unref(qdict); 2300b2c1beeSMarkus Armbruster 2310b2c1beeSMarkus Armbruster /* Multiple indexes, last one wins */ 232b2cd5b92SMarkus Armbruster qdict = keyval_parse("list.1=goner,list.0=null,list.01=eins,list.2=zwei", 2330b2c1beeSMarkus Armbruster NULL, &error_abort); 2340b2c1beeSMarkus Armbruster g_assert_cmpint(qdict_size(qdict), ==, 1); 2350b2c1beeSMarkus Armbruster check_list012(qdict_get_qlist(qdict, "list")); 236cb3e7f08SMarc-André Lureau qobject_unref(qdict); 2370b2c1beeSMarkus Armbruster 2380b2c1beeSMarkus Armbruster /* List at deeper nesting */ 239b2cd5b92SMarkus Armbruster qdict = keyval_parse("a.list.1=eins,a.list.00=null,a.list.2=zwei", 2400b2c1beeSMarkus Armbruster NULL, &error_abort); 2410b2c1beeSMarkus Armbruster g_assert_cmpint(qdict_size(qdict), ==, 1); 2420b2c1beeSMarkus Armbruster sub_qdict = qdict_get_qdict(qdict, "a"); 2430b2c1beeSMarkus Armbruster g_assert_cmpint(qdict_size(sub_qdict), ==, 1); 2440b2c1beeSMarkus Armbruster check_list012(qdict_get_qlist(sub_qdict, "list")); 245cb3e7f08SMarc-André Lureau qobject_unref(qdict); 2460b2c1beeSMarkus Armbruster 2470b2c1beeSMarkus Armbruster /* Inconsistent dotted keys: both list and dictionary */ 2480b2c1beeSMarkus Armbruster qdict = keyval_parse("a.b.c=1,a.b.0=2", NULL, &err); 2490b2c1beeSMarkus Armbruster error_free_or_abort(&err); 2500b2c1beeSMarkus Armbruster g_assert(!qdict); 2510b2c1beeSMarkus Armbruster qdict = keyval_parse("a.0.c=1,a.b.c=2", NULL, &err); 2520b2c1beeSMarkus Armbruster error_free_or_abort(&err); 2530b2c1beeSMarkus Armbruster g_assert(!qdict); 2540b2c1beeSMarkus Armbruster 2550b2c1beeSMarkus Armbruster /* Missing list indexes */ 256b2cd5b92SMarkus Armbruster qdict = keyval_parse("list.1=lonely", NULL, &err); 2570b2c1beeSMarkus Armbruster error_free_or_abort(&err); 2580b2c1beeSMarkus Armbruster g_assert(!qdict); 2590b2c1beeSMarkus Armbruster qdict = keyval_parse("list.0=null,list.2=eins,list.02=zwei", NULL, &err); 2600b2c1beeSMarkus Armbruster error_free_or_abort(&err); 2610b2c1beeSMarkus Armbruster g_assert(!qdict); 2620b2c1beeSMarkus Armbruster } 2630b2c1beeSMarkus Armbruster 2649e3943f8SMarkus Armbruster static void test_keyval_visit_bool(void) 2659e3943f8SMarkus Armbruster { 2669e3943f8SMarkus Armbruster Error *err = NULL; 2679e3943f8SMarkus Armbruster Visitor *v; 2689e3943f8SMarkus Armbruster QDict *qdict; 2699e3943f8SMarkus Armbruster bool b; 2709e3943f8SMarkus Armbruster 2719e3943f8SMarkus Armbruster qdict = keyval_parse("bool1=on,bool2=off", NULL, &error_abort); 2729e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 273cb3e7f08SMarc-André Lureau qobject_unref(qdict); 2749e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 2759e3943f8SMarkus Armbruster visit_type_bool(v, "bool1", &b, &error_abort); 2769e3943f8SMarkus Armbruster g_assert(b); 2779e3943f8SMarkus Armbruster visit_type_bool(v, "bool2", &b, &error_abort); 2789e3943f8SMarkus Armbruster g_assert(!b); 2799e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 2809e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 2819e3943f8SMarkus Armbruster visit_free(v); 2829e3943f8SMarkus Armbruster 2839e3943f8SMarkus Armbruster qdict = keyval_parse("bool1=offer", NULL, &error_abort); 2849e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 285cb3e7f08SMarc-André Lureau qobject_unref(qdict); 2869e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 2879e3943f8SMarkus Armbruster visit_type_bool(v, "bool1", &b, &err); 2889e3943f8SMarkus Armbruster error_free_or_abort(&err); 2899e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 2909e3943f8SMarkus Armbruster visit_free(v); 2919e3943f8SMarkus Armbruster } 2929e3943f8SMarkus Armbruster 2939e3943f8SMarkus Armbruster static void test_keyval_visit_number(void) 2949e3943f8SMarkus Armbruster { 2959e3943f8SMarkus Armbruster Error *err = NULL; 2969e3943f8SMarkus Armbruster Visitor *v; 2979e3943f8SMarkus Armbruster QDict *qdict; 2989e3943f8SMarkus Armbruster uint64_t u; 2999e3943f8SMarkus Armbruster 3009e3943f8SMarkus Armbruster /* Lower limit zero */ 3019e3943f8SMarkus Armbruster qdict = keyval_parse("number1=0", NULL, &error_abort); 3029e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 303cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3049e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3059e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &error_abort); 3069e3943f8SMarkus Armbruster g_assert_cmpuint(u, ==, 0); 3079e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 3089e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3099e3943f8SMarkus Armbruster visit_free(v); 3109e3943f8SMarkus Armbruster 3119e3943f8SMarkus Armbruster /* Upper limit 2^64-1 */ 3129e3943f8SMarkus Armbruster qdict = keyval_parse("number1=18446744073709551615,number2=-1", 3139e3943f8SMarkus Armbruster NULL, &error_abort); 3149e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 315cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3169e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3179e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &error_abort); 3189e3943f8SMarkus Armbruster g_assert_cmphex(u, ==, UINT64_MAX); 3199e3943f8SMarkus Armbruster visit_type_uint64(v, "number2", &u, &error_abort); 3209e3943f8SMarkus Armbruster g_assert_cmphex(u, ==, UINT64_MAX); 3219e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 3229e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3239e3943f8SMarkus Armbruster visit_free(v); 3249e3943f8SMarkus Armbruster 3259e3943f8SMarkus Armbruster /* Above upper limit */ 3269e3943f8SMarkus Armbruster qdict = keyval_parse("number1=18446744073709551616", 3279e3943f8SMarkus Armbruster NULL, &error_abort); 3289e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 329cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3309e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3319e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &err); 3329e3943f8SMarkus Armbruster error_free_or_abort(&err); 3339e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3349e3943f8SMarkus Armbruster visit_free(v); 3359e3943f8SMarkus Armbruster 3369e3943f8SMarkus Armbruster /* Below lower limit */ 3379e3943f8SMarkus Armbruster qdict = keyval_parse("number1=-18446744073709551616", 3389e3943f8SMarkus Armbruster NULL, &error_abort); 3399e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 340cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3419e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3429e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &err); 3439e3943f8SMarkus Armbruster error_free_or_abort(&err); 3449e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3459e3943f8SMarkus Armbruster visit_free(v); 3469e3943f8SMarkus Armbruster 3479e3943f8SMarkus Armbruster /* Hex and octal */ 3489e3943f8SMarkus Armbruster qdict = keyval_parse("number1=0x2a,number2=052", 3499e3943f8SMarkus Armbruster NULL, &error_abort); 3509e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 351cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3529e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3539e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &error_abort); 3549e3943f8SMarkus Armbruster g_assert_cmpuint(u, ==, 42); 3559e3943f8SMarkus Armbruster visit_type_uint64(v, "number2", &u, &error_abort); 3569e3943f8SMarkus Armbruster g_assert_cmpuint(u, ==, 42); 3579e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 3589e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3599e3943f8SMarkus Armbruster visit_free(v); 3609e3943f8SMarkus Armbruster 3619e3943f8SMarkus Armbruster /* Trailing crap */ 3629e3943f8SMarkus Armbruster qdict = keyval_parse("number1=3.14,number2=08", 3639e3943f8SMarkus Armbruster NULL, &error_abort); 3649e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 365cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3669e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3679e3943f8SMarkus Armbruster visit_type_uint64(v, "number1", &u, &err); 3689e3943f8SMarkus Armbruster error_free_or_abort(&err); 3699e3943f8SMarkus Armbruster visit_type_uint64(v, "number2", &u, &err); 3709e3943f8SMarkus Armbruster error_free_or_abort(&err); 3719e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3729e3943f8SMarkus Armbruster visit_free(v); 3739e3943f8SMarkus Armbruster } 3749e3943f8SMarkus Armbruster 3759e3943f8SMarkus Armbruster static void test_keyval_visit_size(void) 3769e3943f8SMarkus Armbruster { 3779e3943f8SMarkus Armbruster Error *err = NULL; 3789e3943f8SMarkus Armbruster Visitor *v; 3799e3943f8SMarkus Armbruster QDict *qdict; 3809e3943f8SMarkus Armbruster uint64_t sz; 3819e3943f8SMarkus Armbruster 3829e3943f8SMarkus Armbruster /* Lower limit zero */ 3839e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=0", NULL, &error_abort); 3849e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 385cb3e7f08SMarc-André Lureau qobject_unref(qdict); 3869e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 3879e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 3889e3943f8SMarkus Armbruster g_assert_cmpuint(sz, ==, 0); 3899e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 3909e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 3919e3943f8SMarkus Armbruster visit_free(v); 3929e3943f8SMarkus Armbruster 3939e3943f8SMarkus Armbruster /* Note: precision is 53 bits since we're parsing with strtod() */ 3949e3943f8SMarkus Armbruster 3959e3943f8SMarkus Armbruster /* Around limit of precision: 2^53-1, 2^53, 2^53+1 */ 3969e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=9007199254740991," 3979e3943f8SMarkus Armbruster "sz2=9007199254740992," 3989e3943f8SMarkus Armbruster "sz3=9007199254740993", 3999e3943f8SMarkus Armbruster NULL, &error_abort); 4009e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 401cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4029e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4039e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 4049e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0x1fffffffffffff); 4059e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &error_abort); 4069e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0x20000000000000); 4079e3943f8SMarkus Armbruster visit_type_size(v, "sz3", &sz, &error_abort); 4089e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0x20000000000000); 4099e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 4109e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4119e3943f8SMarkus Armbruster visit_free(v); 4129e3943f8SMarkus Armbruster 4139e3943f8SMarkus Armbruster /* Close to signed upper limit 0x7ffffffffffffc00 (53 msbs set) */ 4149e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=9223372036854774784," /* 7ffffffffffffc00 */ 4159e3943f8SMarkus Armbruster "sz2=9223372036854775295", /* 7ffffffffffffdff */ 4169e3943f8SMarkus Armbruster NULL, &error_abort); 4179e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 418cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4199e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4209e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 4219e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0x7ffffffffffffc00); 4229e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &error_abort); 4239e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0x7ffffffffffffc00); 4249e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 4259e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4269e3943f8SMarkus Armbruster visit_free(v); 4279e3943f8SMarkus Armbruster 4289e3943f8SMarkus Armbruster /* Close to actual upper limit 0xfffffffffffff800 (53 msbs set) */ 4299e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=18446744073709549568," /* fffffffffffff800 */ 4309e3943f8SMarkus Armbruster "sz2=18446744073709550591", /* fffffffffffffbff */ 4319e3943f8SMarkus Armbruster NULL, &error_abort); 4329e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 433cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4349e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4359e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 4369e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0xfffffffffffff800); 4379e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &error_abort); 4389e3943f8SMarkus Armbruster g_assert_cmphex(sz, ==, 0xfffffffffffff800); 4399e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 4409e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4419e3943f8SMarkus Armbruster visit_free(v); 4429e3943f8SMarkus Armbruster 4439e3943f8SMarkus Armbruster /* Beyond limits */ 4449e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=-1," 4459e3943f8SMarkus Armbruster "sz2=18446744073709550592", /* fffffffffffffc00 */ 4469e3943f8SMarkus Armbruster NULL, &error_abort); 4479e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 448cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4499e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4509e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &err); 4519e3943f8SMarkus Armbruster error_free_or_abort(&err); 4529e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &err); 4539e3943f8SMarkus Armbruster error_free_or_abort(&err); 4549e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4559e3943f8SMarkus Armbruster visit_free(v); 4569e3943f8SMarkus Armbruster 4579e3943f8SMarkus Armbruster /* Suffixes */ 4589e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=8b,sz2=1.5k,sz3=2M,sz4=0.1G,sz5=16777215T", 4599e3943f8SMarkus Armbruster NULL, &error_abort); 4609e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 461cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4629e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4639e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &error_abort); 4649e3943f8SMarkus Armbruster g_assert_cmpuint(sz, ==, 8); 4659e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &error_abort); 4669e3943f8SMarkus Armbruster g_assert_cmpuint(sz, ==, 1536); 4679e3943f8SMarkus Armbruster visit_type_size(v, "sz3", &sz, &error_abort); 468d23b6caaSPhilippe Mathieu-Daudé g_assert_cmphex(sz, ==, 2 * MiB); 4699e3943f8SMarkus Armbruster visit_type_size(v, "sz4", &sz, &error_abort); 470d23b6caaSPhilippe Mathieu-Daudé g_assert_cmphex(sz, ==, GiB / 10); 4719e3943f8SMarkus Armbruster visit_type_size(v, "sz5", &sz, &error_abort); 472d23b6caaSPhilippe Mathieu-Daudé g_assert_cmphex(sz, ==, 16777215ULL * TiB); 4739e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 4749e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4759e3943f8SMarkus Armbruster visit_free(v); 4769e3943f8SMarkus Armbruster 4779e3943f8SMarkus Armbruster /* Beyond limit with suffix */ 4789e3943f8SMarkus Armbruster qdict = keyval_parse("sz1=16777216T", NULL, &error_abort); 4799e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 480cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4819e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4829e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &err); 4839e3943f8SMarkus Armbruster error_free_or_abort(&err); 4849e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4859e3943f8SMarkus Armbruster visit_free(v); 4869e3943f8SMarkus Armbruster 4879e3943f8SMarkus Armbruster /* Trailing crap */ 488877e2cfbSMarkus Armbruster qdict = keyval_parse("sz1=0Z,sz2=16Gi", NULL, &error_abort); 4899e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 490cb3e7f08SMarc-André Lureau qobject_unref(qdict); 4919e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 4929e3943f8SMarkus Armbruster visit_type_size(v, "sz1", &sz, &err); 4939e3943f8SMarkus Armbruster error_free_or_abort(&err); 4949e3943f8SMarkus Armbruster visit_type_size(v, "sz2", &sz, &err); 4959e3943f8SMarkus Armbruster error_free_or_abort(&err); 4969e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 4979e3943f8SMarkus Armbruster visit_free(v); 4989e3943f8SMarkus Armbruster } 4999e3943f8SMarkus Armbruster 5009e3943f8SMarkus Armbruster static void test_keyval_visit_dict(void) 5019e3943f8SMarkus Armbruster { 5029e3943f8SMarkus Armbruster Error *err = NULL; 5039e3943f8SMarkus Armbruster Visitor *v; 5049e3943f8SMarkus Armbruster QDict *qdict; 5059e3943f8SMarkus Armbruster int64_t i; 5069e3943f8SMarkus Armbruster 5079e3943f8SMarkus Armbruster qdict = keyval_parse("a.b.c=1,a.b.c=2,d=3", NULL, &error_abort); 5089e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 509cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5109e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5119e3943f8SMarkus Armbruster visit_start_struct(v, "a", NULL, 0, &error_abort); 5129e3943f8SMarkus Armbruster visit_start_struct(v, "b", NULL, 0, &error_abort); 5139e3943f8SMarkus Armbruster visit_type_int(v, "c", &i, &error_abort); 5149e3943f8SMarkus Armbruster g_assert_cmpint(i, ==, 2); 5159e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 5169e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5179e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 5189e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5199e3943f8SMarkus Armbruster visit_type_int(v, "d", &i, &error_abort); 5209e3943f8SMarkus Armbruster g_assert_cmpint(i, ==, 3); 5219e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 5229e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5239e3943f8SMarkus Armbruster visit_free(v); 5249e3943f8SMarkus Armbruster 5259e3943f8SMarkus Armbruster qdict = keyval_parse("a.b=", NULL, &error_abort); 5269e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 527cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5289e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5299e3943f8SMarkus Armbruster visit_start_struct(v, "a", NULL, 0, &error_abort); 5309e3943f8SMarkus Armbruster visit_type_int(v, "c", &i, &err); /* a.c missing */ 5319e3943f8SMarkus Armbruster error_free_or_abort(&err); 5329e3943f8SMarkus Armbruster visit_check_struct(v, &err); 5339e3943f8SMarkus Armbruster error_free_or_abort(&err); /* a.b unexpected */ 5349e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5359e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 5369e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 5379e3943f8SMarkus Armbruster visit_free(v); 5389e3943f8SMarkus Armbruster } 5399e3943f8SMarkus Armbruster 5400b2c1beeSMarkus Armbruster static void test_keyval_visit_list(void) 5410b2c1beeSMarkus Armbruster { 5420b2c1beeSMarkus Armbruster Error *err = NULL; 5430b2c1beeSMarkus Armbruster Visitor *v; 5440b2c1beeSMarkus Armbruster QDict *qdict; 5450b2c1beeSMarkus Armbruster char *s; 5460b2c1beeSMarkus Armbruster 5470b2c1beeSMarkus Armbruster qdict = keyval_parse("a.0=,a.1=I,a.2.0=II", NULL, &error_abort); 5480b2c1beeSMarkus Armbruster /* TODO empty list */ 5490b2c1beeSMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 550cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5510b2c1beeSMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5520b2c1beeSMarkus Armbruster visit_start_list(v, "a", NULL, 0, &error_abort); 5530b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &error_abort); 5540b2c1beeSMarkus Armbruster g_assert_cmpstr(s, ==, ""); 5550b2c1beeSMarkus Armbruster g_free(s); 5560b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &error_abort); 5570b2c1beeSMarkus Armbruster g_assert_cmpstr(s, ==, "I"); 5580b2c1beeSMarkus Armbruster g_free(s); 5590b2c1beeSMarkus Armbruster visit_start_list(v, NULL, NULL, 0, &error_abort); 5600b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &error_abort); 5610b2c1beeSMarkus Armbruster g_assert_cmpstr(s, ==, "II"); 5620b2c1beeSMarkus Armbruster g_free(s); 5630b2c1beeSMarkus Armbruster visit_check_list(v, &error_abort); 5640b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 5650b2c1beeSMarkus Armbruster visit_check_list(v, &error_abort); 5660b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 5670b2c1beeSMarkus Armbruster visit_check_struct(v, &error_abort); 5680b2c1beeSMarkus Armbruster visit_end_struct(v, NULL); 5690b2c1beeSMarkus Armbruster visit_free(v); 5700b2c1beeSMarkus Armbruster 5710b2c1beeSMarkus Armbruster qdict = keyval_parse("a.0=,b.0.0=head", NULL, &error_abort); 5720b2c1beeSMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 573cb3e7f08SMarc-André Lureau qobject_unref(qdict); 5740b2c1beeSMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 5750b2c1beeSMarkus Armbruster visit_start_list(v, "a", NULL, 0, &error_abort); 5760b2c1beeSMarkus Armbruster visit_check_list(v, &err); /* a[0] unexpected */ 5770b2c1beeSMarkus Armbruster error_free_or_abort(&err); 5780b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 5790b2c1beeSMarkus Armbruster visit_start_list(v, "b", NULL, 0, &error_abort); 5800b2c1beeSMarkus Armbruster visit_start_list(v, NULL, NULL, 0, &error_abort); 5810b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &error_abort); 5820b2c1beeSMarkus Armbruster g_assert_cmpstr(s, ==, "head"); 5830b2c1beeSMarkus Armbruster g_free(s); 5840b2c1beeSMarkus Armbruster visit_type_str(v, NULL, &s, &err); /* b[0][1] missing */ 5850b2c1beeSMarkus Armbruster error_free_or_abort(&err); 5860b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 5870b2c1beeSMarkus Armbruster visit_end_list(v, NULL); 5880b2c1beeSMarkus Armbruster visit_check_struct(v, &error_abort); 5890b2c1beeSMarkus Armbruster visit_end_struct(v, NULL); 5900b2c1beeSMarkus Armbruster visit_free(v); 5910b2c1beeSMarkus Armbruster } 5920b2c1beeSMarkus Armbruster 5939e3943f8SMarkus Armbruster static void test_keyval_visit_optional(void) 5949e3943f8SMarkus Armbruster { 5959e3943f8SMarkus Armbruster Visitor *v; 5969e3943f8SMarkus Armbruster QDict *qdict; 5979e3943f8SMarkus Armbruster bool present; 5989e3943f8SMarkus Armbruster int64_t i; 5999e3943f8SMarkus Armbruster 6009e3943f8SMarkus Armbruster qdict = keyval_parse("a.b=1", NULL, &error_abort); 6019e3943f8SMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 602cb3e7f08SMarc-André Lureau qobject_unref(qdict); 6039e3943f8SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 6049e3943f8SMarkus Armbruster visit_optional(v, "b", &present); 6059e3943f8SMarkus Armbruster g_assert(!present); /* b missing */ 6069e3943f8SMarkus Armbruster visit_optional(v, "a", &present); 6079e3943f8SMarkus Armbruster g_assert(present); /* a present */ 6089e3943f8SMarkus Armbruster visit_start_struct(v, "a", NULL, 0, &error_abort); 6099e3943f8SMarkus Armbruster visit_optional(v, "b", &present); 6109e3943f8SMarkus Armbruster g_assert(present); /* a.b present */ 6119e3943f8SMarkus Armbruster visit_type_int(v, "b", &i, &error_abort); 6129e3943f8SMarkus Armbruster g_assert_cmpint(i, ==, 1); 6139e3943f8SMarkus Armbruster visit_optional(v, "a", &present); 6149e3943f8SMarkus Armbruster g_assert(!present); /* a.a missing */ 6159e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 6169e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 6179e3943f8SMarkus Armbruster visit_check_struct(v, &error_abort); 6189e3943f8SMarkus Armbruster visit_end_struct(v, NULL); 6199e3943f8SMarkus Armbruster visit_free(v); 6209e3943f8SMarkus Armbruster } 6219e3943f8SMarkus Armbruster 622599c156bSMarkus Armbruster static void test_keyval_visit_alternate(void) 623599c156bSMarkus Armbruster { 624599c156bSMarkus Armbruster Error *err = NULL; 625599c156bSMarkus Armbruster Visitor *v; 626599c156bSMarkus Armbruster QDict *qdict; 627c0644771SMarkus Armbruster AltStrObj *aso; 6287c877c80SMarc-André Lureau AltNumEnum *ane; 629c0644771SMarkus Armbruster AltEnumBool *aeb; 630599c156bSMarkus Armbruster 631599c156bSMarkus Armbruster /* 632599c156bSMarkus Armbruster * Can't do scalar alternate variants other than string. You get 633599c156bSMarkus Armbruster * the string variant if there is one, else an error. 634c0644771SMarkus Armbruster * TODO make it work for unambiguous cases like AltEnumBool below 635599c156bSMarkus Armbruster */ 636c0644771SMarkus Armbruster qdict = keyval_parse("a=1,b=2,c=on", NULL, &error_abort); 637599c156bSMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 638cb3e7f08SMarc-André Lureau qobject_unref(qdict); 639599c156bSMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 640c0644771SMarkus Armbruster visit_type_AltStrObj(v, "a", &aso, &error_abort); 641c0644771SMarkus Armbruster g_assert_cmpint(aso->type, ==, QTYPE_QSTRING); 642c0644771SMarkus Armbruster g_assert_cmpstr(aso->u.s, ==, "1"); 643c0644771SMarkus Armbruster qapi_free_AltStrObj(aso); 6447c877c80SMarc-André Lureau visit_type_AltNumEnum(v, "b", &ane, &err); 645c0644771SMarkus Armbruster error_free_or_abort(&err); 646c0644771SMarkus Armbruster visit_type_AltEnumBool(v, "c", &aeb, &err); 647599c156bSMarkus Armbruster error_free_or_abort(&err); 648599c156bSMarkus Armbruster visit_end_struct(v, NULL); 649599c156bSMarkus Armbruster visit_free(v); 650599c156bSMarkus Armbruster } 651599c156bSMarkus Armbruster 652599c156bSMarkus Armbruster static void test_keyval_visit_any(void) 653599c156bSMarkus Armbruster { 654599c156bSMarkus Armbruster Visitor *v; 655599c156bSMarkus Armbruster QDict *qdict; 656599c156bSMarkus Armbruster QObject *any; 657599c156bSMarkus Armbruster QList *qlist; 658599c156bSMarkus Armbruster QString *qstr; 659599c156bSMarkus Armbruster 660599c156bSMarkus Armbruster qdict = keyval_parse("a.0=null,a.1=1", NULL, &error_abort); 661599c156bSMarkus Armbruster v = qobject_input_visitor_new_keyval(QOBJECT(qdict)); 662cb3e7f08SMarc-André Lureau qobject_unref(qdict); 663599c156bSMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, &error_abort); 664599c156bSMarkus Armbruster visit_type_any(v, "a", &any, &error_abort); 6657dc847ebSMax Reitz qlist = qobject_to(QList, any); 666599c156bSMarkus Armbruster g_assert(qlist); 6677dc847ebSMax Reitz qstr = qobject_to(QString, qlist_pop(qlist)); 668599c156bSMarkus Armbruster g_assert_cmpstr(qstring_get_str(qstr), ==, "null"); 669cb3e7f08SMarc-André Lureau qobject_unref(qstr); 6707dc847ebSMax Reitz qstr = qobject_to(QString, qlist_pop(qlist)); 671599c156bSMarkus Armbruster g_assert_cmpstr(qstring_get_str(qstr), ==, "1"); 672599c156bSMarkus Armbruster g_assert(qlist_empty(qlist)); 673cb3e7f08SMarc-André Lureau qobject_unref(qstr); 674cb3e7f08SMarc-André Lureau qobject_unref(any); 675599c156bSMarkus Armbruster visit_check_struct(v, &error_abort); 676599c156bSMarkus Armbruster visit_end_struct(v, NULL); 677599c156bSMarkus Armbruster visit_free(v); 678599c156bSMarkus Armbruster } 679599c156bSMarkus Armbruster 680d454dbe0SMarkus Armbruster int main(int argc, char *argv[]) 681d454dbe0SMarkus Armbruster { 682d454dbe0SMarkus Armbruster g_test_init(&argc, &argv, NULL); 683d454dbe0SMarkus Armbruster g_test_add_func("/keyval/keyval_parse", test_keyval_parse); 6840b2c1beeSMarkus Armbruster g_test_add_func("/keyval/keyval_parse/list", test_keyval_parse_list); 6859e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/bool", test_keyval_visit_bool); 6869e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/number", test_keyval_visit_number); 6879e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/size", test_keyval_visit_size); 6889e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/dict", test_keyval_visit_dict); 6890b2c1beeSMarkus Armbruster g_test_add_func("/keyval/visit/list", test_keyval_visit_list); 6909e3943f8SMarkus Armbruster g_test_add_func("/keyval/visit/optional", test_keyval_visit_optional); 691599c156bSMarkus Armbruster g_test_add_func("/keyval/visit/alternate", test_keyval_visit_alternate); 692599c156bSMarkus Armbruster g_test_add_func("/keyval/visit/any", test_keyval_visit_any); 693d454dbe0SMarkus Armbruster g_test_run(); 694d454dbe0SMarkus Armbruster return 0; 695d454dbe0SMarkus Armbruster } 696