2 * Copyright IBM, Corp. 2009
5 * Anthony Liguori <aliguori@us.ibm.com>
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.
21 #include "qemu-common.h"
23 START_TEST(escaped_string
)
37 { "\"\\/\"", "/", .skip
= 1 },
40 { "\"hello world \\\"embedded string\\\"\"",
41 "hello world \"embedded string\"" },
42 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
43 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip
= 1 },
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" },
49 for (i
= 0; test_cases
[i
].encoded
; i
++) {
53 obj
= qobject_from_json(test_cases
[i
].encoded
);
55 fail_unless(obj
!= NULL
);
56 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
58 str
= qobject_to_qstring(obj
);
59 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0,
60 "%s != %s\n", qstring_get_str(str
), test_cases
[i
].decoded
);
62 if (test_cases
[i
].skip
== 0) {
63 str
= qobject_to_json(obj
);
64 fail_unless(strcmp(qstring_get_str(str
),test_cases
[i
].encoded
) == 0,
65 "%s != %s\n", qstring_get_str(str
),
66 test_cases
[i
].encoded
);
76 START_TEST(simple_string
)
83 { "\"hello world\"", "hello world" },
84 { "\"the quick brown fox jumped over the fence\"",
85 "the quick brown fox jumped over the fence" },
89 for (i
= 0; test_cases
[i
].encoded
; i
++) {
93 obj
= qobject_from_json(test_cases
[i
].encoded
);
95 fail_unless(obj
!= NULL
);
96 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
98 str
= qobject_to_qstring(obj
);
99 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
101 str
= qobject_to_json(obj
);
102 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
111 START_TEST(single_quote_string
)
118 { "'hello world'", "hello world" },
119 { "'the quick brown fox \\' jumped over the fence'",
120 "the quick brown fox ' jumped over the fence" },
124 for (i
= 0; test_cases
[i
].encoded
; i
++) {
128 obj
= qobject_from_json(test_cases
[i
].encoded
);
130 fail_unless(obj
!= NULL
);
131 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
133 str
= qobject_to_qstring(obj
);
134 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
141 START_TEST(vararg_string
)
148 { "the quick brown fox jumped over the fence" },
152 for (i
= 0; test_cases
[i
].decoded
; i
++) {
156 obj
= qobject_from_jsonf("%s", test_cases
[i
].decoded
);
158 fail_unless(obj
!= NULL
);
159 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
161 str
= qobject_to_qstring(obj
);
162 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
169 START_TEST(simple_number
)
181 { "-0", 0, .skip
= 1 },
185 for (i
= 0; test_cases
[i
].encoded
; i
++) {
189 obj
= qobject_from_json(test_cases
[i
].encoded
);
190 fail_unless(obj
!= NULL
);
191 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
193 qint
= qobject_to_qint(obj
);
194 fail_unless(qint_get_int(qint
) == test_cases
[i
].decoded
);
195 if (test_cases
[i
].skip
== 0) {
198 str
= qobject_to_json(obj
);
199 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
208 START_TEST(float_number
)
218 { "-32.12313", -32.12313 },
219 { "-32.20e-10", -32.20e-10, .skip
= 1 },
223 for (i
= 0; test_cases
[i
].encoded
; i
++) {
227 obj
= qobject_from_json(test_cases
[i
].encoded
);
228 fail_unless(obj
!= NULL
);
229 fail_unless(qobject_type(obj
) == QTYPE_QFLOAT
);
231 qfloat
= qobject_to_qfloat(obj
);
232 fail_unless(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
234 if (test_cases
[i
].skip
== 0) {
237 str
= qobject_to_json(obj
);
238 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
247 START_TEST(vararg_number
)
253 int64_t value64
= 0x2342342343LL
;
254 double valuef
= 2.323423423;
256 obj
= qobject_from_jsonf("%d", value
);
257 fail_unless(obj
!= NULL
);
258 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
260 qint
= qobject_to_qint(obj
);
261 fail_unless(qint_get_int(qint
) == value
);
265 obj
= qobject_from_jsonf("%" PRId64
, value64
);
266 fail_unless(obj
!= NULL
);
267 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
269 qint
= qobject_to_qint(obj
);
270 fail_unless(qint_get_int(qint
) == value64
);
274 obj
= qobject_from_jsonf("%f", valuef
);
275 fail_unless(obj
!= NULL
);
276 fail_unless(qobject_type(obj
) == QTYPE_QFLOAT
);
278 qfloat
= qobject_to_qfloat(obj
);
279 fail_unless(qfloat_get_double(qfloat
) == valuef
);
285 START_TEST(keyword_literal
)
291 obj
= qobject_from_json("true");
292 fail_unless(obj
!= NULL
);
293 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
295 qbool
= qobject_to_qbool(obj
);
296 fail_unless(qbool_get_int(qbool
) != 0);
298 str
= qobject_to_json(obj
);
299 fail_unless(strcmp(qstring_get_str(str
), "true") == 0);
304 obj
= qobject_from_json("false");
305 fail_unless(obj
!= NULL
);
306 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
308 qbool
= qobject_to_qbool(obj
);
309 fail_unless(qbool_get_int(qbool
) == 0);
311 str
= qobject_to_json(obj
);
312 fail_unless(strcmp(qstring_get_str(str
), "false") == 0);
317 obj
= qobject_from_jsonf("%i", false);
318 fail_unless(obj
!= NULL
);
319 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
321 qbool
= qobject_to_qbool(obj
);
322 fail_unless(qbool_get_int(qbool
) == 0);
326 obj
= qobject_from_jsonf("%i", true);
327 fail_unless(obj
!= NULL
);
328 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
330 qbool
= qobject_to_qbool(obj
);
331 fail_unless(qbool_get_int(qbool
) != 0);
337 typedef struct LiteralQDictEntry LiteralQDictEntry
;
338 typedef struct LiteralQObject LiteralQObject
;
340 struct LiteralQObject
346 LiteralQDictEntry
*qdict
;
347 LiteralQObject
*qlist
;
351 struct LiteralQDictEntry
354 LiteralQObject value
;
357 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
358 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
359 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
360 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
362 typedef struct QListCompareHelper
365 LiteralQObject
*objs
;
367 } QListCompareHelper
;
369 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
371 static void compare_helper(QObject
*obj
, void *opaque
)
373 QListCompareHelper
*helper
= opaque
;
375 if (helper
->result
== 0) {
379 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
384 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
387 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
389 if (lhs
->type
!= qobject_type(rhs
)) {
395 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
397 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
401 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
402 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
404 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
412 QListCompareHelper helper
;
415 helper
.objs
= lhs
->value
.qlist
;
418 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
420 return helper
.result
;
429 START_TEST(simple_dict
)
434 LiteralQObject decoded
;
437 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
438 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
439 { "foo", QLIT_QINT(42) },
440 { "bar", QLIT_QSTR("hello world") },
445 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
449 .encoded
= "{\"foo\": 43}",
450 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
451 { "foo", QLIT_QINT(43) },
458 for (i
= 0; test_cases
[i
].encoded
; i
++) {
462 obj
= qobject_from_json(test_cases
[i
].encoded
);
463 fail_unless(obj
!= NULL
);
464 fail_unless(qobject_type(obj
) == QTYPE_QDICT
);
466 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
468 str
= qobject_to_json(obj
);
471 obj
= qobject_from_json(qstring_get_str(str
));
472 fail_unless(obj
!= NULL
);
473 fail_unless(qobject_type(obj
) == QTYPE_QDICT
);
475 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
482 START_TEST(simple_list
)
487 LiteralQObject decoded
;
490 .encoded
= "[43,42]",
491 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
499 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
506 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
512 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
513 QLIT_QDICT(((LiteralQDictEntry
[]){
522 for (i
= 0; test_cases
[i
].encoded
; i
++) {
526 obj
= qobject_from_json(test_cases
[i
].encoded
);
527 fail_unless(obj
!= NULL
);
528 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
530 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
532 str
= qobject_to_json(obj
);
535 obj
= qobject_from_json(qstring_get_str(str
));
536 fail_unless(obj
!= NULL
);
537 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
539 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
546 START_TEST(simple_whitespace
)
551 LiteralQObject decoded
;
554 .encoded
= " [ 43 , 42 ]",
555 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
562 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
563 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
565 QLIT_QDICT(((LiteralQDictEntry
[]){
566 { "h", QLIT_QSTR("b") },
568 QLIT_QLIST(((LiteralQObject
[]){
575 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
576 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
578 QLIT_QDICT(((LiteralQDictEntry
[]){
579 { "h", QLIT_QSTR("b") },
580 { "a", QLIT_QINT(32) },
582 QLIT_QLIST(((LiteralQObject
[]){
591 for (i
= 0; test_cases
[i
].encoded
; i
++) {
595 obj
= qobject_from_json(test_cases
[i
].encoded
);
596 fail_unless(obj
!= NULL
);
597 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
599 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
601 str
= qobject_to_json(obj
);
604 obj
= qobject_from_json(qstring_get_str(str
));
605 fail_unless(obj
!= NULL
);
606 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
608 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
616 START_TEST(simple_varargs
)
618 QObject
*embedded_obj
;
620 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
623 QLIT_QLIST(((LiteralQObject
[]){
629 embedded_obj
= qobject_from_json("[32, 42]");
630 fail_unless(embedded_obj
!= NULL
);
632 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
633 fail_unless(obj
!= NULL
);
635 fail_unless(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
641 START_TEST(empty_input
)
643 const char *empty
= "";
645 QObject
*obj
= qobject_from_json(empty
);
646 fail_unless(obj
== NULL
);
650 START_TEST(unterminated_string
)
652 QObject
*obj
= qobject_from_json("\"abc");
653 fail_unless(obj
== NULL
);
657 START_TEST(unterminated_sq_string
)
659 QObject
*obj
= qobject_from_json("'abc");
660 fail_unless(obj
== NULL
);
664 START_TEST(unterminated_escape
)
666 QObject
*obj
= qobject_from_json("\"abc\\\"");
667 fail_unless(obj
== NULL
);
671 START_TEST(unterminated_array
)
673 QObject
*obj
= qobject_from_json("[32");
674 fail_unless(obj
== NULL
);
678 START_TEST(unterminated_array_comma
)
680 QObject
*obj
= qobject_from_json("[32,");
681 fail_unless(obj
== NULL
);
685 START_TEST(invalid_array_comma
)
687 QObject
*obj
= qobject_from_json("[32,}");
688 fail_unless(obj
== NULL
);
692 START_TEST(unterminated_dict
)
694 QObject
*obj
= qobject_from_json("{'abc':32");
695 fail_unless(obj
== NULL
);
699 START_TEST(unterminated_dict_comma
)
701 QObject
*obj
= qobject_from_json("{'abc':32,");
702 fail_unless(obj
== NULL
);
707 START_TEST(invalid_dict_comma
)
709 QObject
*obj
= qobject_from_json("{'abc':32,}");
710 fail_unless(obj
== NULL
);
714 START_TEST(unterminated_literal
)
716 QObject
*obj
= qobject_from_json("nul");
717 fail_unless(obj
== NULL
);
722 static Suite
*qjson_suite(void)
725 TCase
*string_literals
, *number_literals
, *keyword_literals
;
726 TCase
*dicts
, *lists
, *whitespace
, *varargs
, *errors
;
728 string_literals
= tcase_create("String Literals");
729 tcase_add_test(string_literals
, simple_string
);
730 tcase_add_test(string_literals
, escaped_string
);
731 tcase_add_test(string_literals
, single_quote_string
);
732 tcase_add_test(string_literals
, vararg_string
);
734 number_literals
= tcase_create("Number Literals");
735 tcase_add_test(number_literals
, simple_number
);
736 tcase_add_test(number_literals
, float_number
);
737 tcase_add_test(number_literals
, vararg_number
);
739 keyword_literals
= tcase_create("Keywords");
740 tcase_add_test(keyword_literals
, keyword_literal
);
741 dicts
= tcase_create("Objects");
742 tcase_add_test(dicts
, simple_dict
);
743 lists
= tcase_create("Lists");
744 tcase_add_test(lists
, simple_list
);
746 whitespace
= tcase_create("Whitespace");
747 tcase_add_test(whitespace
, simple_whitespace
);
749 varargs
= tcase_create("Varargs");
750 tcase_add_test(varargs
, simple_varargs
);
752 errors
= tcase_create("Invalid JSON");
753 tcase_add_test(errors
, empty_input
);
754 tcase_add_test(errors
, unterminated_string
);
755 tcase_add_test(errors
, unterminated_escape
);
756 tcase_add_test(errors
, unterminated_sq_string
);
757 tcase_add_test(errors
, unterminated_array
);
758 tcase_add_test(errors
, unterminated_array_comma
);
759 tcase_add_test(errors
, invalid_array_comma
);
760 tcase_add_test(errors
, unterminated_dict
);
761 tcase_add_test(errors
, unterminated_dict_comma
);
763 /* FIXME: this print parse error messages on stderr. */
764 tcase_add_test(errors
, invalid_dict_comma
);
765 tcase_add_test(errors
, unterminated_literal
);
768 suite
= suite_create("QJSON test-suite");
769 suite_add_tcase(suite
, string_literals
);
770 suite_add_tcase(suite
, number_literals
);
771 suite_add_tcase(suite
, keyword_literals
);
772 suite_add_tcase(suite
, dicts
);
773 suite_add_tcase(suite
, lists
);
774 suite_add_tcase(suite
, whitespace
);
775 suite_add_tcase(suite
, varargs
);
776 suite_add_tcase(suite
, errors
);
788 sr
= srunner_create(s
);
790 srunner_run_all(sr
, CK_NORMAL
);
791 nf
= srunner_ntests_failed(sr
);
794 return (nf
== 0) ? EXIT_SUCCESS
: EXIT_FAILURE
;