]> git.proxmox.com Git - qemu.git/blob - check-qjson.c
Move stdbool.h
[qemu.git] / check-qjson.c
1 /*
2 * Copyright IBM, Corp. 2009
3 *
4 * Authors:
5 * Anthony Liguori <aliguori@us.ibm.com>
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 */
11 #include <check.h>
12
13 #include "qstring.h"
14 #include "qint.h"
15 #include "qdict.h"
16 #include "qlist.h"
17 #include "qfloat.h"
18 #include "qbool.h"
19 #include "qjson.h"
20
21 #include "qemu-common.h"
22
23 START_TEST(escaped_string)
24 {
25 int i;
26 struct {
27 const char *encoded;
28 const char *decoded;
29 int skip;
30 } test_cases[] = {
31 { "\"\\\"\"", "\"" },
32 { "\"hello world \\\"embedded string\\\"\"",
33 "hello world \"embedded string\"" },
34 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
35 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
36 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
37 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
38 {}
39 };
40
41 for (i = 0; test_cases[i].encoded; i++) {
42 QObject *obj;
43 QString *str;
44
45 obj = qobject_from_json(test_cases[i].encoded);
46
47 fail_unless(obj != NULL);
48 fail_unless(qobject_type(obj) == QTYPE_QSTRING);
49
50 str = qobject_to_qstring(obj);
51 fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
52
53 if (test_cases[i].skip == 0) {
54 str = qobject_to_json(obj);
55 fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
56
57 qobject_decref(obj);
58 }
59
60 QDECREF(str);
61 }
62 }
63 END_TEST
64
65 START_TEST(simple_string)
66 {
67 int i;
68 struct {
69 const char *encoded;
70 const char *decoded;
71 } test_cases[] = {
72 { "\"hello world\"", "hello world" },
73 { "\"the quick brown fox jumped over the fence\"",
74 "the quick brown fox jumped over the fence" },
75 {}
76 };
77
78 for (i = 0; test_cases[i].encoded; i++) {
79 QObject *obj;
80 QString *str;
81
82 obj = qobject_from_json(test_cases[i].encoded);
83
84 fail_unless(obj != NULL);
85 fail_unless(qobject_type(obj) == QTYPE_QSTRING);
86
87 str = qobject_to_qstring(obj);
88 fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
89
90 str = qobject_to_json(obj);
91 fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
92
93 qobject_decref(obj);
94
95 QDECREF(str);
96 }
97 }
98 END_TEST
99
100 START_TEST(single_quote_string)
101 {
102 int i;
103 struct {
104 const char *encoded;
105 const char *decoded;
106 } test_cases[] = {
107 { "'hello world'", "hello world" },
108 { "'the quick brown fox \\' jumped over the fence'",
109 "the quick brown fox ' jumped over the fence" },
110 {}
111 };
112
113 for (i = 0; test_cases[i].encoded; i++) {
114 QObject *obj;
115 QString *str;
116
117 obj = qobject_from_json(test_cases[i].encoded);
118
119 fail_unless(obj != NULL);
120 fail_unless(qobject_type(obj) == QTYPE_QSTRING);
121
122 str = qobject_to_qstring(obj);
123 fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
124
125 QDECREF(str);
126 }
127 }
128 END_TEST
129
130 START_TEST(vararg_string)
131 {
132 int i;
133 struct {
134 const char *decoded;
135 } test_cases[] = {
136 { "hello world" },
137 { "the quick brown fox jumped over the fence" },
138 {}
139 };
140
141 for (i = 0; test_cases[i].decoded; i++) {
142 QObject *obj;
143 QString *str;
144
145 obj = qobject_from_jsonf("%s", test_cases[i].decoded);
146
147 fail_unless(obj != NULL);
148 fail_unless(qobject_type(obj) == QTYPE_QSTRING);
149
150 str = qobject_to_qstring(obj);
151 fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
152
153 QDECREF(str);
154 }
155 }
156 END_TEST
157
158 START_TEST(simple_number)
159 {
160 int i;
161 struct {
162 const char *encoded;
163 int64_t decoded;
164 int skip;
165 } test_cases[] = {
166 { "0", 0 },
167 { "1234", 1234 },
168 { "1", 1 },
169 { "-32", -32 },
170 { "-0", 0, .skip = 1 },
171 { },
172 };
173
174 for (i = 0; test_cases[i].encoded; i++) {
175 QObject *obj;
176 QInt *qint;
177
178 obj = qobject_from_json(test_cases[i].encoded);
179 fail_unless(obj != NULL);
180 fail_unless(qobject_type(obj) == QTYPE_QINT);
181
182 qint = qobject_to_qint(obj);
183 fail_unless(qint_get_int(qint) == test_cases[i].decoded);
184 if (test_cases[i].skip == 0) {
185 QString *str;
186
187 str = qobject_to_json(obj);
188 fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
189 QDECREF(str);
190 }
191
192 QDECREF(qint);
193 }
194 }
195 END_TEST
196
197 START_TEST(float_number)
198 {
199 int i;
200 struct {
201 const char *encoded;
202 double decoded;
203 int skip;
204 } test_cases[] = {
205 { "32.43", 32.43 },
206 { "0.222", 0.222 },
207 { "-32.12313", -32.12313 },
208 { "-32.20e-10", -32.20e-10, .skip = 1 },
209 { },
210 };
211
212 for (i = 0; test_cases[i].encoded; i++) {
213 QObject *obj;
214 QFloat *qfloat;
215
216 obj = qobject_from_json(test_cases[i].encoded);
217 fail_unless(obj != NULL);
218 fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
219
220 qfloat = qobject_to_qfloat(obj);
221 fail_unless(qfloat_get_double(qfloat) == test_cases[i].decoded);
222
223 if (test_cases[i].skip == 0) {
224 QString *str;
225
226 str = qobject_to_json(obj);
227 fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
228 QDECREF(str);
229 }
230
231 QDECREF(qfloat);
232 }
233 }
234 END_TEST
235
236 START_TEST(vararg_number)
237 {
238 QObject *obj;
239 QInt *qint;
240 QFloat *qfloat;
241 int value = 0x2342;
242 int64_t value64 = 0x2342342343LL;
243 double valuef = 2.323423423;
244
245 obj = qobject_from_jsonf("%d", value);
246 fail_unless(obj != NULL);
247 fail_unless(qobject_type(obj) == QTYPE_QINT);
248
249 qint = qobject_to_qint(obj);
250 fail_unless(qint_get_int(qint) == value);
251
252 QDECREF(qint);
253
254 obj = qobject_from_jsonf("%" PRId64, value64);
255 fail_unless(obj != NULL);
256 fail_unless(qobject_type(obj) == QTYPE_QINT);
257
258 qint = qobject_to_qint(obj);
259 fail_unless(qint_get_int(qint) == value64);
260
261 QDECREF(qint);
262
263 obj = qobject_from_jsonf("%f", valuef);
264 fail_unless(obj != NULL);
265 fail_unless(qobject_type(obj) == QTYPE_QFLOAT);
266
267 qfloat = qobject_to_qfloat(obj);
268 fail_unless(qfloat_get_double(qfloat) == valuef);
269
270 QDECREF(qfloat);
271 }
272 END_TEST
273
274 START_TEST(keyword_literal)
275 {
276 QObject *obj;
277 QBool *qbool;
278 QString *str;
279
280 obj = qobject_from_json("true");
281 fail_unless(obj != NULL);
282 fail_unless(qobject_type(obj) == QTYPE_QBOOL);
283
284 qbool = qobject_to_qbool(obj);
285 fail_unless(qbool_get_int(qbool) != 0);
286
287 str = qobject_to_json(obj);
288 fail_unless(strcmp(qstring_get_str(str), "true") == 0);
289 QDECREF(str);
290
291 QDECREF(qbool);
292
293 obj = qobject_from_json("false");
294 fail_unless(obj != NULL);
295 fail_unless(qobject_type(obj) == QTYPE_QBOOL);
296
297 qbool = qobject_to_qbool(obj);
298 fail_unless(qbool_get_int(qbool) == 0);
299
300 str = qobject_to_json(obj);
301 fail_unless(strcmp(qstring_get_str(str), "false") == 0);
302 QDECREF(str);
303
304 QDECREF(qbool);
305
306 obj = qobject_from_jsonf("%i", false);
307 fail_unless(obj != NULL);
308 fail_unless(qobject_type(obj) == QTYPE_QBOOL);
309
310 qbool = qobject_to_qbool(obj);
311 fail_unless(qbool_get_int(qbool) == 0);
312
313 QDECREF(qbool);
314
315 obj = qobject_from_jsonf("%i", true);
316 fail_unless(obj != NULL);
317 fail_unless(qobject_type(obj) == QTYPE_QBOOL);
318
319 qbool = qobject_to_qbool(obj);
320 fail_unless(qbool_get_int(qbool) != 0);
321
322 QDECREF(qbool);
323 }
324 END_TEST
325
326 typedef struct LiteralQDictEntry LiteralQDictEntry;
327 typedef struct LiteralQObject LiteralQObject;
328
329 struct LiteralQObject
330 {
331 int type;
332 union {
333 int64_t qint;
334 const char *qstr;
335 LiteralQDictEntry *qdict;
336 LiteralQObject *qlist;
337 } value;
338 };
339
340 struct LiteralQDictEntry
341 {
342 const char *key;
343 LiteralQObject value;
344 };
345
346 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
347 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
348 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
349 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
350
351 typedef struct QListCompareHelper
352 {
353 int index;
354 LiteralQObject *objs;
355 int result;
356 } QListCompareHelper;
357
358 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
359
360 static void compare_helper(QObject *obj, void *opaque)
361 {
362 QListCompareHelper *helper = opaque;
363
364 if (helper->result == 0) {
365 return;
366 }
367
368 if (helper->objs[helper->index].type == QTYPE_NONE) {
369 helper->result = 0;
370 return;
371 }
372
373 helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
374 }
375
376 static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
377 {
378 if (lhs->type != qobject_type(rhs)) {
379 return 0;
380 }
381
382 switch (lhs->type) {
383 case QTYPE_QINT:
384 return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
385 case QTYPE_QSTRING:
386 return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
387 case QTYPE_QDICT: {
388 int i;
389
390 for (i = 0; lhs->value.qdict[i].key; i++) {
391 QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
392
393 if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
394 return 0;
395 }
396 }
397
398 return 1;
399 }
400 case QTYPE_QLIST: {
401 QListCompareHelper helper;
402
403 helper.index = 0;
404 helper.objs = lhs->value.qlist;
405 helper.result = 1;
406
407 qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
408
409 return helper.result;
410 }
411 default:
412 break;
413 }
414
415 return 0;
416 }
417
418 START_TEST(simple_dict)
419 {
420 int i;
421 struct {
422 const char *encoded;
423 LiteralQObject decoded;
424 } test_cases[] = {
425 {
426 .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
427 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
428 { "foo", QLIT_QINT(42) },
429 { "bar", QLIT_QSTR("hello world") },
430 { }
431 })),
432 }, {
433 .encoded = "{}",
434 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
435 { }
436 })),
437 }, {
438 .encoded = "{\"foo\": 43}",
439 .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
440 { "foo", QLIT_QINT(43) },
441 { }
442 })),
443 },
444 { }
445 };
446
447 for (i = 0; test_cases[i].encoded; i++) {
448 QObject *obj;
449 QString *str;
450
451 obj = qobject_from_json(test_cases[i].encoded);
452 fail_unless(obj != NULL);
453 fail_unless(qobject_type(obj) == QTYPE_QDICT);
454
455 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
456
457 str = qobject_to_json(obj);
458 qobject_decref(obj);
459
460 obj = qobject_from_json(qstring_get_str(str));
461 fail_unless(obj != NULL);
462 fail_unless(qobject_type(obj) == QTYPE_QDICT);
463
464 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
465 qobject_decref(obj);
466 QDECREF(str);
467 }
468 }
469 END_TEST
470
471 START_TEST(simple_list)
472 {
473 int i;
474 struct {
475 const char *encoded;
476 LiteralQObject decoded;
477 } test_cases[] = {
478 {
479 .encoded = "[43,42]",
480 .decoded = QLIT_QLIST(((LiteralQObject[]){
481 QLIT_QINT(43),
482 QLIT_QINT(42),
483 { }
484 })),
485 },
486 {
487 .encoded = "[43]",
488 .decoded = QLIT_QLIST(((LiteralQObject[]){
489 QLIT_QINT(43),
490 { }
491 })),
492 },
493 {
494 .encoded = "[]",
495 .decoded = QLIT_QLIST(((LiteralQObject[]){
496 { }
497 })),
498 },
499 {
500 .encoded = "[{}]",
501 .decoded = QLIT_QLIST(((LiteralQObject[]){
502 QLIT_QDICT(((LiteralQDictEntry[]){
503 {},
504 })),
505 {},
506 })),
507 },
508 { }
509 };
510
511 for (i = 0; test_cases[i].encoded; i++) {
512 QObject *obj;
513 QString *str;
514
515 obj = qobject_from_json(test_cases[i].encoded);
516 fail_unless(obj != NULL);
517 fail_unless(qobject_type(obj) == QTYPE_QLIST);
518
519 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
520
521 str = qobject_to_json(obj);
522 qobject_decref(obj);
523
524 obj = qobject_from_json(qstring_get_str(str));
525 fail_unless(obj != NULL);
526 fail_unless(qobject_type(obj) == QTYPE_QLIST);
527
528 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
529 qobject_decref(obj);
530 QDECREF(str);
531 }
532 }
533 END_TEST
534
535 START_TEST(simple_whitespace)
536 {
537 int i;
538 struct {
539 const char *encoded;
540 LiteralQObject decoded;
541 } test_cases[] = {
542 {
543 .encoded = " [ 43 , 42 ]",
544 .decoded = QLIT_QLIST(((LiteralQObject[]){
545 QLIT_QINT(43),
546 QLIT_QINT(42),
547 { }
548 })),
549 },
550 {
551 .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
552 .decoded = QLIT_QLIST(((LiteralQObject[]){
553 QLIT_QINT(43),
554 QLIT_QDICT(((LiteralQDictEntry[]){
555 { "h", QLIT_QSTR("b") },
556 { }})),
557 QLIT_QLIST(((LiteralQObject[]){
558 { }})),
559 QLIT_QINT(42),
560 { }
561 })),
562 },
563 {
564 .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
565 .decoded = QLIT_QLIST(((LiteralQObject[]){
566 QLIT_QINT(43),
567 QLIT_QDICT(((LiteralQDictEntry[]){
568 { "h", QLIT_QSTR("b") },
569 { "a", QLIT_QINT(32) },
570 { }})),
571 QLIT_QLIST(((LiteralQObject[]){
572 { }})),
573 QLIT_QINT(42),
574 { }
575 })),
576 },
577 { }
578 };
579
580 for (i = 0; test_cases[i].encoded; i++) {
581 QObject *obj;
582 QString *str;
583
584 obj = qobject_from_json(test_cases[i].encoded);
585 fail_unless(obj != NULL);
586 fail_unless(qobject_type(obj) == QTYPE_QLIST);
587
588 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
589
590 str = qobject_to_json(obj);
591 qobject_decref(obj);
592
593 obj = qobject_from_json(qstring_get_str(str));
594 fail_unless(obj != NULL);
595 fail_unless(qobject_type(obj) == QTYPE_QLIST);
596
597 fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
598
599 qobject_decref(obj);
600 QDECREF(str);
601 }
602 }
603 END_TEST
604
605 START_TEST(simple_varargs)
606 {
607 QObject *embedded_obj;
608 QObject *obj;
609 LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
610 QLIT_QINT(1),
611 QLIT_QINT(2),
612 QLIT_QLIST(((LiteralQObject[]){
613 QLIT_QINT(32),
614 QLIT_QINT(42),
615 {}})),
616 {}}));
617
618 embedded_obj = qobject_from_json("[32, 42]");
619 fail_unless(embedded_obj != NULL);
620
621 obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
622 fail_unless(obj != NULL);
623
624 fail_unless(compare_litqobj_to_qobj(&decoded, obj) == 1);
625
626 qobject_decref(obj);
627 }
628 END_TEST
629
630 static Suite *qjson_suite(void)
631 {
632 Suite *suite;
633 TCase *string_literals, *number_literals, *keyword_literals;
634 TCase *dicts, *lists, *whitespace, *varargs;
635
636 string_literals = tcase_create("String Literals");
637 tcase_add_test(string_literals, simple_string);
638 tcase_add_test(string_literals, escaped_string);
639 tcase_add_test(string_literals, single_quote_string);
640 tcase_add_test(string_literals, vararg_string);
641
642 number_literals = tcase_create("Number Literals");
643 tcase_add_test(number_literals, simple_number);
644 tcase_add_test(number_literals, float_number);
645 tcase_add_test(number_literals, vararg_number);
646
647 keyword_literals = tcase_create("Keywords");
648 tcase_add_test(keyword_literals, keyword_literal);
649 dicts = tcase_create("Objects");
650 tcase_add_test(dicts, simple_dict);
651 lists = tcase_create("Lists");
652 tcase_add_test(lists, simple_list);
653
654 whitespace = tcase_create("Whitespace");
655 tcase_add_test(whitespace, simple_whitespace);
656
657 varargs = tcase_create("Varargs");
658 tcase_add_test(varargs, simple_varargs);
659
660 suite = suite_create("QJSON test-suite");
661 suite_add_tcase(suite, string_literals);
662 suite_add_tcase(suite, number_literals);
663 suite_add_tcase(suite, keyword_literals);
664 suite_add_tcase(suite, dicts);
665 suite_add_tcase(suite, lists);
666 suite_add_tcase(suite, whitespace);
667 suite_add_tcase(suite, varargs);
668
669 return suite;
670 }
671
672 int main(void)
673 {
674 int nf;
675 Suite *s;
676 SRunner *sr;
677
678 s = qjson_suite();
679 sr = srunner_create(s);
680
681 srunner_run_all(sr, CK_NORMAL);
682 nf = srunner_ntests_failed(sr);
683 srunner_free(sr);
684
685 return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
686 }