xref: /qemu/tests/unit/test-keyval.c (revision ce40cbf11d215dc3f820bf32937f7e44aab4a1e3)
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