]>
Commit | Line | Data |
---|---|---|
422c46a8 AL |
1 | /* |
2 | * Copyright IBM, Corp. 2009 | |
3 | * | |
4 | * Authors: | |
5 | * Anthony Liguori <[email protected]> | |
6 | * | |
7 | * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. | |
8 | * See the COPYING.LIB file in the top-level directory. | |
9 | * | |
10 | */ | |
ef76dc59 | 11 | #include <glib.h> |
422c46a8 | 12 | |
7b1b5d19 PB |
13 | #include "qapi/qmp/qstring.h" |
14 | #include "qapi/qmp/qint.h" | |
15 | #include "qapi/qmp/qdict.h" | |
16 | #include "qapi/qmp/qlist.h" | |
17 | #include "qapi/qmp/qfloat.h" | |
18 | #include "qapi/qmp/qbool.h" | |
19 | #include "qapi/qmp/qjson.h" | |
422c46a8 AL |
20 | |
21 | #include "qemu-common.h" | |
22 | ||
ef76dc59 | 23 | static void escaped_string(void) |
422c46a8 AL |
24 | { |
25 | int i; | |
26 | struct { | |
27 | const char *encoded; | |
28 | const char *decoded; | |
6ee59202 | 29 | int skip; |
422c46a8 | 30 | } test_cases[] = { |
d22b0bd7 LC |
31 | { "\"\\b\"", "\b" }, |
32 | { "\"\\f\"", "\f" }, | |
33 | { "\"\\n\"", "\n" }, | |
34 | { "\"\\r\"", "\r" }, | |
35 | { "\"\\t\"", "\t" }, | |
69faeee1 JK |
36 | { "\"/\"", "/" }, |
37 | { "\"\\/\"", "/", .skip = 1 }, | |
d22b0bd7 | 38 | { "\"\\\\\"", "\\" }, |
422c46a8 AL |
39 | { "\"\\\"\"", "\"" }, |
40 | { "\"hello world \\\"embedded string\\\"\"", | |
41 | "hello world \"embedded string\"" }, | |
42 | { "\"hello world\\nwith new line\"", "hello world\nwith new line" }, | |
6ee59202 | 43 | { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 }, |
422c46a8 AL |
44 | { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" }, |
45 | { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" }, | |
46 | {} | |
47 | }; | |
48 | ||
49 | for (i = 0; test_cases[i].encoded; i++) { | |
50 | QObject *obj; | |
51 | QString *str; | |
52 | ||
53 | obj = qobject_from_json(test_cases[i].encoded); | |
54 | ||
ef76dc59 AL |
55 | g_assert(obj != NULL); |
56 | g_assert(qobject_type(obj) == QTYPE_QSTRING); | |
422c46a8 AL |
57 | |
58 | str = qobject_to_qstring(obj); | |
ef76dc59 | 59 | g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded); |
422c46a8 | 60 | |
6ee59202 AL |
61 | if (test_cases[i].skip == 0) { |
62 | str = qobject_to_json(obj); | |
ef76dc59 | 63 | g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded); |
6ee59202 AL |
64 | qobject_decref(obj); |
65 | } | |
66 | ||
422c46a8 AL |
67 | QDECREF(str); |
68 | } | |
69 | } | |
422c46a8 | 70 | |
ef76dc59 | 71 | static void simple_string(void) |
422c46a8 AL |
72 | { |
73 | int i; | |
74 | struct { | |
75 | const char *encoded; | |
76 | const char *decoded; | |
77 | } test_cases[] = { | |
78 | { "\"hello world\"", "hello world" }, | |
79 | { "\"the quick brown fox jumped over the fence\"", | |
80 | "the quick brown fox jumped over the fence" }, | |
81 | {} | |
82 | }; | |
83 | ||
84 | for (i = 0; test_cases[i].encoded; i++) { | |
85 | QObject *obj; | |
86 | QString *str; | |
87 | ||
88 | obj = qobject_from_json(test_cases[i].encoded); | |
89 | ||
ef76dc59 AL |
90 | g_assert(obj != NULL); |
91 | g_assert(qobject_type(obj) == QTYPE_QSTRING); | |
422c46a8 AL |
92 | |
93 | str = qobject_to_qstring(obj); | |
ef76dc59 | 94 | g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0); |
422c46a8 | 95 | |
6ee59202 | 96 | str = qobject_to_json(obj); |
ef76dc59 | 97 | g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0); |
6ee59202 AL |
98 | |
99 | qobject_decref(obj); | |
100 | ||
422c46a8 AL |
101 | QDECREF(str); |
102 | } | |
103 | } | |
422c46a8 | 104 | |
ef76dc59 | 105 | static void single_quote_string(void) |
422c46a8 AL |
106 | { |
107 | int i; | |
108 | struct { | |
109 | const char *encoded; | |
110 | const char *decoded; | |
111 | } test_cases[] = { | |
112 | { "'hello world'", "hello world" }, | |
113 | { "'the quick brown fox \\' jumped over the fence'", | |
114 | "the quick brown fox ' jumped over the fence" }, | |
115 | {} | |
116 | }; | |
117 | ||
118 | for (i = 0; test_cases[i].encoded; i++) { | |
119 | QObject *obj; | |
120 | QString *str; | |
121 | ||
122 | obj = qobject_from_json(test_cases[i].encoded); | |
123 | ||
ef76dc59 AL |
124 | g_assert(obj != NULL); |
125 | g_assert(qobject_type(obj) == QTYPE_QSTRING); | |
422c46a8 AL |
126 | |
127 | str = qobject_to_qstring(obj); | |
ef76dc59 | 128 | g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0); |
422c46a8 AL |
129 | |
130 | QDECREF(str); | |
131 | } | |
132 | } | |
422c46a8 | 133 | |
ef76dc59 | 134 | static void vararg_string(void) |
422c46a8 AL |
135 | { |
136 | int i; | |
137 | struct { | |
138 | const char *decoded; | |
139 | } test_cases[] = { | |
140 | { "hello world" }, | |
141 | { "the quick brown fox jumped over the fence" }, | |
142 | {} | |
143 | }; | |
144 | ||
145 | for (i = 0; test_cases[i].decoded; i++) { | |
146 | QObject *obj; | |
147 | QString *str; | |
148 | ||
149 | obj = qobject_from_jsonf("%s", test_cases[i].decoded); | |
150 | ||
ef76dc59 AL |
151 | g_assert(obj != NULL); |
152 | g_assert(qobject_type(obj) == QTYPE_QSTRING); | |
422c46a8 AL |
153 | |
154 | str = qobject_to_qstring(obj); | |
ef76dc59 | 155 | g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0); |
422c46a8 AL |
156 | |
157 | QDECREF(str); | |
158 | } | |
159 | } | |
422c46a8 | 160 | |
ef76dc59 | 161 | static void simple_number(void) |
422c46a8 AL |
162 | { |
163 | int i; | |
164 | struct { | |
165 | const char *encoded; | |
166 | int64_t decoded; | |
6ee59202 | 167 | int skip; |
422c46a8 AL |
168 | } test_cases[] = { |
169 | { "0", 0 }, | |
170 | { "1234", 1234 }, | |
171 | { "1", 1 }, | |
172 | { "-32", -32 }, | |
6ee59202 | 173 | { "-0", 0, .skip = 1 }, |
422c46a8 AL |
174 | { }, |
175 | }; | |
176 | ||
177 | for (i = 0; test_cases[i].encoded; i++) { | |
178 | QObject *obj; | |
179 | QInt *qint; | |
180 | ||
181 | obj = qobject_from_json(test_cases[i].encoded); | |
ef76dc59 AL |
182 | g_assert(obj != NULL); |
183 | g_assert(qobject_type(obj) == QTYPE_QINT); | |
422c46a8 AL |
184 | |
185 | qint = qobject_to_qint(obj); | |
ef76dc59 | 186 | g_assert(qint_get_int(qint) == test_cases[i].decoded); |
6ee59202 AL |
187 | if (test_cases[i].skip == 0) { |
188 | QString *str; | |
189 | ||
190 | str = qobject_to_json(obj); | |
ef76dc59 | 191 | g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0); |
6ee59202 AL |
192 | QDECREF(str); |
193 | } | |
422c46a8 AL |
194 | |
195 | QDECREF(qint); | |
196 | } | |
197 | } | |
422c46a8 | 198 | |
ef76dc59 | 199 | static void float_number(void) |
422c46a8 AL |
200 | { |
201 | int i; | |
202 | struct { | |
203 | const char *encoded; | |
204 | double decoded; | |
6ee59202 | 205 | int skip; |
422c46a8 AL |
206 | } test_cases[] = { |
207 | { "32.43", 32.43 }, | |
208 | { "0.222", 0.222 }, | |
209 | { "-32.12313", -32.12313 }, | |
6ee59202 | 210 | { "-32.20e-10", -32.20e-10, .skip = 1 }, |
422c46a8 AL |
211 | { }, |
212 | }; | |
213 | ||
214 | for (i = 0; test_cases[i].encoded; i++) { | |
215 | QObject *obj; | |
216 | QFloat *qfloat; | |
217 | ||
218 | obj = qobject_from_json(test_cases[i].encoded); | |
ef76dc59 AL |
219 | g_assert(obj != NULL); |
220 | g_assert(qobject_type(obj) == QTYPE_QFLOAT); | |
422c46a8 AL |
221 | |
222 | qfloat = qobject_to_qfloat(obj); | |
ef76dc59 | 223 | g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded); |
422c46a8 | 224 | |
6ee59202 AL |
225 | if (test_cases[i].skip == 0) { |
226 | QString *str; | |
227 | ||
228 | str = qobject_to_json(obj); | |
ef76dc59 | 229 | g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0); |
6ee59202 AL |
230 | QDECREF(str); |
231 | } | |
232 | ||
422c46a8 AL |
233 | QDECREF(qfloat); |
234 | } | |
235 | } | |
422c46a8 | 236 | |
ef76dc59 | 237 | static void vararg_number(void) |
422c46a8 AL |
238 | { |
239 | QObject *obj; | |
240 | QInt *qint; | |
241 | QFloat *qfloat; | |
242 | int value = 0x2342; | |
243 | int64_t value64 = 0x2342342343LL; | |
244 | double valuef = 2.323423423; | |
245 | ||
246 | obj = qobject_from_jsonf("%d", value); | |
ef76dc59 AL |
247 | g_assert(obj != NULL); |
248 | g_assert(qobject_type(obj) == QTYPE_QINT); | |
422c46a8 AL |
249 | |
250 | qint = qobject_to_qint(obj); | |
ef76dc59 | 251 | g_assert(qint_get_int(qint) == value); |
422c46a8 AL |
252 | |
253 | QDECREF(qint); | |
254 | ||
255 | obj = qobject_from_jsonf("%" PRId64, value64); | |
ef76dc59 AL |
256 | g_assert(obj != NULL); |
257 | g_assert(qobject_type(obj) == QTYPE_QINT); | |
422c46a8 AL |
258 | |
259 | qint = qobject_to_qint(obj); | |
ef76dc59 | 260 | g_assert(qint_get_int(qint) == value64); |
422c46a8 AL |
261 | |
262 | QDECREF(qint); | |
263 | ||
264 | obj = qobject_from_jsonf("%f", valuef); | |
ef76dc59 AL |
265 | g_assert(obj != NULL); |
266 | g_assert(qobject_type(obj) == QTYPE_QFLOAT); | |
422c46a8 AL |
267 | |
268 | qfloat = qobject_to_qfloat(obj); | |
ef76dc59 | 269 | g_assert(qfloat_get_double(qfloat) == valuef); |
422c46a8 AL |
270 | |
271 | QDECREF(qfloat); | |
272 | } | |
422c46a8 | 273 | |
ef76dc59 | 274 | static void keyword_literal(void) |
422c46a8 AL |
275 | { |
276 | QObject *obj; | |
277 | QBool *qbool; | |
6ee59202 | 278 | QString *str; |
422c46a8 AL |
279 | |
280 | obj = qobject_from_json("true"); | |
ef76dc59 AL |
281 | g_assert(obj != NULL); |
282 | g_assert(qobject_type(obj) == QTYPE_QBOOL); | |
422c46a8 AL |
283 | |
284 | qbool = qobject_to_qbool(obj); | |
ef76dc59 | 285 | g_assert(qbool_get_int(qbool) != 0); |
422c46a8 | 286 | |
6ee59202 | 287 | str = qobject_to_json(obj); |
ef76dc59 | 288 | g_assert(strcmp(qstring_get_str(str), "true") == 0); |
6ee59202 AL |
289 | QDECREF(str); |
290 | ||
422c46a8 AL |
291 | QDECREF(qbool); |
292 | ||
293 | obj = qobject_from_json("false"); | |
ef76dc59 AL |
294 | g_assert(obj != NULL); |
295 | g_assert(qobject_type(obj) == QTYPE_QBOOL); | |
422c46a8 AL |
296 | |
297 | qbool = qobject_to_qbool(obj); | |
ef76dc59 | 298 | g_assert(qbool_get_int(qbool) == 0); |
422c46a8 | 299 | |
6ee59202 | 300 | str = qobject_to_json(obj); |
ef76dc59 | 301 | g_assert(strcmp(qstring_get_str(str), "false") == 0); |
6ee59202 AL |
302 | QDECREF(str); |
303 | ||
422c46a8 AL |
304 | QDECREF(qbool); |
305 | ||
306 | obj = qobject_from_jsonf("%i", false); | |
ef76dc59 AL |
307 | g_assert(obj != NULL); |
308 | g_assert(qobject_type(obj) == QTYPE_QBOOL); | |
422c46a8 AL |
309 | |
310 | qbool = qobject_to_qbool(obj); | |
ef76dc59 | 311 | g_assert(qbool_get_int(qbool) == 0); |
422c46a8 AL |
312 | |
313 | QDECREF(qbool); | |
314 | ||
315 | obj = qobject_from_jsonf("%i", true); | |
ef76dc59 AL |
316 | g_assert(obj != NULL); |
317 | g_assert(qobject_type(obj) == QTYPE_QBOOL); | |
422c46a8 AL |
318 | |
319 | qbool = qobject_to_qbool(obj); | |
ef76dc59 | 320 | g_assert(qbool_get_int(qbool) != 0); |
422c46a8 AL |
321 | |
322 | QDECREF(qbool); | |
323 | } | |
422c46a8 AL |
324 | |
325 | typedef struct LiteralQDictEntry LiteralQDictEntry; | |
326 | typedef struct LiteralQObject LiteralQObject; | |
327 | ||
328 | struct LiteralQObject | |
329 | { | |
330 | int type; | |
331 | union { | |
332 | int64_t qint; | |
333 | const char *qstr; | |
334 | LiteralQDictEntry *qdict; | |
335 | LiteralQObject *qlist; | |
336 | } value; | |
337 | }; | |
338 | ||
339 | struct LiteralQDictEntry | |
340 | { | |
341 | const char *key; | |
342 | LiteralQObject value; | |
343 | }; | |
344 | ||
345 | #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)} | |
346 | #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)} | |
347 | #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)} | |
348 | #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)} | |
349 | ||
350 | typedef struct QListCompareHelper | |
351 | { | |
352 | int index; | |
353 | LiteralQObject *objs; | |
354 | int result; | |
355 | } QListCompareHelper; | |
356 | ||
357 | static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs); | |
358 | ||
359 | static void compare_helper(QObject *obj, void *opaque) | |
360 | { | |
361 | QListCompareHelper *helper = opaque; | |
362 | ||
363 | if (helper->result == 0) { | |
364 | return; | |
365 | } | |
366 | ||
367 | if (helper->objs[helper->index].type == QTYPE_NONE) { | |
368 | helper->result = 0; | |
369 | return; | |
370 | } | |
371 | ||
372 | helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj); | |
373 | } | |
374 | ||
375 | static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs) | |
376 | { | |
377 | if (lhs->type != qobject_type(rhs)) { | |
378 | return 0; | |
379 | } | |
380 | ||
381 | switch (lhs->type) { | |
382 | case QTYPE_QINT: | |
383 | return lhs->value.qint == qint_get_int(qobject_to_qint(rhs)); | |
384 | case QTYPE_QSTRING: | |
385 | return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0); | |
386 | case QTYPE_QDICT: { | |
387 | int i; | |
388 | ||
389 | for (i = 0; lhs->value.qdict[i].key; i++) { | |
390 | QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key); | |
391 | ||
392 | if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) { | |
393 | return 0; | |
394 | } | |
395 | } | |
396 | ||
397 | return 1; | |
398 | } | |
399 | case QTYPE_QLIST: { | |
400 | QListCompareHelper helper; | |
401 | ||
402 | helper.index = 0; | |
403 | helper.objs = lhs->value.qlist; | |
404 | helper.result = 1; | |
405 | ||
406 | qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper); | |
407 | ||
408 | return helper.result; | |
409 | } | |
410 | default: | |
411 | break; | |
412 | } | |
413 | ||
414 | return 0; | |
415 | } | |
416 | ||
ef76dc59 | 417 | static void simple_dict(void) |
422c46a8 AL |
418 | { |
419 | int i; | |
420 | struct { | |
421 | const char *encoded; | |
422 | LiteralQObject decoded; | |
423 | } test_cases[] = { | |
424 | { | |
6ee59202 | 425 | .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}", |
422c46a8 AL |
426 | .decoded = QLIT_QDICT(((LiteralQDictEntry[]){ |
427 | { "foo", QLIT_QINT(42) }, | |
428 | { "bar", QLIT_QSTR("hello world") }, | |
429 | { } | |
430 | })), | |
431 | }, { | |
432 | .encoded = "{}", | |
433 | .decoded = QLIT_QDICT(((LiteralQDictEntry[]){ | |
434 | { } | |
435 | })), | |
436 | }, { | |
6ee59202 | 437 | .encoded = "{\"foo\": 43}", |
422c46a8 AL |
438 | .decoded = QLIT_QDICT(((LiteralQDictEntry[]){ |
439 | { "foo", QLIT_QINT(43) }, | |
440 | { } | |
441 | })), | |
442 | }, | |
443 | { } | |
444 | }; | |
445 | ||
446 | for (i = 0; test_cases[i].encoded; i++) { | |
447 | QObject *obj; | |
6ee59202 | 448 | QString *str; |
422c46a8 AL |
449 | |
450 | obj = qobject_from_json(test_cases[i].encoded); | |
ef76dc59 AL |
451 | g_assert(obj != NULL); |
452 | g_assert(qobject_type(obj) == QTYPE_QDICT); | |
422c46a8 | 453 | |
ef76dc59 | 454 | g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1); |
422c46a8 | 455 | |
6ee59202 AL |
456 | str = qobject_to_json(obj); |
457 | qobject_decref(obj); | |
458 | ||
459 | obj = qobject_from_json(qstring_get_str(str)); | |
ef76dc59 AL |
460 | g_assert(obj != NULL); |
461 | g_assert(qobject_type(obj) == QTYPE_QDICT); | |
6ee59202 | 462 | |
ef76dc59 | 463 | g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1); |
422c46a8 | 464 | qobject_decref(obj); |
6ee59202 | 465 | QDECREF(str); |
422c46a8 AL |
466 | } |
467 | } | |
422c46a8 | 468 | |
7109edfe MR |
469 | /* |
470 | * this generates json of the form: | |
471 | * a(0,m) = [0, 1, ..., m-1] | |
472 | * a(n,m) = { | |
473 | * 'key0': a(0,m), | |
474 | * 'key1': a(1,m), | |
475 | * ... | |
476 | * 'key(n-1)': a(n-1,m) | |
477 | * } | |
478 | */ | |
479 | static void gen_test_json(GString *gstr, int nest_level_max, | |
480 | int elem_count) | |
481 | { | |
482 | int i; | |
483 | ||
484 | g_assert(gstr); | |
485 | if (nest_level_max == 0) { | |
486 | g_string_append(gstr, "["); | |
487 | for (i = 0; i < elem_count; i++) { | |
488 | g_string_append_printf(gstr, "%d", i); | |
489 | if (i < elem_count - 1) { | |
490 | g_string_append_printf(gstr, ", "); | |
491 | } | |
492 | } | |
493 | g_string_append(gstr, "]"); | |
494 | return; | |
495 | } | |
496 | ||
497 | g_string_append(gstr, "{"); | |
498 | for (i = 0; i < nest_level_max; i++) { | |
499 | g_string_append_printf(gstr, "'key%d': ", i); | |
500 | gen_test_json(gstr, i, elem_count); | |
501 | if (i < nest_level_max - 1) { | |
502 | g_string_append(gstr, ","); | |
503 | } | |
504 | } | |
505 | g_string_append(gstr, "}"); | |
506 | } | |
507 | ||
508 | static void large_dict(void) | |
509 | { | |
510 | GString *gstr = g_string_new(""); | |
511 | QObject *obj; | |
512 | ||
513 | gen_test_json(gstr, 10, 100); | |
514 | obj = qobject_from_json(gstr->str); | |
515 | g_assert(obj != NULL); | |
516 | ||
517 | qobject_decref(obj); | |
518 | g_string_free(gstr, true); | |
519 | } | |
520 | ||
ef76dc59 | 521 | static void simple_list(void) |
422c46a8 AL |
522 | { |
523 | int i; | |
524 | struct { | |
525 | const char *encoded; | |
526 | LiteralQObject decoded; | |
527 | } test_cases[] = { | |
528 | { | |
529 | .encoded = "[43,42]", | |
530 | .decoded = QLIT_QLIST(((LiteralQObject[]){ | |
531 | QLIT_QINT(43), | |
532 | QLIT_QINT(42), | |
533 | { } | |
534 | })), | |
535 | }, | |
536 | { | |
537 | .encoded = "[43]", | |
538 | .decoded = QLIT_QLIST(((LiteralQObject[]){ | |
539 | QLIT_QINT(43), | |
540 | { } | |
541 | })), | |
542 | }, | |
543 | { | |
544 | .encoded = "[]", | |
545 | .decoded = QLIT_QLIST(((LiteralQObject[]){ | |
546 | { } | |
547 | })), | |
548 | }, | |
549 | { | |
550 | .encoded = "[{}]", | |
551 | .decoded = QLIT_QLIST(((LiteralQObject[]){ | |
552 | QLIT_QDICT(((LiteralQDictEntry[]){ | |
553 | {}, | |
554 | })), | |
555 | {}, | |
556 | })), | |
557 | }, | |
558 | { } | |
559 | }; | |
560 | ||
561 | for (i = 0; test_cases[i].encoded; i++) { | |
562 | QObject *obj; | |
6ee59202 | 563 | QString *str; |
422c46a8 AL |
564 | |
565 | obj = qobject_from_json(test_cases[i].encoded); | |
ef76dc59 AL |
566 | g_assert(obj != NULL); |
567 | g_assert(qobject_type(obj) == QTYPE_QLIST); | |
422c46a8 | 568 | |
ef76dc59 | 569 | g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1); |
422c46a8 | 570 | |
6ee59202 AL |
571 | str = qobject_to_json(obj); |
572 | qobject_decref(obj); | |
573 | ||
574 | obj = qobject_from_json(qstring_get_str(str)); | |
ef76dc59 AL |
575 | g_assert(obj != NULL); |
576 | g_assert(qobject_type(obj) == QTYPE_QLIST); | |
6ee59202 | 577 | |
ef76dc59 | 578 | g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1); |
422c46a8 | 579 | qobject_decref(obj); |
6ee59202 | 580 | QDECREF(str); |
422c46a8 AL |
581 | } |
582 | } | |
422c46a8 | 583 | |
ef76dc59 | 584 | static void simple_whitespace(void) |
422c46a8 AL |
585 | { |
586 | int i; | |
587 | struct { | |
588 | const char *encoded; | |
589 | LiteralQObject decoded; | |
590 | } test_cases[] = { | |
591 | { | |
592 | .encoded = " [ 43 , 42 ]", | |
593 | .decoded = QLIT_QLIST(((LiteralQObject[]){ | |
594 | QLIT_QINT(43), | |
595 | QLIT_QINT(42), | |
596 | { } | |
597 | })), | |
598 | }, | |
599 | { | |
600 | .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]", | |
601 | .decoded = QLIT_QLIST(((LiteralQObject[]){ | |
602 | QLIT_QINT(43), | |
603 | QLIT_QDICT(((LiteralQDictEntry[]){ | |
604 | { "h", QLIT_QSTR("b") }, | |
605 | { }})), | |
606 | QLIT_QLIST(((LiteralQObject[]){ | |
607 | { }})), | |
608 | QLIT_QINT(42), | |
609 | { } | |
610 | })), | |
611 | }, | |
612 | { | |
613 | .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]", | |
614 | .decoded = QLIT_QLIST(((LiteralQObject[]){ | |
615 | QLIT_QINT(43), | |
616 | QLIT_QDICT(((LiteralQDictEntry[]){ | |
617 | { "h", QLIT_QSTR("b") }, | |
618 | { "a", QLIT_QINT(32) }, | |
619 | { }})), | |
620 | QLIT_QLIST(((LiteralQObject[]){ | |
621 | { }})), | |
622 | QLIT_QINT(42), | |
623 | { } | |
624 | })), | |
625 | }, | |
626 | { } | |
627 | }; | |
628 | ||
629 | for (i = 0; test_cases[i].encoded; i++) { | |
630 | QObject *obj; | |
6ee59202 | 631 | QString *str; |
422c46a8 AL |
632 | |
633 | obj = qobject_from_json(test_cases[i].encoded); | |
ef76dc59 AL |
634 | g_assert(obj != NULL); |
635 | g_assert(qobject_type(obj) == QTYPE_QLIST); | |
422c46a8 | 636 | |
ef76dc59 | 637 | g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1); |
422c46a8 | 638 | |
6ee59202 | 639 | str = qobject_to_json(obj); |
422c46a8 | 640 | qobject_decref(obj); |
6ee59202 AL |
641 | |
642 | obj = qobject_from_json(qstring_get_str(str)); | |
ef76dc59 AL |
643 | g_assert(obj != NULL); |
644 | g_assert(qobject_type(obj) == QTYPE_QLIST); | |
6ee59202 | 645 | |
ef76dc59 | 646 | g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1); |
6ee59202 AL |
647 | |
648 | qobject_decref(obj); | |
649 | QDECREF(str); | |
422c46a8 AL |
650 | } |
651 | } | |
422c46a8 | 652 | |
ef76dc59 | 653 | static void simple_varargs(void) |
422c46a8 AL |
654 | { |
655 | QObject *embedded_obj; | |
656 | QObject *obj; | |
657 | LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){ | |
658 | QLIT_QINT(1), | |
659 | QLIT_QINT(2), | |
660 | QLIT_QLIST(((LiteralQObject[]){ | |
661 | QLIT_QINT(32), | |
662 | QLIT_QINT(42), | |
663 | {}})), | |
664 | {}})); | |
665 | ||
666 | embedded_obj = qobject_from_json("[32, 42]"); | |
ef76dc59 | 667 | g_assert(embedded_obj != NULL); |
422c46a8 AL |
668 | |
669 | obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj); | |
ef76dc59 | 670 | g_assert(obj != NULL); |
422c46a8 | 671 | |
ef76dc59 | 672 | g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1); |
422c46a8 AL |
673 | |
674 | qobject_decref(obj); | |
675 | } | |
422c46a8 | 676 | |
ef76dc59 | 677 | static void empty_input(void) |
7f8fca7c | 678 | { |
e7a06af8 JK |
679 | const char *empty = ""; |
680 | ||
681 | QObject *obj = qobject_from_json(empty); | |
ef76dc59 | 682 | g_assert(obj == NULL); |
7f8fca7c | 683 | } |
7f8fca7c | 684 | |
ef76dc59 | 685 | static void unterminated_string(void) |
7f8fca7c PB |
686 | { |
687 | QObject *obj = qobject_from_json("\"abc"); | |
ef76dc59 | 688 | g_assert(obj == NULL); |
7f8fca7c | 689 | } |
7f8fca7c | 690 | |
ef76dc59 | 691 | static void unterminated_sq_string(void) |
7f8fca7c PB |
692 | { |
693 | QObject *obj = qobject_from_json("'abc"); | |
ef76dc59 | 694 | g_assert(obj == NULL); |
7f8fca7c | 695 | } |
7f8fca7c | 696 | |
ef76dc59 | 697 | static void unterminated_escape(void) |
7f8fca7c PB |
698 | { |
699 | QObject *obj = qobject_from_json("\"abc\\\""); | |
ef76dc59 | 700 | g_assert(obj == NULL); |
7f8fca7c | 701 | } |
7f8fca7c | 702 | |
ef76dc59 | 703 | static void unterminated_array(void) |
7f8fca7c PB |
704 | { |
705 | QObject *obj = qobject_from_json("[32"); | |
ef76dc59 | 706 | g_assert(obj == NULL); |
7f8fca7c | 707 | } |
7f8fca7c | 708 | |
ef76dc59 | 709 | static void unterminated_array_comma(void) |
7f8fca7c PB |
710 | { |
711 | QObject *obj = qobject_from_json("[32,"); | |
ef76dc59 | 712 | g_assert(obj == NULL); |
7f8fca7c | 713 | } |
7f8fca7c | 714 | |
ef76dc59 | 715 | static void invalid_array_comma(void) |
7f8fca7c PB |
716 | { |
717 | QObject *obj = qobject_from_json("[32,}"); | |
ef76dc59 | 718 | g_assert(obj == NULL); |
7f8fca7c | 719 | } |
7f8fca7c | 720 | |
ef76dc59 | 721 | static void unterminated_dict(void) |
7f8fca7c PB |
722 | { |
723 | QObject *obj = qobject_from_json("{'abc':32"); | |
ef76dc59 | 724 | g_assert(obj == NULL); |
7f8fca7c | 725 | } |
7f8fca7c | 726 | |
ef76dc59 | 727 | static void unterminated_dict_comma(void) |
7f8fca7c PB |
728 | { |
729 | QObject *obj = qobject_from_json("{'abc':32,"); | |
ef76dc59 | 730 | g_assert(obj == NULL); |
7f8fca7c | 731 | } |
7f8fca7c | 732 | |
ef76dc59 | 733 | static void invalid_dict_comma(void) |
7f8fca7c PB |
734 | { |
735 | QObject *obj = qobject_from_json("{'abc':32,}"); | |
ef76dc59 | 736 | g_assert(obj == NULL); |
7f8fca7c | 737 | } |
7f8fca7c | 738 | |
ef76dc59 | 739 | static void unterminated_literal(void) |
7f8fca7c PB |
740 | { |
741 | QObject *obj = qobject_from_json("nul"); | |
ef76dc59 | 742 | g_assert(obj == NULL); |
7f8fca7c | 743 | } |
7f8fca7c | 744 | |
ef76dc59 | 745 | int main(int argc, char **argv) |
422c46a8 | 746 | { |
ef76dc59 AL |
747 | g_test_init(&argc, &argv, NULL); |
748 | ||
749 | g_test_add_func("/literals/string/simple", simple_string); | |
750 | g_test_add_func("/literals/string/escaped", escaped_string); | |
751 | g_test_add_func("/literals/string/single_quote", single_quote_string); | |
752 | g_test_add_func("/literals/string/vararg", vararg_string); | |
753 | ||
754 | g_test_add_func("/literals/number/simple", simple_number); | |
755 | g_test_add_func("/literals/number/float", float_number); | |
756 | g_test_add_func("/literals/number/vararg", vararg_number); | |
757 | ||
758 | g_test_add_func("/literals/keyword", keyword_literal); | |
759 | ||
760 | g_test_add_func("/dicts/simple_dict", simple_dict); | |
7109edfe | 761 | g_test_add_func("/dicts/large_dict", large_dict); |
ef76dc59 AL |
762 | g_test_add_func("/lists/simple_list", simple_list); |
763 | ||
764 | g_test_add_func("/whitespace/simple_whitespace", simple_whitespace); | |
765 | ||
766 | g_test_add_func("/varargs/simple_varargs", simple_varargs); | |
767 | ||
768 | g_test_add_func("/errors/empty_input", empty_input); | |
769 | g_test_add_func("/errors/unterminated/string", unterminated_string); | |
770 | g_test_add_func("/errors/unterminated/escape", unterminated_escape); | |
771 | g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string); | |
772 | g_test_add_func("/errors/unterminated/array", unterminated_array); | |
773 | g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma); | |
774 | g_test_add_func("/errors/unterminated/dict", unterminated_dict); | |
775 | g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma); | |
776 | g_test_add_func("/errors/invalid_array_comma", invalid_array_comma); | |
ef76dc59 AL |
777 | g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma); |
778 | g_test_add_func("/errors/unterminated/literal", unterminated_literal); | |
7f8fca7c | 779 | |
ef76dc59 | 780 | return g_test_run(); |
422c46a8 | 781 | } |