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