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
)
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" },
41 for (i
= 0; test_cases
[i
].encoded
; i
++) {
45 obj
= qobject_from_json(test_cases
[i
].encoded
);
47 fail_unless(obj
!= NULL
);
48 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
50 str
= qobject_to_qstring(obj
);
51 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
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);
65 START_TEST(simple_string
)
72 { "\"hello world\"", "hello world" },
73 { "\"the quick brown fox jumped over the fence\"",
74 "the quick brown fox jumped over the fence" },
78 for (i
= 0; test_cases
[i
].encoded
; i
++) {
82 obj
= qobject_from_json(test_cases
[i
].encoded
);
84 fail_unless(obj
!= NULL
);
85 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
87 str
= qobject_to_qstring(obj
);
88 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
90 str
= qobject_to_json(obj
);
91 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
100 START_TEST(single_quote_string
)
107 { "'hello world'", "hello world" },
108 { "'the quick brown fox \\' jumped over the fence'",
109 "the quick brown fox ' jumped over the fence" },
113 for (i
= 0; test_cases
[i
].encoded
; i
++) {
117 obj
= qobject_from_json(test_cases
[i
].encoded
);
119 fail_unless(obj
!= NULL
);
120 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
122 str
= qobject_to_qstring(obj
);
123 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
130 START_TEST(vararg_string
)
137 { "the quick brown fox jumped over the fence" },
141 for (i
= 0; test_cases
[i
].decoded
; i
++) {
145 obj
= qobject_from_jsonf("%s", test_cases
[i
].decoded
);
147 fail_unless(obj
!= NULL
);
148 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
150 str
= qobject_to_qstring(obj
);
151 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
158 START_TEST(simple_number
)
170 { "-0", 0, .skip
= 1 },
174 for (i
= 0; test_cases
[i
].encoded
; i
++) {
178 obj
= qobject_from_json(test_cases
[i
].encoded
);
179 fail_unless(obj
!= NULL
);
180 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
182 qint
= qobject_to_qint(obj
);
183 fail_unless(qint_get_int(qint
) == test_cases
[i
].decoded
);
184 if (test_cases
[i
].skip
== 0) {
187 str
= qobject_to_json(obj
);
188 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
197 START_TEST(float_number
)
207 { "-32.12313", -32.12313 },
208 { "-32.20e-10", -32.20e-10, .skip
= 1 },
212 for (i
= 0; test_cases
[i
].encoded
; i
++) {
216 obj
= qobject_from_json(test_cases
[i
].encoded
);
217 fail_unless(obj
!= NULL
);
218 fail_unless(qobject_type(obj
) == QTYPE_QFLOAT
);
220 qfloat
= qobject_to_qfloat(obj
);
221 fail_unless(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
223 if (test_cases
[i
].skip
== 0) {
226 str
= qobject_to_json(obj
);
227 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
236 START_TEST(vararg_number
)
242 int64_t value64
= 0x2342342343LL
;
243 double valuef
= 2.323423423;
245 obj
= qobject_from_jsonf("%d", value
);
246 fail_unless(obj
!= NULL
);
247 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
249 qint
= qobject_to_qint(obj
);
250 fail_unless(qint_get_int(qint
) == value
);
254 obj
= qobject_from_jsonf("%" PRId64
, value64
);
255 fail_unless(obj
!= NULL
);
256 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
258 qint
= qobject_to_qint(obj
);
259 fail_unless(qint_get_int(qint
) == value64
);
263 obj
= qobject_from_jsonf("%f", valuef
);
264 fail_unless(obj
!= NULL
);
265 fail_unless(qobject_type(obj
) == QTYPE_QFLOAT
);
267 qfloat
= qobject_to_qfloat(obj
);
268 fail_unless(qfloat_get_double(qfloat
) == valuef
);
274 START_TEST(keyword_literal
)
280 obj
= qobject_from_json("true");
281 fail_unless(obj
!= NULL
);
282 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
284 qbool
= qobject_to_qbool(obj
);
285 fail_unless(qbool_get_int(qbool
) != 0);
287 str
= qobject_to_json(obj
);
288 fail_unless(strcmp(qstring_get_str(str
), "true") == 0);
293 obj
= qobject_from_json("false");
294 fail_unless(obj
!= NULL
);
295 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
297 qbool
= qobject_to_qbool(obj
);
298 fail_unless(qbool_get_int(qbool
) == 0);
300 str
= qobject_to_json(obj
);
301 fail_unless(strcmp(qstring_get_str(str
), "false") == 0);
306 obj
= qobject_from_jsonf("%i", false);
307 fail_unless(obj
!= NULL
);
308 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
310 qbool
= qobject_to_qbool(obj
);
311 fail_unless(qbool_get_int(qbool
) == 0);
315 obj
= qobject_from_jsonf("%i", true);
316 fail_unless(obj
!= NULL
);
317 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
319 qbool
= qobject_to_qbool(obj
);
320 fail_unless(qbool_get_int(qbool
) != 0);
326 typedef struct LiteralQDictEntry LiteralQDictEntry
;
327 typedef struct LiteralQObject LiteralQObject
;
329 struct LiteralQObject
335 LiteralQDictEntry
*qdict
;
336 LiteralQObject
*qlist
;
340 struct LiteralQDictEntry
343 LiteralQObject value
;
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)}
351 typedef struct QListCompareHelper
354 LiteralQObject
*objs
;
356 } QListCompareHelper
;
358 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
360 static void compare_helper(QObject
*obj
, void *opaque
)
362 QListCompareHelper
*helper
= opaque
;
364 if (helper
->result
== 0) {
368 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
373 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
376 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
378 if (lhs
->type
!= qobject_type(rhs
)) {
384 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
386 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
390 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
391 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
393 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
401 QListCompareHelper helper
;
404 helper
.objs
= lhs
->value
.qlist
;
407 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
409 return helper
.result
;
418 START_TEST(simple_dict
)
423 LiteralQObject decoded
;
426 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
427 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
428 { "foo", QLIT_QINT(42) },
429 { "bar", QLIT_QSTR("hello world") },
434 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
438 .encoded
= "{\"foo\": 43}",
439 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
440 { "foo", QLIT_QINT(43) },
447 for (i
= 0; test_cases
[i
].encoded
; i
++) {
451 obj
= qobject_from_json(test_cases
[i
].encoded
);
452 fail_unless(obj
!= NULL
);
453 fail_unless(qobject_type(obj
) == QTYPE_QDICT
);
455 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
457 str
= qobject_to_json(obj
);
460 obj
= qobject_from_json(qstring_get_str(str
));
461 fail_unless(obj
!= NULL
);
462 fail_unless(qobject_type(obj
) == QTYPE_QDICT
);
464 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
471 START_TEST(simple_list
)
476 LiteralQObject decoded
;
479 .encoded
= "[43,42]",
480 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
488 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
495 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
501 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
502 QLIT_QDICT(((LiteralQDictEntry
[]){
511 for (i
= 0; test_cases
[i
].encoded
; i
++) {
515 obj
= qobject_from_json(test_cases
[i
].encoded
);
516 fail_unless(obj
!= NULL
);
517 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
519 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
521 str
= qobject_to_json(obj
);
524 obj
= qobject_from_json(qstring_get_str(str
));
525 fail_unless(obj
!= NULL
);
526 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
528 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
535 START_TEST(simple_whitespace
)
540 LiteralQObject decoded
;
543 .encoded
= " [ 43 , 42 ]",
544 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
551 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
552 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
554 QLIT_QDICT(((LiteralQDictEntry
[]){
555 { "h", QLIT_QSTR("b") },
557 QLIT_QLIST(((LiteralQObject
[]){
564 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
565 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
567 QLIT_QDICT(((LiteralQDictEntry
[]){
568 { "h", QLIT_QSTR("b") },
569 { "a", QLIT_QINT(32) },
571 QLIT_QLIST(((LiteralQObject
[]){
580 for (i
= 0; test_cases
[i
].encoded
; i
++) {
584 obj
= qobject_from_json(test_cases
[i
].encoded
);
585 fail_unless(obj
!= NULL
);
586 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
588 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
590 str
= qobject_to_json(obj
);
593 obj
= qobject_from_json(qstring_get_str(str
));
594 fail_unless(obj
!= NULL
);
595 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
597 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
605 START_TEST(simple_varargs
)
607 QObject
*embedded_obj
;
609 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
612 QLIT_QLIST(((LiteralQObject
[]){
618 embedded_obj
= qobject_from_json("[32, 42]");
619 fail_unless(embedded_obj
!= NULL
);
621 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
622 fail_unless(obj
!= NULL
);
624 fail_unless(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
630 static Suite
*qjson_suite(void)
633 TCase
*string_literals
, *number_literals
, *keyword_literals
;
634 TCase
*dicts
, *lists
, *whitespace
, *varargs
;
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
);
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
);
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
);
654 whitespace
= tcase_create("Whitespace");
655 tcase_add_test(whitespace
, simple_whitespace
);
657 varargs
= tcase_create("Varargs");
658 tcase_add_test(varargs
, simple_varargs
);
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
);
679 sr
= srunner_create(s
);
681 srunner_run_all(sr
, CK_NORMAL
);
682 nf
= srunner_ntests_failed(sr
);
685 return (nf
== 0) ? EXIT_SUCCESS
: EXIT_FAILURE
;