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