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.
22 #include "qemu-common.h"
24 START_TEST(escaped_string
)
33 { "\"hello world \\\"embedded string\\\"\"",
34 "hello world \"embedded string\"" },
35 { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
36 { "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip
= 1 },
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" },
42 for (i
= 0; test_cases
[i
].encoded
; i
++) {
46 obj
= qobject_from_json(test_cases
[i
].encoded
);
48 fail_unless(obj
!= NULL
);
49 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
51 str
= qobject_to_qstring(obj
);
52 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
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);
66 START_TEST(simple_string
)
73 { "\"hello world\"", "hello world" },
74 { "\"the quick brown fox jumped over the fence\"",
75 "the quick brown fox jumped over the fence" },
79 for (i
= 0; test_cases
[i
].encoded
; i
++) {
83 obj
= qobject_from_json(test_cases
[i
].encoded
);
85 fail_unless(obj
!= NULL
);
86 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
88 str
= qobject_to_qstring(obj
);
89 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
91 str
= qobject_to_json(obj
);
92 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
101 START_TEST(single_quote_string
)
108 { "'hello world'", "hello world" },
109 { "'the quick brown fox \\' jumped over the fence'",
110 "the quick brown fox ' jumped over the fence" },
114 for (i
= 0; test_cases
[i
].encoded
; i
++) {
118 obj
= qobject_from_json(test_cases
[i
].encoded
);
120 fail_unless(obj
!= NULL
);
121 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
123 str
= qobject_to_qstring(obj
);
124 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
131 START_TEST(vararg_string
)
138 { "the quick brown fox jumped over the fence" },
142 for (i
= 0; test_cases
[i
].decoded
; i
++) {
146 obj
= qobject_from_jsonf("%s", test_cases
[i
].decoded
);
148 fail_unless(obj
!= NULL
);
149 fail_unless(qobject_type(obj
) == QTYPE_QSTRING
);
151 str
= qobject_to_qstring(obj
);
152 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
159 START_TEST(simple_number
)
171 { "-0", 0, .skip
= 1 },
175 for (i
= 0; test_cases
[i
].encoded
; i
++) {
179 obj
= qobject_from_json(test_cases
[i
].encoded
);
180 fail_unless(obj
!= NULL
);
181 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
183 qint
= qobject_to_qint(obj
);
184 fail_unless(qint_get_int(qint
) == test_cases
[i
].decoded
);
185 if (test_cases
[i
].skip
== 0) {
188 str
= qobject_to_json(obj
);
189 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
198 START_TEST(float_number
)
208 { "-32.12313", -32.12313 },
209 { "-32.20e-10", -32.20e-10, .skip
= 1 },
213 for (i
= 0; test_cases
[i
].encoded
; i
++) {
217 obj
= qobject_from_json(test_cases
[i
].encoded
);
218 fail_unless(obj
!= NULL
);
219 fail_unless(qobject_type(obj
) == QTYPE_QFLOAT
);
221 qfloat
= qobject_to_qfloat(obj
);
222 fail_unless(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
224 if (test_cases
[i
].skip
== 0) {
227 str
= qobject_to_json(obj
);
228 fail_unless(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
237 START_TEST(vararg_number
)
243 int64_t value64
= 0x2342342343LL
;
244 double valuef
= 2.323423423;
246 obj
= qobject_from_jsonf("%d", value
);
247 fail_unless(obj
!= NULL
);
248 fail_unless(qobject_type(obj
) == QTYPE_QINT
);
250 qint
= qobject_to_qint(obj
);
251 fail_unless(qint_get_int(qint
) == value
);
255 obj
= qobject_from_jsonf("%" PRId64
, value64
);
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
) == value64
);
264 obj
= qobject_from_jsonf("%f", valuef
);
265 fail_unless(obj
!= NULL
);
266 fail_unless(qobject_type(obj
) == QTYPE_QFLOAT
);
268 qfloat
= qobject_to_qfloat(obj
);
269 fail_unless(qfloat_get_double(qfloat
) == valuef
);
275 START_TEST(keyword_literal
)
281 obj
= qobject_from_json("true");
282 fail_unless(obj
!= NULL
);
283 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
285 qbool
= qobject_to_qbool(obj
);
286 fail_unless(qbool_get_int(qbool
) != 0);
288 str
= qobject_to_json(obj
);
289 fail_unless(strcmp(qstring_get_str(str
), "true") == 0);
294 obj
= qobject_from_json("false");
295 fail_unless(obj
!= NULL
);
296 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
298 qbool
= qobject_to_qbool(obj
);
299 fail_unless(qbool_get_int(qbool
) == 0);
301 str
= qobject_to_json(obj
);
302 fail_unless(strcmp(qstring_get_str(str
), "false") == 0);
307 obj
= qobject_from_jsonf("%i", false);
308 fail_unless(obj
!= NULL
);
309 fail_unless(qobject_type(obj
) == QTYPE_QBOOL
);
311 qbool
= qobject_to_qbool(obj
);
312 fail_unless(qbool_get_int(qbool
) == 0);
316 obj
= qobject_from_jsonf("%i", true);
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);
327 typedef struct LiteralQDictEntry LiteralQDictEntry
;
328 typedef struct LiteralQObject LiteralQObject
;
330 struct LiteralQObject
336 LiteralQDictEntry
*qdict
;
337 LiteralQObject
*qlist
;
341 struct LiteralQDictEntry
344 LiteralQObject value
;
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)}
352 typedef struct QListCompareHelper
355 LiteralQObject
*objs
;
357 } QListCompareHelper
;
359 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
361 static void compare_helper(QObject
*obj
, void *opaque
)
363 QListCompareHelper
*helper
= opaque
;
365 if (helper
->result
== 0) {
369 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
374 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
377 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
379 if (lhs
->type
!= qobject_type(rhs
)) {
385 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
387 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
391 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
392 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
394 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
402 QListCompareHelper helper
;
405 helper
.objs
= lhs
->value
.qlist
;
408 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
410 return helper
.result
;
419 START_TEST(simple_dict
)
424 LiteralQObject decoded
;
427 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
428 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
429 { "foo", QLIT_QINT(42) },
430 { "bar", QLIT_QSTR("hello world") },
435 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
439 .encoded
= "{\"foo\": 43}",
440 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
441 { "foo", QLIT_QINT(43) },
448 for (i
= 0; test_cases
[i
].encoded
; i
++) {
452 obj
= qobject_from_json(test_cases
[i
].encoded
);
453 fail_unless(obj
!= NULL
);
454 fail_unless(qobject_type(obj
) == QTYPE_QDICT
);
456 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
458 str
= qobject_to_json(obj
);
461 obj
= qobject_from_json(qstring_get_str(str
));
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);
472 START_TEST(simple_list
)
477 LiteralQObject decoded
;
480 .encoded
= "[43,42]",
481 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
489 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
496 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
502 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
503 QLIT_QDICT(((LiteralQDictEntry
[]){
512 for (i
= 0; test_cases
[i
].encoded
; i
++) {
516 obj
= qobject_from_json(test_cases
[i
].encoded
);
517 fail_unless(obj
!= NULL
);
518 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
520 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
522 str
= qobject_to_json(obj
);
525 obj
= qobject_from_json(qstring_get_str(str
));
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);
536 START_TEST(simple_whitespace
)
541 LiteralQObject decoded
;
544 .encoded
= " [ 43 , 42 ]",
545 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
552 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
553 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
555 QLIT_QDICT(((LiteralQDictEntry
[]){
556 { "h", QLIT_QSTR("b") },
558 QLIT_QLIST(((LiteralQObject
[]){
565 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
566 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
568 QLIT_QDICT(((LiteralQDictEntry
[]){
569 { "h", QLIT_QSTR("b") },
570 { "a", QLIT_QINT(32) },
572 QLIT_QLIST(((LiteralQObject
[]){
581 for (i
= 0; test_cases
[i
].encoded
; i
++) {
585 obj
= qobject_from_json(test_cases
[i
].encoded
);
586 fail_unless(obj
!= NULL
);
587 fail_unless(qobject_type(obj
) == QTYPE_QLIST
);
589 fail_unless(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
591 str
= qobject_to_json(obj
);
594 obj
= qobject_from_json(qstring_get_str(str
));
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);
606 START_TEST(simple_varargs
)
608 QObject
*embedded_obj
;
610 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
613 QLIT_QLIST(((LiteralQObject
[]){
619 embedded_obj
= qobject_from_json("[32, 42]");
620 fail_unless(embedded_obj
!= NULL
);
622 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
623 fail_unless(obj
!= NULL
);
625 fail_unless(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
631 static Suite
*qjson_suite(void)
634 TCase
*string_literals
, *number_literals
, *keyword_literals
;
635 TCase
*dicts
, *lists
, *whitespace
, *varargs
;
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
);
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
);
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
);
655 whitespace
= tcase_create("Whitespace");
656 tcase_add_test(whitespace
, simple_whitespace
);
658 varargs
= tcase_create("Varargs");
659 tcase_add_test(varargs
, simple_varargs
);
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
);
680 sr
= srunner_create(s
);
682 srunner_run_all(sr
, CK_NORMAL
);
683 nf
= srunner_ntests_failed(sr
);
686 return (nf
== 0) ? EXIT_SUCCESS
: EXIT_FAILURE
;