xref: /qemu/tests/unit/check-qdict.c (revision 7cebff0d)
1 /*
2  * QDict unit-tests.
3  *
4  * Copyright (C) 2009 Red Hat Inc.
5  *
6  * Authors:
7  *  Luiz Capitulino <lcapitulino@redhat.com>
8  *
9  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10  * See the COPYING.LIB file in the top-level directory.
11  */
12 
13 #include "qemu/osdep.h"
14 #include "qapi/qmp/qdict.h"
15 #include "qapi/qmp/qnum.h"
16 #include "qapi/qmp/qstring.h"
17 
18 /*
19  * Public Interface test-cases
20  *
21  * (with some violations to access 'private' data)
22  */
23 
24 static void qdict_new_test(void)
25 {
26     QDict *qdict;
27 
28     qdict = qdict_new();
29     g_assert(qdict != NULL);
30     g_assert(qdict_size(qdict) == 0);
31     g_assert(qdict->base.refcnt == 1);
32     g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
33 
34     qobject_unref(qdict);
35 }
36 
37 static void qdict_put_obj_test(void)
38 {
39     QNum *qn;
40     QDict *qdict;
41     QDictEntry *ent;
42     const int num = 42;
43 
44     qdict = qdict_new();
45 
46     // key "" will have tdb hash 12345
47     qdict_put_int(qdict, "", num);
48 
49     g_assert(qdict_size(qdict) == 1);
50     ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
51     qn = qobject_to(QNum, ent->value);
52     g_assert_cmpint(qnum_get_int(qn), ==, num);
53 
54     qobject_unref(qdict);
55 }
56 
57 static void qdict_destroy_simple_test(void)
58 {
59     QDict *qdict;
60 
61     qdict = qdict_new();
62     qdict_put_int(qdict, "num", 0);
63     qdict_put_str(qdict, "str", "foo");
64 
65     qobject_unref(qdict);
66 }
67 
68 static void qdict_get_test(void)
69 {
70     QNum *qn;
71     QObject *obj;
72     const int value = -42;
73     const char *key = "test";
74     QDict *tests_dict = qdict_new();
75 
76     qdict_put_int(tests_dict, key, value);
77 
78     obj = qdict_get(tests_dict, key);
79     g_assert(obj != NULL);
80 
81     qn = qobject_to(QNum, obj);
82     g_assert_cmpint(qnum_get_int(qn), ==, value);
83 
84     qobject_unref(tests_dict);
85 }
86 
87 static void qdict_get_int_test(void)
88 {
89     int ret;
90     const int value = 100;
91     const char *key = "int";
92     QDict *tests_dict = qdict_new();
93 
94     qdict_put_int(tests_dict, key, value);
95 
96     ret = qdict_get_int(tests_dict, key);
97     g_assert(ret == value);
98 
99     qobject_unref(tests_dict);
100 }
101 
102 static void qdict_get_try_int_test(void)
103 {
104     int ret;
105     const int value = 100;
106     const char *key = "int";
107     QDict *tests_dict = qdict_new();
108 
109     qdict_put_int(tests_dict, key, value);
110     qdict_put_str(tests_dict, "string", "test");
111 
112     ret = qdict_get_try_int(tests_dict, key, 0);
113     g_assert(ret == value);
114 
115     ret = qdict_get_try_int(tests_dict, "missing", -42);
116     g_assert_cmpuint(ret, ==, -42);
117 
118     ret = qdict_get_try_int(tests_dict, "string", -42);
119     g_assert_cmpuint(ret, ==, -42);
120 
121     qobject_unref(tests_dict);
122 }
123 
124 static void qdict_get_str_test(void)
125 {
126     const char *p;
127     const char *key = "key";
128     const char *str = "string";
129     QDict *tests_dict = qdict_new();
130 
131     qdict_put_str(tests_dict, key, str);
132 
133     p = qdict_get_str(tests_dict, key);
134     g_assert(p != NULL);
135     g_assert(strcmp(p, str) == 0);
136 
137     qobject_unref(tests_dict);
138 }
139 
140 static void qdict_get_try_str_test(void)
141 {
142     const char *p;
143     const char *key = "key";
144     const char *str = "string";
145     QDict *tests_dict = qdict_new();
146 
147     qdict_put_str(tests_dict, key, str);
148 
149     p = qdict_get_try_str(tests_dict, key);
150     g_assert(p != NULL);
151     g_assert(strcmp(p, str) == 0);
152 
153     qobject_unref(tests_dict);
154 }
155 
156 static void qdict_haskey_not_test(void)
157 {
158     QDict *tests_dict = qdict_new();
159     g_assert(qdict_haskey(tests_dict, "test") == 0);
160 
161     qobject_unref(tests_dict);
162 }
163 
164 static void qdict_haskey_test(void)
165 {
166     const char *key = "test";
167     QDict *tests_dict = qdict_new();
168 
169     qdict_put_int(tests_dict, key, 0);
170     g_assert(qdict_haskey(tests_dict, key) == 1);
171 
172     qobject_unref(tests_dict);
173 }
174 
175 static void qdict_del_test(void)
176 {
177     const char *key = "key test";
178     QDict *tests_dict = qdict_new();
179 
180     qdict_put_str(tests_dict, key, "foo");
181     g_assert(qdict_size(tests_dict) == 1);
182 
183     qdict_del(tests_dict, key);
184 
185     g_assert(qdict_size(tests_dict) == 0);
186     g_assert(qdict_haskey(tests_dict, key) == 0);
187 
188     qobject_unref(tests_dict);
189 }
190 
191 static void qobject_to_qdict_test(void)
192 {
193     QDict *tests_dict = qdict_new();
194     g_assert(qobject_to(QDict, QOBJECT(tests_dict)) == tests_dict);
195 
196     qobject_unref(tests_dict);
197 }
198 
199 static void qdict_iterapi_test(void)
200 {
201     int count;
202     const QDictEntry *ent;
203     QDict *tests_dict = qdict_new();
204 
205     g_assert(qdict_first(tests_dict) == NULL);
206 
207     qdict_put_int(tests_dict, "key1", 1);
208     qdict_put_int(tests_dict, "key2", 2);
209     qdict_put_int(tests_dict, "key3", 3);
210 
211     count = 0;
212     for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
213         g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
214         count++;
215     }
216 
217     g_assert(count == qdict_size(tests_dict));
218 
219     /* Do it again to test restarting */
220     count = 0;
221     for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
222         g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
223         count++;
224     }
225 
226     g_assert(count == qdict_size(tests_dict));
227 
228     qobject_unref(tests_dict);
229 }
230 
231 /*
232  * Errors test-cases
233  */
234 
235 static void qdict_put_exists_test(void)
236 {
237     int value;
238     const char *key = "exists";
239     QDict *tests_dict = qdict_new();
240 
241     qdict_put_int(tests_dict, key, 1);
242     qdict_put_int(tests_dict, key, 2);
243 
244     value = qdict_get_int(tests_dict, key);
245     g_assert(value == 2);
246 
247     g_assert(qdict_size(tests_dict) == 1);
248 
249     qobject_unref(tests_dict);
250 }
251 
252 static void qdict_get_not_exists_test(void)
253 {
254     QDict *tests_dict = qdict_new();
255     g_assert(qdict_get(tests_dict, "foo") == NULL);
256 
257     qobject_unref(tests_dict);
258 }
259 
260 /*
261  * Stress test-case
262  *
263  * This is a lot big for a unit-test, but there is no other place
264  * to have it.
265  */
266 
267 static void remove_dots(char *string)
268 {
269     char *p = strchr(string, ':');
270     if (p)
271         *p = '\0';
272 }
273 
274 static QString *read_line(FILE *file, char *key)
275 {
276     char value[128];
277 
278     if (fscanf(file, "%127s%127s", key, value) == EOF) {
279         return NULL;
280     }
281     remove_dots(key);
282     return qstring_from_str(value);
283 }
284 
285 #define reset_file(file)    fseek(file, 0L, SEEK_SET)
286 
287 static void qdict_stress_test(void)
288 {
289     size_t lines;
290     char key[128];
291     FILE *test_file;
292     QDict *qdict;
293     QString *value;
294     const char *test_file_path = "tests/data/qobject/qdict.txt";
295 
296     test_file = fopen(test_file_path, "r");
297     g_assert(test_file != NULL);
298 
299     // Create the dict
300     qdict = qdict_new();
301     g_assert(qdict != NULL);
302 
303     // Add everything from the test file
304     for (lines = 0;; lines++) {
305         value = read_line(test_file, key);
306         if (!value)
307             break;
308 
309         qdict_put(qdict, key, value);
310     }
311     g_assert(qdict_size(qdict) == lines);
312 
313     // Check if everything is really in there
314     reset_file(test_file);
315     for (;;) {
316         const char *str1, *str2;
317 
318         value = read_line(test_file, key);
319         if (!value)
320             break;
321 
322         str1 = qstring_get_str(value);
323 
324         str2 = qdict_get_str(qdict, key);
325         g_assert(str2 != NULL);
326 
327         g_assert(strcmp(str1, str2) == 0);
328 
329         qobject_unref(value);
330     }
331 
332     // Delete everything
333     reset_file(test_file);
334     for (;;) {
335         value = read_line(test_file, key);
336         if (!value)
337             break;
338 
339         qdict_del(qdict, key);
340         qobject_unref(value);
341 
342         g_assert(qdict_haskey(qdict, key) == 0);
343     }
344     fclose(test_file);
345 
346     g_assert(qdict_size(qdict) == 0);
347     qobject_unref(qdict);
348 }
349 
350 int main(int argc, char **argv)
351 {
352     g_test_init(&argc, &argv, NULL);
353 
354     g_test_add_func("/public/new", qdict_new_test);
355     g_test_add_func("/public/put_obj", qdict_put_obj_test);
356     g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
357 
358     /* Continue, but now with fixtures */
359     g_test_add_func("/public/get", qdict_get_test);
360     g_test_add_func("/public/get_int", qdict_get_int_test);
361     g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
362     g_test_add_func("/public/get_str", qdict_get_str_test);
363     g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
364     g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
365     g_test_add_func("/public/haskey", qdict_haskey_test);
366     g_test_add_func("/public/del", qdict_del_test);
367     g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
368     g_test_add_func("/public/iterapi", qdict_iterapi_test);
369 
370     g_test_add_func("/errors/put_exists", qdict_put_exists_test);
371     g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
372 
373     /* The Big one */
374     if (g_test_slow()) {
375         g_test_add_func("/stress/test", qdict_stress_test);
376     }
377 
378     return g_test_run();
379 }
380