xref: /openbmc/qemu/tests/unit/check-block-qdict.c (revision da668aa15b99150a8595c491aee00d5d2426aaf9)
1*da668aa1SThomas Huth /*
2*da668aa1SThomas Huth  * Unit-tests for Block layer QDict extras
3*da668aa1SThomas Huth  *
4*da668aa1SThomas Huth  * Copyright (c) 2013-2018 Red Hat, Inc.
5*da668aa1SThomas Huth  *
6*da668aa1SThomas Huth  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
7*da668aa1SThomas Huth  * See the COPYING.LIB file in the top-level directory.
8*da668aa1SThomas Huth  */
9*da668aa1SThomas Huth 
10*da668aa1SThomas Huth #include "qemu/osdep.h"
11*da668aa1SThomas Huth #include "block/qdict.h"
12*da668aa1SThomas Huth #include "qapi/qmp/qlist.h"
13*da668aa1SThomas Huth #include "qapi/qmp/qnum.h"
14*da668aa1SThomas Huth #include "qapi/error.h"
15*da668aa1SThomas Huth 
16*da668aa1SThomas Huth static void qdict_defaults_test(void)
17*da668aa1SThomas Huth {
18*da668aa1SThomas Huth     QDict *dict, *copy;
19*da668aa1SThomas Huth 
20*da668aa1SThomas Huth     dict = qdict_new();
21*da668aa1SThomas Huth     copy = qdict_new();
22*da668aa1SThomas Huth 
23*da668aa1SThomas Huth     qdict_set_default_str(dict, "foo", "abc");
24*da668aa1SThomas Huth     qdict_set_default_str(dict, "foo", "def");
25*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(dict, "foo"), ==, "abc");
26*da668aa1SThomas Huth     qdict_set_default_str(dict, "bar", "ghi");
27*da668aa1SThomas Huth 
28*da668aa1SThomas Huth     qdict_copy_default(copy, dict, "foo");
29*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "foo"), ==, "abc");
30*da668aa1SThomas Huth     qdict_set_default_str(copy, "bar", "xyz");
31*da668aa1SThomas Huth     qdict_copy_default(copy, dict, "bar");
32*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "bar"), ==, "xyz");
33*da668aa1SThomas Huth 
34*da668aa1SThomas Huth     qobject_unref(copy);
35*da668aa1SThomas Huth     qobject_unref(dict);
36*da668aa1SThomas Huth }
37*da668aa1SThomas Huth 
38*da668aa1SThomas Huth static void qdict_flatten_test(void)
39*da668aa1SThomas Huth {
40*da668aa1SThomas Huth     QList *e_1 = qlist_new();
41*da668aa1SThomas Huth     QList *e = qlist_new();
42*da668aa1SThomas Huth     QDict *e_1_2 = qdict_new();
43*da668aa1SThomas Huth     QDict *f = qdict_new();
44*da668aa1SThomas Huth     QList *y = qlist_new();
45*da668aa1SThomas Huth     QDict *z = qdict_new();
46*da668aa1SThomas Huth     QDict *root = qdict_new();
47*da668aa1SThomas Huth 
48*da668aa1SThomas Huth     /*
49*da668aa1SThomas Huth      * Test the flattening of
50*da668aa1SThomas Huth      *
51*da668aa1SThomas Huth      * {
52*da668aa1SThomas Huth      *     "e": [
53*da668aa1SThomas Huth      *         42,
54*da668aa1SThomas Huth      *         [
55*da668aa1SThomas Huth      *             23,
56*da668aa1SThomas Huth      *             66,
57*da668aa1SThomas Huth      *             {
58*da668aa1SThomas Huth      *                 "a": 0,
59*da668aa1SThomas Huth      *                 "b": 1
60*da668aa1SThomas Huth      *             }
61*da668aa1SThomas Huth      *         ]
62*da668aa1SThomas Huth      *     ],
63*da668aa1SThomas Huth      *     "f": {
64*da668aa1SThomas Huth      *         "c": 2,
65*da668aa1SThomas Huth      *         "d": 3,
66*da668aa1SThomas Huth      *     },
67*da668aa1SThomas Huth      *     "g": 4,
68*da668aa1SThomas Huth      *     "y": [{}],
69*da668aa1SThomas Huth      *     "z": {"a": []}
70*da668aa1SThomas Huth      * }
71*da668aa1SThomas Huth      *
72*da668aa1SThomas Huth      * to
73*da668aa1SThomas Huth      *
74*da668aa1SThomas Huth      * {
75*da668aa1SThomas Huth      *     "e.0": 42,
76*da668aa1SThomas Huth      *     "e.1.0": 23,
77*da668aa1SThomas Huth      *     "e.1.1": 66,
78*da668aa1SThomas Huth      *     "e.1.2.a": 0,
79*da668aa1SThomas Huth      *     "e.1.2.b": 1,
80*da668aa1SThomas Huth      *     "f.c": 2,
81*da668aa1SThomas Huth      *     "f.d": 3,
82*da668aa1SThomas Huth      *     "g": 4,
83*da668aa1SThomas Huth      *     "y.0": {},
84*da668aa1SThomas Huth      *     "z.a": []
85*da668aa1SThomas Huth      * }
86*da668aa1SThomas Huth      */
87*da668aa1SThomas Huth 
88*da668aa1SThomas Huth     qdict_put_int(e_1_2, "a", 0);
89*da668aa1SThomas Huth     qdict_put_int(e_1_2, "b", 1);
90*da668aa1SThomas Huth 
91*da668aa1SThomas Huth     qlist_append_int(e_1, 23);
92*da668aa1SThomas Huth     qlist_append_int(e_1, 66);
93*da668aa1SThomas Huth     qlist_append(e_1, e_1_2);
94*da668aa1SThomas Huth     qlist_append_int(e, 42);
95*da668aa1SThomas Huth     qlist_append(e, e_1);
96*da668aa1SThomas Huth 
97*da668aa1SThomas Huth     qdict_put_int(f, "c", 2);
98*da668aa1SThomas Huth     qdict_put_int(f, "d", 3);
99*da668aa1SThomas Huth 
100*da668aa1SThomas Huth     qlist_append(y, qdict_new());
101*da668aa1SThomas Huth 
102*da668aa1SThomas Huth     qdict_put(z, "a", qlist_new());
103*da668aa1SThomas Huth 
104*da668aa1SThomas Huth     qdict_put(root, "e", e);
105*da668aa1SThomas Huth     qdict_put(root, "f", f);
106*da668aa1SThomas Huth     qdict_put_int(root, "g", 4);
107*da668aa1SThomas Huth     qdict_put(root, "y", y);
108*da668aa1SThomas Huth     qdict_put(root, "z", z);
109*da668aa1SThomas Huth 
110*da668aa1SThomas Huth     qdict_flatten(root);
111*da668aa1SThomas Huth 
112*da668aa1SThomas Huth     g_assert(qdict_get_int(root, "e.0") == 42);
113*da668aa1SThomas Huth     g_assert(qdict_get_int(root, "e.1.0") == 23);
114*da668aa1SThomas Huth     g_assert(qdict_get_int(root, "e.1.1") == 66);
115*da668aa1SThomas Huth     g_assert(qdict_get_int(root, "e.1.2.a") == 0);
116*da668aa1SThomas Huth     g_assert(qdict_get_int(root, "e.1.2.b") == 1);
117*da668aa1SThomas Huth     g_assert(qdict_get_int(root, "f.c") == 2);
118*da668aa1SThomas Huth     g_assert(qdict_get_int(root, "f.d") == 3);
119*da668aa1SThomas Huth     g_assert(qdict_get_int(root, "g") == 4);
120*da668aa1SThomas Huth     g_assert(!qdict_size(qdict_get_qdict(root, "y.0")));
121*da668aa1SThomas Huth     g_assert(qlist_empty(qdict_get_qlist(root, "z.a")));
122*da668aa1SThomas Huth 
123*da668aa1SThomas Huth     g_assert(qdict_size(root) == 10);
124*da668aa1SThomas Huth 
125*da668aa1SThomas Huth     qobject_unref(root);
126*da668aa1SThomas Huth }
127*da668aa1SThomas Huth 
128*da668aa1SThomas Huth static void qdict_clone_flatten_test(void)
129*da668aa1SThomas Huth {
130*da668aa1SThomas Huth     QDict *dict1 = qdict_new();
131*da668aa1SThomas Huth     QDict *dict2 = qdict_new();
132*da668aa1SThomas Huth     QDict *cloned_dict1;
133*da668aa1SThomas Huth 
134*da668aa1SThomas Huth     /*
135*da668aa1SThomas Huth      * Test that we can clone and flatten
136*da668aa1SThomas Huth      *    { "a": { "b": 42 } }
137*da668aa1SThomas Huth      * without modifying the clone.
138*da668aa1SThomas Huth      */
139*da668aa1SThomas Huth 
140*da668aa1SThomas Huth     qdict_put_int(dict2, "b", 42);
141*da668aa1SThomas Huth     qdict_put(dict1, "a", dict2);
142*da668aa1SThomas Huth 
143*da668aa1SThomas Huth     cloned_dict1 = qdict_clone_shallow(dict1);
144*da668aa1SThomas Huth 
145*da668aa1SThomas Huth     qdict_flatten(dict1);
146*da668aa1SThomas Huth 
147*da668aa1SThomas Huth     g_assert(qdict_size(dict1) == 1);
148*da668aa1SThomas Huth     g_assert(qdict_get_int(dict1, "a.b") == 42);
149*da668aa1SThomas Huth 
150*da668aa1SThomas Huth     g_assert(qdict_size(cloned_dict1) == 1);
151*da668aa1SThomas Huth     g_assert(qdict_get_qdict(cloned_dict1, "a") == dict2);
152*da668aa1SThomas Huth 
153*da668aa1SThomas Huth     g_assert(qdict_size(dict2) == 1);
154*da668aa1SThomas Huth     g_assert(qdict_get_int(dict2, "b") == 42);
155*da668aa1SThomas Huth 
156*da668aa1SThomas Huth     qobject_unref(dict1);
157*da668aa1SThomas Huth     qobject_unref(cloned_dict1);
158*da668aa1SThomas Huth }
159*da668aa1SThomas Huth 
160*da668aa1SThomas Huth static void qdict_array_split_test(void)
161*da668aa1SThomas Huth {
162*da668aa1SThomas Huth     QDict *test_dict = qdict_new();
163*da668aa1SThomas Huth     QDict *dict1, *dict2;
164*da668aa1SThomas Huth     QNum *int1;
165*da668aa1SThomas Huth     QList *test_list;
166*da668aa1SThomas Huth 
167*da668aa1SThomas Huth     /*
168*da668aa1SThomas Huth      * Test the split of
169*da668aa1SThomas Huth      *
170*da668aa1SThomas Huth      * {
171*da668aa1SThomas Huth      *     "1.x": 0,
172*da668aa1SThomas Huth      *     "4.y": 1,
173*da668aa1SThomas Huth      *     "0.a": 42,
174*da668aa1SThomas Huth      *     "o.o": 7,
175*da668aa1SThomas Huth      *     "0.b": 23,
176*da668aa1SThomas Huth      *     "2": 66
177*da668aa1SThomas Huth      * }
178*da668aa1SThomas Huth      *
179*da668aa1SThomas Huth      * to
180*da668aa1SThomas Huth      *
181*da668aa1SThomas Huth      * [
182*da668aa1SThomas Huth      *     {
183*da668aa1SThomas Huth      *         "a": 42,
184*da668aa1SThomas Huth      *         "b": 23
185*da668aa1SThomas Huth      *     },
186*da668aa1SThomas Huth      *     {
187*da668aa1SThomas Huth      *         "x": 0
188*da668aa1SThomas Huth      *     },
189*da668aa1SThomas Huth      *     66
190*da668aa1SThomas Huth      * ]
191*da668aa1SThomas Huth      *
192*da668aa1SThomas Huth      * and
193*da668aa1SThomas Huth      *
194*da668aa1SThomas Huth      * {
195*da668aa1SThomas Huth      *     "4.y": 1,
196*da668aa1SThomas Huth      *     "o.o": 7
197*da668aa1SThomas Huth      * }
198*da668aa1SThomas Huth      *
199*da668aa1SThomas Huth      * (remaining in the old QDict)
200*da668aa1SThomas Huth      *
201*da668aa1SThomas Huth      * This example is given in the comment of qdict_array_split().
202*da668aa1SThomas Huth      */
203*da668aa1SThomas Huth 
204*da668aa1SThomas Huth     qdict_put_int(test_dict, "1.x", 0);
205*da668aa1SThomas Huth     qdict_put_int(test_dict, "4.y", 1);
206*da668aa1SThomas Huth     qdict_put_int(test_dict, "0.a", 42);
207*da668aa1SThomas Huth     qdict_put_int(test_dict, "o.o", 7);
208*da668aa1SThomas Huth     qdict_put_int(test_dict, "0.b", 23);
209*da668aa1SThomas Huth     qdict_put_int(test_dict, "2", 66);
210*da668aa1SThomas Huth 
211*da668aa1SThomas Huth     qdict_array_split(test_dict, &test_list);
212*da668aa1SThomas Huth 
213*da668aa1SThomas Huth     dict1 = qobject_to(QDict, qlist_pop(test_list));
214*da668aa1SThomas Huth     dict2 = qobject_to(QDict, qlist_pop(test_list));
215*da668aa1SThomas Huth     int1 = qobject_to(QNum, qlist_pop(test_list));
216*da668aa1SThomas Huth 
217*da668aa1SThomas Huth     g_assert(dict1);
218*da668aa1SThomas Huth     g_assert(dict2);
219*da668aa1SThomas Huth     g_assert(int1);
220*da668aa1SThomas Huth     g_assert(qlist_empty(test_list));
221*da668aa1SThomas Huth 
222*da668aa1SThomas Huth     qobject_unref(test_list);
223*da668aa1SThomas Huth 
224*da668aa1SThomas Huth     g_assert(qdict_get_int(dict1, "a") == 42);
225*da668aa1SThomas Huth     g_assert(qdict_get_int(dict1, "b") == 23);
226*da668aa1SThomas Huth 
227*da668aa1SThomas Huth     g_assert(qdict_size(dict1) == 2);
228*da668aa1SThomas Huth 
229*da668aa1SThomas Huth     qobject_unref(dict1);
230*da668aa1SThomas Huth 
231*da668aa1SThomas Huth     g_assert(qdict_get_int(dict2, "x") == 0);
232*da668aa1SThomas Huth 
233*da668aa1SThomas Huth     g_assert(qdict_size(dict2) == 1);
234*da668aa1SThomas Huth 
235*da668aa1SThomas Huth     qobject_unref(dict2);
236*da668aa1SThomas Huth 
237*da668aa1SThomas Huth     g_assert_cmpint(qnum_get_int(int1), ==, 66);
238*da668aa1SThomas Huth 
239*da668aa1SThomas Huth     qobject_unref(int1);
240*da668aa1SThomas Huth 
241*da668aa1SThomas Huth     g_assert(qdict_get_int(test_dict, "4.y") == 1);
242*da668aa1SThomas Huth     g_assert(qdict_get_int(test_dict, "o.o") == 7);
243*da668aa1SThomas Huth 
244*da668aa1SThomas Huth     g_assert(qdict_size(test_dict) == 2);
245*da668aa1SThomas Huth 
246*da668aa1SThomas Huth     qobject_unref(test_dict);
247*da668aa1SThomas Huth 
248*da668aa1SThomas Huth     /*
249*da668aa1SThomas Huth      * Test the split of
250*da668aa1SThomas Huth      *
251*da668aa1SThomas Huth      * {
252*da668aa1SThomas Huth      *     "0": 42,
253*da668aa1SThomas Huth      *     "1": 23,
254*da668aa1SThomas Huth      *     "1.x": 84
255*da668aa1SThomas Huth      * }
256*da668aa1SThomas Huth      *
257*da668aa1SThomas Huth      * to
258*da668aa1SThomas Huth      *
259*da668aa1SThomas Huth      * [
260*da668aa1SThomas Huth      *     42
261*da668aa1SThomas Huth      * ]
262*da668aa1SThomas Huth      *
263*da668aa1SThomas Huth      * and
264*da668aa1SThomas Huth      *
265*da668aa1SThomas Huth      * {
266*da668aa1SThomas Huth      *     "1": 23,
267*da668aa1SThomas Huth      *     "1.x": 84
268*da668aa1SThomas Huth      * }
269*da668aa1SThomas Huth      *
270*da668aa1SThomas Huth      * That is, test whether splitting stops if there is both an entry with key
271*da668aa1SThomas Huth      * of "%u" and other entries with keys prefixed "%u." for the same index.
272*da668aa1SThomas Huth      */
273*da668aa1SThomas Huth 
274*da668aa1SThomas Huth     test_dict = qdict_new();
275*da668aa1SThomas Huth 
276*da668aa1SThomas Huth     qdict_put_int(test_dict, "0", 42);
277*da668aa1SThomas Huth     qdict_put_int(test_dict, "1", 23);
278*da668aa1SThomas Huth     qdict_put_int(test_dict, "1.x", 84);
279*da668aa1SThomas Huth 
280*da668aa1SThomas Huth     qdict_array_split(test_dict, &test_list);
281*da668aa1SThomas Huth 
282*da668aa1SThomas Huth     int1 = qobject_to(QNum, qlist_pop(test_list));
283*da668aa1SThomas Huth 
284*da668aa1SThomas Huth     g_assert(int1);
285*da668aa1SThomas Huth     g_assert(qlist_empty(test_list));
286*da668aa1SThomas Huth 
287*da668aa1SThomas Huth     qobject_unref(test_list);
288*da668aa1SThomas Huth 
289*da668aa1SThomas Huth     g_assert_cmpint(qnum_get_int(int1), ==, 42);
290*da668aa1SThomas Huth 
291*da668aa1SThomas Huth     qobject_unref(int1);
292*da668aa1SThomas Huth 
293*da668aa1SThomas Huth     g_assert(qdict_get_int(test_dict, "1") == 23);
294*da668aa1SThomas Huth     g_assert(qdict_get_int(test_dict, "1.x") == 84);
295*da668aa1SThomas Huth 
296*da668aa1SThomas Huth     g_assert(qdict_size(test_dict) == 2);
297*da668aa1SThomas Huth 
298*da668aa1SThomas Huth     qobject_unref(test_dict);
299*da668aa1SThomas Huth }
300*da668aa1SThomas Huth 
301*da668aa1SThomas Huth static void qdict_array_entries_test(void)
302*da668aa1SThomas Huth {
303*da668aa1SThomas Huth     QDict *dict = qdict_new();
304*da668aa1SThomas Huth 
305*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);
306*da668aa1SThomas Huth 
307*da668aa1SThomas Huth     qdict_put_int(dict, "bar", 0);
308*da668aa1SThomas Huth     qdict_put_int(dict, "baz.0", 0);
309*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 0);
310*da668aa1SThomas Huth 
311*da668aa1SThomas Huth     qdict_put_int(dict, "foo.1", 0);
312*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, -EINVAL);
313*da668aa1SThomas Huth     qdict_put_int(dict, "foo.0", 0);
314*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 2);
315*da668aa1SThomas Huth     qdict_put_int(dict, "foo.bar", 0);
316*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, -EINVAL);
317*da668aa1SThomas Huth     qdict_del(dict, "foo.bar");
318*da668aa1SThomas Huth 
319*da668aa1SThomas Huth     qdict_put_int(dict, "foo.2.a", 0);
320*da668aa1SThomas Huth     qdict_put_int(dict, "foo.2.b", 0);
321*da668aa1SThomas Huth     qdict_put_int(dict, "foo.2.c", 0);
322*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, "foo."), ==, 3);
323*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
324*da668aa1SThomas Huth 
325*da668aa1SThomas Huth     qobject_unref(dict);
326*da668aa1SThomas Huth 
327*da668aa1SThomas Huth     dict = qdict_new();
328*da668aa1SThomas Huth     qdict_put_int(dict, "1", 0);
329*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
330*da668aa1SThomas Huth     qdict_put_int(dict, "0", 0);
331*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, ""), ==, 2);
332*da668aa1SThomas Huth     qdict_put_int(dict, "bar", 0);
333*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, ""), ==, -EINVAL);
334*da668aa1SThomas Huth     qdict_del(dict, "bar");
335*da668aa1SThomas Huth 
336*da668aa1SThomas Huth     qdict_put_int(dict, "2.a", 0);
337*da668aa1SThomas Huth     qdict_put_int(dict, "2.b", 0);
338*da668aa1SThomas Huth     qdict_put_int(dict, "2.c", 0);
339*da668aa1SThomas Huth     g_assert_cmpint(qdict_array_entries(dict, ""), ==, 3);
340*da668aa1SThomas Huth 
341*da668aa1SThomas Huth     qobject_unref(dict);
342*da668aa1SThomas Huth }
343*da668aa1SThomas Huth 
344*da668aa1SThomas Huth static void qdict_join_test(void)
345*da668aa1SThomas Huth {
346*da668aa1SThomas Huth     QDict *dict1, *dict2;
347*da668aa1SThomas Huth     bool overwrite = false;
348*da668aa1SThomas Huth     int i;
349*da668aa1SThomas Huth 
350*da668aa1SThomas Huth     dict1 = qdict_new();
351*da668aa1SThomas Huth     dict2 = qdict_new();
352*da668aa1SThomas Huth 
353*da668aa1SThomas Huth     /* Test everything once without overwrite and once with */
354*da668aa1SThomas Huth     do {
355*da668aa1SThomas Huth         /* Test empty dicts */
356*da668aa1SThomas Huth         qdict_join(dict1, dict2, overwrite);
357*da668aa1SThomas Huth 
358*da668aa1SThomas Huth         g_assert(qdict_size(dict1) == 0);
359*da668aa1SThomas Huth         g_assert(qdict_size(dict2) == 0);
360*da668aa1SThomas Huth 
361*da668aa1SThomas Huth         /* First iteration: Test movement */
362*da668aa1SThomas Huth         /* Second iteration: Test empty source and non-empty destination */
363*da668aa1SThomas Huth         qdict_put_int(dict2, "foo", 42);
364*da668aa1SThomas Huth 
365*da668aa1SThomas Huth         for (i = 0; i < 2; i++) {
366*da668aa1SThomas Huth             qdict_join(dict1, dict2, overwrite);
367*da668aa1SThomas Huth 
368*da668aa1SThomas Huth             g_assert(qdict_size(dict1) == 1);
369*da668aa1SThomas Huth             g_assert(qdict_size(dict2) == 0);
370*da668aa1SThomas Huth 
371*da668aa1SThomas Huth             g_assert(qdict_get_int(dict1, "foo") == 42);
372*da668aa1SThomas Huth         }
373*da668aa1SThomas Huth 
374*da668aa1SThomas Huth         /* Test non-empty source and destination without conflict */
375*da668aa1SThomas Huth         qdict_put_int(dict2, "bar", 23);
376*da668aa1SThomas Huth 
377*da668aa1SThomas Huth         qdict_join(dict1, dict2, overwrite);
378*da668aa1SThomas Huth 
379*da668aa1SThomas Huth         g_assert(qdict_size(dict1) == 2);
380*da668aa1SThomas Huth         g_assert(qdict_size(dict2) == 0);
381*da668aa1SThomas Huth 
382*da668aa1SThomas Huth         g_assert(qdict_get_int(dict1, "foo") == 42);
383*da668aa1SThomas Huth         g_assert(qdict_get_int(dict1, "bar") == 23);
384*da668aa1SThomas Huth 
385*da668aa1SThomas Huth         /* Test conflict */
386*da668aa1SThomas Huth         qdict_put_int(dict2, "foo", 84);
387*da668aa1SThomas Huth 
388*da668aa1SThomas Huth         qdict_join(dict1, dict2, overwrite);
389*da668aa1SThomas Huth 
390*da668aa1SThomas Huth         g_assert(qdict_size(dict1) == 2);
391*da668aa1SThomas Huth         g_assert(qdict_size(dict2) == !overwrite);
392*da668aa1SThomas Huth 
393*da668aa1SThomas Huth         g_assert(qdict_get_int(dict1, "foo") == (overwrite ? 84 : 42));
394*da668aa1SThomas Huth         g_assert(qdict_get_int(dict1, "bar") == 23);
395*da668aa1SThomas Huth 
396*da668aa1SThomas Huth         if (!overwrite) {
397*da668aa1SThomas Huth             g_assert(qdict_get_int(dict2, "foo") == 84);
398*da668aa1SThomas Huth         }
399*da668aa1SThomas Huth 
400*da668aa1SThomas Huth         /* Check the references */
401*da668aa1SThomas Huth         g_assert(qdict_get(dict1, "foo")->base.refcnt == 1);
402*da668aa1SThomas Huth         g_assert(qdict_get(dict1, "bar")->base.refcnt == 1);
403*da668aa1SThomas Huth 
404*da668aa1SThomas Huth         if (!overwrite) {
405*da668aa1SThomas Huth             g_assert(qdict_get(dict2, "foo")->base.refcnt == 1);
406*da668aa1SThomas Huth         }
407*da668aa1SThomas Huth 
408*da668aa1SThomas Huth         /* Clean up */
409*da668aa1SThomas Huth         qdict_del(dict1, "foo");
410*da668aa1SThomas Huth         qdict_del(dict1, "bar");
411*da668aa1SThomas Huth 
412*da668aa1SThomas Huth         if (!overwrite) {
413*da668aa1SThomas Huth             qdict_del(dict2, "foo");
414*da668aa1SThomas Huth         }
415*da668aa1SThomas Huth     } while (overwrite ^= true);
416*da668aa1SThomas Huth 
417*da668aa1SThomas Huth     qobject_unref(dict1);
418*da668aa1SThomas Huth     qobject_unref(dict2);
419*da668aa1SThomas Huth }
420*da668aa1SThomas Huth 
421*da668aa1SThomas Huth static void qdict_crumple_test_recursive(void)
422*da668aa1SThomas Huth {
423*da668aa1SThomas Huth     QDict *src, *dst, *rule, *vnc, *acl, *listen;
424*da668aa1SThomas Huth     QDict *empty, *empty_dict, *empty_list_0;
425*da668aa1SThomas Huth     QList *rules, *empty_list, *empty_dict_a;
426*da668aa1SThomas Huth 
427*da668aa1SThomas Huth     src = qdict_new();
428*da668aa1SThomas Huth     qdict_put_str(src, "vnc.listen.addr", "127.0.0.1");
429*da668aa1SThomas Huth     qdict_put_str(src, "vnc.listen.port", "5901");
430*da668aa1SThomas Huth     qdict_put_str(src, "vnc.acl.rules.0.match", "fred");
431*da668aa1SThomas Huth     qdict_put_str(src, "vnc.acl.rules.0.policy", "allow");
432*da668aa1SThomas Huth     qdict_put_str(src, "vnc.acl.rules.1.match", "bob");
433*da668aa1SThomas Huth     qdict_put_str(src, "vnc.acl.rules.1.policy", "deny");
434*da668aa1SThomas Huth     qdict_put_str(src, "vnc.acl.default", "deny");
435*da668aa1SThomas Huth     qdict_put_str(src, "vnc.acl..name", "acl0");
436*da668aa1SThomas Huth     qdict_put_str(src, "vnc.acl.rule..name", "acl0");
437*da668aa1SThomas Huth     qdict_put(src, "empty.dict.a", qlist_new());
438*da668aa1SThomas Huth     qdict_put(src, "empty.list.0", qdict_new());
439*da668aa1SThomas Huth 
440*da668aa1SThomas Huth     dst = qobject_to(QDict, qdict_crumple(src, &error_abort));
441*da668aa1SThomas Huth     g_assert(dst);
442*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(dst), ==, 2);
443*da668aa1SThomas Huth 
444*da668aa1SThomas Huth     vnc = qdict_get_qdict(dst, "vnc");
445*da668aa1SThomas Huth     g_assert(vnc);
446*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(vnc), ==, 3);
447*da668aa1SThomas Huth 
448*da668aa1SThomas Huth     listen = qdict_get_qdict(vnc, "listen");
449*da668aa1SThomas Huth     g_assert(listen);
450*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(listen), ==, 2);
451*da668aa1SThomas Huth     g_assert_cmpstr("127.0.0.1", ==, qdict_get_str(listen, "addr"));
452*da668aa1SThomas Huth     g_assert_cmpstr("5901", ==, qdict_get_str(listen, "port"));
453*da668aa1SThomas Huth 
454*da668aa1SThomas Huth     acl = qdict_get_qdict(vnc, "acl");
455*da668aa1SThomas Huth     g_assert(acl);
456*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(acl), ==, 3);
457*da668aa1SThomas Huth 
458*da668aa1SThomas Huth     rules = qdict_get_qlist(acl, "rules");
459*da668aa1SThomas Huth     g_assert(rules);
460*da668aa1SThomas Huth     g_assert_cmpint(qlist_size(rules), ==, 2);
461*da668aa1SThomas Huth 
462*da668aa1SThomas Huth     rule = qobject_to(QDict, qlist_pop(rules));
463*da668aa1SThomas Huth     g_assert(rule);
464*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(rule), ==, 2);
465*da668aa1SThomas Huth     g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match"));
466*da668aa1SThomas Huth     g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy"));
467*da668aa1SThomas Huth     qobject_unref(rule);
468*da668aa1SThomas Huth 
469*da668aa1SThomas Huth     rule = qobject_to(QDict, qlist_pop(rules));
470*da668aa1SThomas Huth     g_assert(rule);
471*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(rule), ==, 2);
472*da668aa1SThomas Huth     g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match"));
473*da668aa1SThomas Huth     g_assert_cmpstr("deny", ==, qdict_get_str(rule, "policy"));
474*da668aa1SThomas Huth     qobject_unref(rule);
475*da668aa1SThomas Huth 
476*da668aa1SThomas Huth     /* With recursive crumpling, we should see all names unescaped */
477*da668aa1SThomas Huth     g_assert_cmpstr("acl0", ==, qdict_get_str(vnc, "acl.name"));
478*da668aa1SThomas Huth     g_assert_cmpstr("acl0", ==, qdict_get_str(acl, "rule.name"));
479*da668aa1SThomas Huth 
480*da668aa1SThomas Huth     empty = qdict_get_qdict(dst, "empty");
481*da668aa1SThomas Huth     g_assert(empty);
482*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(empty), ==, 2);
483*da668aa1SThomas Huth     empty_dict = qdict_get_qdict(empty, "dict");
484*da668aa1SThomas Huth     g_assert(empty_dict);
485*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(empty_dict), ==, 1);
486*da668aa1SThomas Huth     empty_dict_a = qdict_get_qlist(empty_dict, "a");
487*da668aa1SThomas Huth     g_assert(empty_dict_a && qlist_empty(empty_dict_a));
488*da668aa1SThomas Huth     empty_list = qdict_get_qlist(empty, "list");
489*da668aa1SThomas Huth     g_assert(empty_list);
490*da668aa1SThomas Huth     g_assert_cmpint(qlist_size(empty_list), ==, 1);
491*da668aa1SThomas Huth     empty_list_0 = qobject_to(QDict, qlist_pop(empty_list));
492*da668aa1SThomas Huth     g_assert(empty_list_0);
493*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(empty_list_0), ==, 0);
494*da668aa1SThomas Huth     qobject_unref(empty_list_0);
495*da668aa1SThomas Huth 
496*da668aa1SThomas Huth     qobject_unref(src);
497*da668aa1SThomas Huth     qobject_unref(dst);
498*da668aa1SThomas Huth }
499*da668aa1SThomas Huth 
500*da668aa1SThomas Huth static void qdict_crumple_test_empty(void)
501*da668aa1SThomas Huth {
502*da668aa1SThomas Huth     QDict *src, *dst;
503*da668aa1SThomas Huth 
504*da668aa1SThomas Huth     src = qdict_new();
505*da668aa1SThomas Huth 
506*da668aa1SThomas Huth     dst = qobject_to(QDict, qdict_crumple(src, &error_abort));
507*da668aa1SThomas Huth 
508*da668aa1SThomas Huth     g_assert_cmpint(qdict_size(dst), ==, 0);
509*da668aa1SThomas Huth 
510*da668aa1SThomas Huth     qobject_unref(src);
511*da668aa1SThomas Huth     qobject_unref(dst);
512*da668aa1SThomas Huth }
513*da668aa1SThomas Huth 
514*da668aa1SThomas Huth static int qdict_count_entries(QDict *dict)
515*da668aa1SThomas Huth {
516*da668aa1SThomas Huth     const QDictEntry *e;
517*da668aa1SThomas Huth     int count = 0;
518*da668aa1SThomas Huth 
519*da668aa1SThomas Huth     for (e = qdict_first(dict); e; e = qdict_next(dict, e)) {
520*da668aa1SThomas Huth         count++;
521*da668aa1SThomas Huth     }
522*da668aa1SThomas Huth 
523*da668aa1SThomas Huth     return count;
524*da668aa1SThomas Huth }
525*da668aa1SThomas Huth 
526*da668aa1SThomas Huth static void qdict_rename_keys_test(void)
527*da668aa1SThomas Huth {
528*da668aa1SThomas Huth     QDict *dict = qdict_new();
529*da668aa1SThomas Huth     QDict *copy;
530*da668aa1SThomas Huth     QDictRenames *renames;
531*da668aa1SThomas Huth     Error *local_err = NULL;
532*da668aa1SThomas Huth 
533*da668aa1SThomas Huth     qdict_put_str(dict, "abc", "foo");
534*da668aa1SThomas Huth     qdict_put_str(dict, "abcdef", "bar");
535*da668aa1SThomas Huth     qdict_put_int(dict, "number", 42);
536*da668aa1SThomas Huth     qdict_put_bool(dict, "flag", true);
537*da668aa1SThomas Huth     qdict_put_null(dict, "nothing");
538*da668aa1SThomas Huth 
539*da668aa1SThomas Huth     /* Empty rename list */
540*da668aa1SThomas Huth     renames = (QDictRenames[]) {
541*da668aa1SThomas Huth         { NULL, "this can be anything" }
542*da668aa1SThomas Huth     };
543*da668aa1SThomas Huth     copy = qdict_clone_shallow(dict);
544*da668aa1SThomas Huth     qdict_rename_keys(copy, renames, &error_abort);
545*da668aa1SThomas Huth 
546*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "abc"), ==, "foo");
547*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "abcdef"), ==, "bar");
548*da668aa1SThomas Huth     g_assert_cmpint(qdict_get_int(copy, "number"), ==, 42);
549*da668aa1SThomas Huth     g_assert_cmpint(qdict_get_bool(copy, "flag"), ==, true);
550*da668aa1SThomas Huth     g_assert(qobject_type(qdict_get(copy, "nothing")) == QTYPE_QNULL);
551*da668aa1SThomas Huth     g_assert_cmpint(qdict_count_entries(copy), ==, 5);
552*da668aa1SThomas Huth 
553*da668aa1SThomas Huth     qobject_unref(copy);
554*da668aa1SThomas Huth 
555*da668aa1SThomas Huth     /* Simple rename of all entries */
556*da668aa1SThomas Huth     renames = (QDictRenames[]) {
557*da668aa1SThomas Huth         { "abc",        "str1" },
558*da668aa1SThomas Huth         { "abcdef",     "str2" },
559*da668aa1SThomas Huth         { "number",     "int" },
560*da668aa1SThomas Huth         { "flag",       "bool" },
561*da668aa1SThomas Huth         { "nothing",    "null" },
562*da668aa1SThomas Huth         { NULL , NULL }
563*da668aa1SThomas Huth     };
564*da668aa1SThomas Huth     copy = qdict_clone_shallow(dict);
565*da668aa1SThomas Huth     qdict_rename_keys(copy, renames, &error_abort);
566*da668aa1SThomas Huth 
567*da668aa1SThomas Huth     g_assert(!qdict_haskey(copy, "abc"));
568*da668aa1SThomas Huth     g_assert(!qdict_haskey(copy, "abcdef"));
569*da668aa1SThomas Huth     g_assert(!qdict_haskey(copy, "number"));
570*da668aa1SThomas Huth     g_assert(!qdict_haskey(copy, "flag"));
571*da668aa1SThomas Huth     g_assert(!qdict_haskey(copy, "nothing"));
572*da668aa1SThomas Huth 
573*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "str1"), ==, "foo");
574*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "str2"), ==, "bar");
575*da668aa1SThomas Huth     g_assert_cmpint(qdict_get_int(copy, "int"), ==, 42);
576*da668aa1SThomas Huth     g_assert_cmpint(qdict_get_bool(copy, "bool"), ==, true);
577*da668aa1SThomas Huth     g_assert(qobject_type(qdict_get(copy, "null")) == QTYPE_QNULL);
578*da668aa1SThomas Huth     g_assert_cmpint(qdict_count_entries(copy), ==, 5);
579*da668aa1SThomas Huth 
580*da668aa1SThomas Huth     qobject_unref(copy);
581*da668aa1SThomas Huth 
582*da668aa1SThomas Huth     /* Renames are processed top to bottom */
583*da668aa1SThomas Huth     renames = (QDictRenames[]) {
584*da668aa1SThomas Huth         { "abc",        "tmp" },
585*da668aa1SThomas Huth         { "abcdef",     "abc" },
586*da668aa1SThomas Huth         { "number",     "abcdef" },
587*da668aa1SThomas Huth         { "flag",       "number" },
588*da668aa1SThomas Huth         { "nothing",    "flag" },
589*da668aa1SThomas Huth         { "tmp",        "nothing" },
590*da668aa1SThomas Huth         { NULL , NULL }
591*da668aa1SThomas Huth     };
592*da668aa1SThomas Huth     copy = qdict_clone_shallow(dict);
593*da668aa1SThomas Huth     qdict_rename_keys(copy, renames, &error_abort);
594*da668aa1SThomas Huth 
595*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "nothing"), ==, "foo");
596*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "abc"), ==, "bar");
597*da668aa1SThomas Huth     g_assert_cmpint(qdict_get_int(copy, "abcdef"), ==, 42);
598*da668aa1SThomas Huth     g_assert_cmpint(qdict_get_bool(copy, "number"), ==, true);
599*da668aa1SThomas Huth     g_assert(qobject_type(qdict_get(copy, "flag")) == QTYPE_QNULL);
600*da668aa1SThomas Huth     g_assert(!qdict_haskey(copy, "tmp"));
601*da668aa1SThomas Huth     g_assert_cmpint(qdict_count_entries(copy), ==, 5);
602*da668aa1SThomas Huth 
603*da668aa1SThomas Huth     qobject_unref(copy);
604*da668aa1SThomas Huth 
605*da668aa1SThomas Huth     /* Conflicting rename */
606*da668aa1SThomas Huth     renames = (QDictRenames[]) {
607*da668aa1SThomas Huth         { "abcdef",     "abc" },
608*da668aa1SThomas Huth         { NULL , NULL }
609*da668aa1SThomas Huth     };
610*da668aa1SThomas Huth     copy = qdict_clone_shallow(dict);
611*da668aa1SThomas Huth     qdict_rename_keys(copy, renames, &local_err);
612*da668aa1SThomas Huth 
613*da668aa1SThomas Huth     error_free_or_abort(&local_err);
614*da668aa1SThomas Huth 
615*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "abc"), ==, "foo");
616*da668aa1SThomas Huth     g_assert_cmpstr(qdict_get_str(copy, "abcdef"), ==, "bar");
617*da668aa1SThomas Huth     g_assert_cmpint(qdict_get_int(copy, "number"), ==, 42);
618*da668aa1SThomas Huth     g_assert_cmpint(qdict_get_bool(copy, "flag"), ==, true);
619*da668aa1SThomas Huth     g_assert(qobject_type(qdict_get(copy, "nothing")) == QTYPE_QNULL);
620*da668aa1SThomas Huth     g_assert_cmpint(qdict_count_entries(copy), ==, 5);
621*da668aa1SThomas Huth 
622*da668aa1SThomas Huth     qobject_unref(copy);
623*da668aa1SThomas Huth 
624*da668aa1SThomas Huth     /* Renames in an empty dict */
625*da668aa1SThomas Huth     renames = (QDictRenames[]) {
626*da668aa1SThomas Huth         { "abcdef",     "abc" },
627*da668aa1SThomas Huth         { NULL , NULL }
628*da668aa1SThomas Huth     };
629*da668aa1SThomas Huth 
630*da668aa1SThomas Huth     qobject_unref(dict);
631*da668aa1SThomas Huth     dict = qdict_new();
632*da668aa1SThomas Huth 
633*da668aa1SThomas Huth     qdict_rename_keys(dict, renames, &error_abort);
634*da668aa1SThomas Huth     g_assert(qdict_first(dict) == NULL);
635*da668aa1SThomas Huth 
636*da668aa1SThomas Huth     qobject_unref(dict);
637*da668aa1SThomas Huth }
638*da668aa1SThomas Huth 
639*da668aa1SThomas Huth static void qdict_crumple_test_bad_inputs(void)
640*da668aa1SThomas Huth {
641*da668aa1SThomas Huth     QDict *src, *nested;
642*da668aa1SThomas Huth     Error *error = NULL;
643*da668aa1SThomas Huth 
644*da668aa1SThomas Huth     src = qdict_new();
645*da668aa1SThomas Huth     /* rule.0 can't be both a string and a dict */
646*da668aa1SThomas Huth     qdict_put_str(src, "rule.0", "fred");
647*da668aa1SThomas Huth     qdict_put_str(src, "rule.0.policy", "allow");
648*da668aa1SThomas Huth 
649*da668aa1SThomas Huth     g_assert(qdict_crumple(src, &error) == NULL);
650*da668aa1SThomas Huth     error_free_or_abort(&error);
651*da668aa1SThomas Huth     qobject_unref(src);
652*da668aa1SThomas Huth 
653*da668aa1SThomas Huth     src = qdict_new();
654*da668aa1SThomas Huth     /* rule can't be both a list and a dict */
655*da668aa1SThomas Huth     qdict_put_str(src, "rule.0", "fred");
656*da668aa1SThomas Huth     qdict_put_str(src, "rule.a", "allow");
657*da668aa1SThomas Huth 
658*da668aa1SThomas Huth     g_assert(qdict_crumple(src, &error) == NULL);
659*da668aa1SThomas Huth     error_free_or_abort(&error);
660*da668aa1SThomas Huth     qobject_unref(src);
661*da668aa1SThomas Huth 
662*da668aa1SThomas Huth     src = qdict_new();
663*da668aa1SThomas Huth     /* The input should be flat, ie no dicts or lists */
664*da668aa1SThomas Huth     nested = qdict_new();
665*da668aa1SThomas Huth     qdict_put(nested, "x", qdict_new());
666*da668aa1SThomas Huth     qdict_put(src, "rule.a", nested);
667*da668aa1SThomas Huth     qdict_put_str(src, "rule.b", "allow");
668*da668aa1SThomas Huth 
669*da668aa1SThomas Huth     g_assert(qdict_crumple(src, &error) == NULL);
670*da668aa1SThomas Huth     error_free_or_abort(&error);
671*da668aa1SThomas Huth     qobject_unref(src);
672*da668aa1SThomas Huth 
673*da668aa1SThomas Huth     src = qdict_new();
674*da668aa1SThomas Huth     /* List indexes must not have gaps */
675*da668aa1SThomas Huth     qdict_put_str(src, "rule.0", "deny");
676*da668aa1SThomas Huth     qdict_put_str(src, "rule.3", "allow");
677*da668aa1SThomas Huth 
678*da668aa1SThomas Huth     g_assert(qdict_crumple(src, &error) == NULL);
679*da668aa1SThomas Huth     error_free_or_abort(&error);
680*da668aa1SThomas Huth     qobject_unref(src);
681*da668aa1SThomas Huth 
682*da668aa1SThomas Huth     src = qdict_new();
683*da668aa1SThomas Huth     /* List indexes must be in %zu format */
684*da668aa1SThomas Huth     qdict_put_str(src, "rule.0", "deny");
685*da668aa1SThomas Huth     qdict_put_str(src, "rule.+1", "allow");
686*da668aa1SThomas Huth 
687*da668aa1SThomas Huth     g_assert(qdict_crumple(src, &error) == NULL);
688*da668aa1SThomas Huth     error_free_or_abort(&error);
689*da668aa1SThomas Huth     qobject_unref(src);
690*da668aa1SThomas Huth }
691*da668aa1SThomas Huth 
692*da668aa1SThomas Huth int main(int argc, char **argv)
693*da668aa1SThomas Huth {
694*da668aa1SThomas Huth     g_test_init(&argc, &argv, NULL);
695*da668aa1SThomas Huth 
696*da668aa1SThomas Huth     g_test_add_func("/public/defaults", qdict_defaults_test);
697*da668aa1SThomas Huth     g_test_add_func("/public/flatten", qdict_flatten_test);
698*da668aa1SThomas Huth     g_test_add_func("/public/clone_flatten", qdict_clone_flatten_test);
699*da668aa1SThomas Huth     g_test_add_func("/public/array_split", qdict_array_split_test);
700*da668aa1SThomas Huth     g_test_add_func("/public/array_entries", qdict_array_entries_test);
701*da668aa1SThomas Huth     g_test_add_func("/public/join", qdict_join_test);
702*da668aa1SThomas Huth     g_test_add_func("/public/crumple/recursive",
703*da668aa1SThomas Huth                     qdict_crumple_test_recursive);
704*da668aa1SThomas Huth     g_test_add_func("/public/crumple/empty",
705*da668aa1SThomas Huth                     qdict_crumple_test_empty);
706*da668aa1SThomas Huth     g_test_add_func("/public/crumple/bad_inputs",
707*da668aa1SThomas Huth                     qdict_crumple_test_bad_inputs);
708*da668aa1SThomas Huth 
709*da668aa1SThomas Huth     g_test_add_func("/public/rename_keys", qdict_rename_keys_test);
710*da668aa1SThomas Huth 
711*da668aa1SThomas Huth     return g_test_run();
712*da668aa1SThomas Huth }
713