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
)
39 { "\"hello world \\\"embedded string\\\"\"",
40 "hello world \"embedded string\"" },
41 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
42 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip
= 1 },
43 { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
44 { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
48 for (i
= 0; test_cases
[i
].encoded
; i
++) {
52 obj
= qobject_from_json(test_cases
[i
].encoded
);
54 fail_unless(obj
!= NULL
);
55 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
57 str
= qobject_to_qstring(obj
);
58 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0,
59 "%s != %s\n", qstring_get_str(str
), test_cases
[i
].decoded
);
61 if (test_cases
[i
].skip
== 0) {
62 str
= qobject_to_json(obj
);
63 fail_unless(strcmp(qstring_get_str(str
),test_cases
[i
].encoded
) == 0,
64 "%s != %s\n", qstring_get_str(str
),
65 test_cases
[i
].encoded
);
75 START_TEST(simple_string
)
82 { "\"hello world\"", "hello world" },
83 { "\"the quick brown fox jumped over the fence\"",
84 "the quick brown fox jumped over the fence" },
88 for (i
= 0; test_cases
[i
].encoded
; i
++) {
92 obj
= qobject_from_json(test_cases
[i
].encoded
);
94 fail_unless(obj
!= NULL
);
95 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
97 str
= qobject_to_qstring(obj
);
98 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
100 str
= qobject_to_json(obj
);
101 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
110 START_TEST(single_quote_string
)
117 { "'hello world'", "hello world" },
118 { "'the quick brown fox \\' jumped over the fence'",
119 "the quick brown fox ' jumped over the fence" },
123 for (i
= 0; test_cases
[i
].encoded
; i
++) {
127 obj
= qobject_from_json(test_cases
[i
].encoded
);
129 fail_unless(obj
!= NULL
);
130 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
132 str
= qobject_to_qstring(obj
);
133 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
140 START_TEST(vararg_string
)
147 { "the quick brown fox jumped over the fence" },
151 for (i
= 0; test_cases
[i
].decoded
; i
++) {
155 obj
= qobject_from_jsonf("%s", test_cases
[i
].decoded
);
157 fail_unless(obj
!= NULL
);
158 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
160 str
= qobject_to_qstring(obj
);
161 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
168 START_TEST(simple_number
)
180 { "-0", 0, .skip
= 1 },
184 for (i
= 0; test_cases
[i
].encoded
; i
++) {
188 obj
= qobject_from_json(test_cases
[i
].encoded
);
189 fail_unless(obj
!= NULL
);
190 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
192 qint
= qobject_to_qint(obj
);
193 fail_unless(qint_get_int(qint
) == test_cases
[i
].decoded
);
194 if (test_cases
[i
].skip
== 0) {
197 str
= qobject_to_json(obj
);
198 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
207 START_TEST(float_number
)
217 { "-32.12313", -32.12313 },
218 { "-32.20e-10", -32.20e-10, .skip
= 1 },
222 for (i
= 0; test_cases
[i
].encoded
; i
++) {
226 obj
= qobject_from_json(test_cases
[i
].encoded
);
227 fail_unless(obj
!= NULL
);
228 fail_unless(qobject_type(obj
) == QTYPE_QFLOAT
);
230 qfloat
= qobject_to_qfloat(obj
);
231 fail_unless(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
233 if (test_cases
[i
].skip
== 0) {
236 str
= qobject_to_json(obj
);
237 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
246 START_TEST(vararg_number
)
252 int64_t value64
= 0x2342342343LL
;
253 double valuef
= 2.323423423;
255 obj
= qobject_from_jsonf("%d", value
);
256 fail_unless(obj
!= NULL
);
257 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
259 qint
= qobject_to_qint(obj
);
260 fail_unless(qint_get_int(qint
) == value
);
264 obj
= qobject_from_jsonf("%" PRId64
, value64
);
265 fail_unless(obj
!= NULL
);
266 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
268 qint
= qobject_to_qint(obj
);
269 fail_unless(qint_get_int(qint
) == value64
);
273 obj
= qobject_from_jsonf("%f", valuef
);
274 fail_unless(obj
!= NULL
);
275 fail_unless(qobject_type(obj
) == QTYPE_QFLOAT
);
277 qfloat
= qobject_to_qfloat(obj
);
278 fail_unless(qfloat_get_double(qfloat
) == valuef
);
284 START_TEST(keyword_literal
)
290 obj
= qobject_from_json("true");
291 fail_unless(obj
!= NULL
);
292 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
294 qbool
= qobject_to_qbool(obj
);
295 fail_unless(qbool_get_int(qbool
) != 0);
297 str
= qobject_to_json(obj
);
298 fail_unless(strcmp(qstring_get_str(str
), "true") == 0);
303 obj
= qobject_from_json("false");
304 fail_unless(obj
!= NULL
);
305 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
307 qbool
= qobject_to_qbool(obj
);
308 fail_unless(qbool_get_int(qbool
) == 0);
310 str
= qobject_to_json(obj
);
311 fail_unless(strcmp(qstring_get_str(str
), "false") == 0);
316 obj
= qobject_from_jsonf("%i", false);
317 fail_unless(obj
!= NULL
);
318 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
320 qbool
= qobject_to_qbool(obj
);
321 fail_unless(qbool_get_int(qbool
) == 0);
325 obj
= qobject_from_jsonf("%i", true);
326 fail_unless(obj
!= NULL
);
327 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
329 qbool
= qobject_to_qbool(obj
);
330 fail_unless(qbool_get_int(qbool
) != 0);
336 typedef struct LiteralQDictEntry LiteralQDictEntry
;
337 typedef struct LiteralQObject LiteralQObject
;
339 struct LiteralQObject
345 LiteralQDictEntry
*qdict
;
346 LiteralQObject
*qlist
;
350 struct LiteralQDictEntry
353 LiteralQObject value
;
356 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
357 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
358 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
359 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
361 typedef struct QListCompareHelper
364 LiteralQObject
*objs
;
366 } QListCompareHelper
;
368 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
370 static void compare_helper(QObject
*obj
, void *opaque
)
372 QListCompareHelper
*helper
= opaque
;
374 if (helper
->result
== 0) {
378 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
383 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
386 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
388 if (lhs
->type
!= qobject_type(rhs
)) {
394 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
396 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
400 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
401 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
403 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
411 QListCompareHelper helper
;
414 helper
.objs
= lhs
->value
.qlist
;
417 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
419 return helper
.result
;
428 START_TEST(simple_dict
)
433 LiteralQObject decoded
;
436 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
437 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
438 { "foo", QLIT_QINT(42) },
439 { "bar", QLIT_QSTR("hello world") },
444 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
448 .encoded
= "{\"foo\": 43}",
449 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
450 { "foo", QLIT_QINT(43) },
457 for (i
= 0; test_cases
[i
].encoded
; i
++) {
461 obj
= qobject_from_json(test_cases
[i
].encoded
);
462 fail_unless(obj
!= NULL
);
463 fail_unless(qobject_type(obj
) == QTYPE_QDICT
);
465 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
467 str
= qobject_to_json(obj
);
470 obj
= qobject_from_json(qstring_get_str(str
));
471 fail_unless(obj
!= NULL
);
472 fail_unless(qobject_type(obj
) == QTYPE_QDICT
);
474 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
481 START_TEST(simple_list
)
486 LiteralQObject decoded
;
489 .encoded
= "[43,42]",
490 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
498 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
505 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
511 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
512 QLIT_QDICT(((LiteralQDictEntry
[]){
521 for (i
= 0; test_cases
[i
].encoded
; i
++) {
525 obj
= qobject_from_json(test_cases
[i
].encoded
);
526 fail_unless(obj
!= NULL
);
527 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
529 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
531 str
= qobject_to_json(obj
);
534 obj
= qobject_from_json(qstring_get_str(str
));
535 fail_unless(obj
!= NULL
);
536 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
538 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
545 START_TEST(simple_whitespace
)
550 LiteralQObject decoded
;
553 .encoded
= " [ 43 , 42 ]",
554 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
561 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
562 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
564 QLIT_QDICT(((LiteralQDictEntry
[]){
565 { "h", QLIT_QSTR("b") },
567 QLIT_QLIST(((LiteralQObject
[]){
574 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
575 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
577 QLIT_QDICT(((LiteralQDictEntry
[]){
578 { "h", QLIT_QSTR("b") },
579 { "a", QLIT_QINT(32) },
581 QLIT_QLIST(((LiteralQObject
[]){
590 for (i
= 0; test_cases
[i
].encoded
; i
++) {
594 obj
= qobject_from_json(test_cases
[i
].encoded
);
595 fail_unless(obj
!= NULL
);
596 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
598 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
600 str
= qobject_to_json(obj
);
603 obj
= qobject_from_json(qstring_get_str(str
));
604 fail_unless(obj
!= NULL
);
605 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
607 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
615 START_TEST(simple_varargs
)
617 QObject
*embedded_obj
;
619 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
622 QLIT_QLIST(((LiteralQObject
[]){
628 embedded_obj
= qobject_from_json("[32, 42]");
629 fail_unless(embedded_obj
!= NULL
);
631 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
632 fail_unless(obj
!= NULL
);
634 fail_unless(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
640 START_TEST(empty_input
)
642 QObject
*obj
= qobject_from_json("");
643 fail_unless(obj
== NULL
);
647 START_TEST(unterminated_string
)
649 QObject
*obj
= qobject_from_json("\"abc");
650 fail_unless(obj
== NULL
);
654 START_TEST(unterminated_sq_string
)
656 QObject
*obj
= qobject_from_json("'abc");
657 fail_unless(obj
== NULL
);
661 START_TEST(unterminated_escape
)
663 QObject
*obj
= qobject_from_json("\"abc\\\"");
664 fail_unless(obj
== NULL
);
668 START_TEST(unterminated_array
)
670 QObject
*obj
= qobject_from_json("[32");
671 fail_unless(obj
== NULL
);
675 START_TEST(unterminated_array_comma
)
677 QObject
*obj
= qobject_from_json("[32,");
678 fail_unless(obj
== NULL
);
682 START_TEST(invalid_array_comma
)
684 QObject
*obj
= qobject_from_json("[32,}");
685 fail_unless(obj
== NULL
);
689 START_TEST(unterminated_dict
)
691 QObject
*obj
= qobject_from_json("{'abc':32");
692 fail_unless(obj
== NULL
);
696 START_TEST(unterminated_dict_comma
)
698 QObject
*obj
= qobject_from_json("{'abc':32,");
699 fail_unless(obj
== NULL
);
704 START_TEST(invalid_dict_comma
)
706 QObject
*obj
= qobject_from_json("{'abc':32,}");
707 fail_unless(obj
== NULL
);
711 START_TEST(unterminated_literal
)
713 QObject
*obj
= qobject_from_json("nul");
714 fail_unless(obj
== NULL
);
719 static Suite
*qjson_suite(void)
722 TCase
*string_literals
, *number_literals
, *keyword_literals
;
723 TCase
*dicts
, *lists
, *whitespace
, *varargs
, *errors
;
725 string_literals
= tcase_create("String Literals");
726 tcase_add_test(string_literals
, simple_string
);
727 tcase_add_test(string_literals
, escaped_string
);
728 tcase_add_test(string_literals
, single_quote_string
);
729 tcase_add_test(string_literals
, vararg_string
);
731 number_literals
= tcase_create("Number Literals");
732 tcase_add_test(number_literals
, simple_number
);
733 tcase_add_test(number_literals
, float_number
);
734 tcase_add_test(number_literals
, vararg_number
);
736 keyword_literals
= tcase_create("Keywords");
737 tcase_add_test(keyword_literals
, keyword_literal
);
738 dicts
= tcase_create("Objects");
739 tcase_add_test(dicts
, simple_dict
);
740 lists
= tcase_create("Lists");
741 tcase_add_test(lists
, simple_list
);
743 whitespace
= tcase_create("Whitespace");
744 tcase_add_test(whitespace
, simple_whitespace
);
746 varargs
= tcase_create("Varargs");
747 tcase_add_test(varargs
, simple_varargs
);
749 errors
= tcase_create("Invalid JSON");
750 tcase_add_test(errors
, empty_input
);
751 tcase_add_test(errors
, unterminated_string
);
752 tcase_add_test(errors
, unterminated_escape
);
753 tcase_add_test(errors
, unterminated_sq_string
);
754 tcase_add_test(errors
, unterminated_array
);
755 tcase_add_test(errors
, unterminated_array_comma
);
756 tcase_add_test(errors
, invalid_array_comma
);
757 tcase_add_test(errors
, unterminated_dict
);
758 tcase_add_test(errors
, unterminated_dict_comma
);
760 /* FIXME: this print parse error messages on stderr. */
761 tcase_add_test(errors
, invalid_dict_comma
);
762 tcase_add_test(errors
, unterminated_literal
);
765 suite
= suite_create("QJSON test-suite");
766 suite_add_tcase(suite
, string_literals
);
767 suite_add_tcase(suite
, number_literals
);
768 suite_add_tcase(suite
, keyword_literals
);
769 suite_add_tcase(suite
, dicts
);
770 suite_add_tcase(suite
, lists
);
771 suite_add_tcase(suite
, whitespace
);
772 suite_add_tcase(suite
, varargs
);
773 suite_add_tcase(suite
, errors
);
785 sr
= srunner_create(s
);
787 srunner_run_all(sr
, CK_NORMAL
);
788 nf
= srunner_ntests_failed(sr
);
791 return (nf
== 0) ? EXIT_SUCCESS
: EXIT_FAILURE
;