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 static void escaped_string(void)
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 g_assert(obj
!= NULL
);
56 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
58 str
= qobject_to_qstring(obj
);
59 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].decoded
);
61 if (test_cases
[i
].skip
== 0) {
62 str
= qobject_to_json(obj
);
63 g_assert_cmpstr(qstring_get_str(str
), ==, test_cases
[i
].encoded
);
71 static void simple_string(void)
78 { "\"hello world\"", "hello world" },
79 { "\"the quick brown fox jumped over the fence\"",
80 "the quick brown fox jumped over the fence" },
84 for (i
= 0; test_cases
[i
].encoded
; i
++) {
88 obj
= qobject_from_json(test_cases
[i
].encoded
);
90 g_assert(obj
!= NULL
);
91 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
93 str
= qobject_to_qstring(obj
);
94 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
96 str
= qobject_to_json(obj
);
97 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
105 static void single_quote_string(void)
112 { "'hello world'", "hello world" },
113 { "'the quick brown fox \\' jumped over the fence'",
114 "the quick brown fox ' jumped over the fence" },
118 for (i
= 0; test_cases
[i
].encoded
; i
++) {
122 obj
= qobject_from_json(test_cases
[i
].encoded
);
124 g_assert(obj
!= NULL
);
125 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
127 str
= qobject_to_qstring(obj
);
128 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
134 static void vararg_string(void)
141 { "the quick brown fox jumped over the fence" },
145 for (i
= 0; test_cases
[i
].decoded
; i
++) {
149 obj
= qobject_from_jsonf("%s", test_cases
[i
].decoded
);
151 g_assert(obj
!= NULL
);
152 g_assert(qobject_type(obj
) == QTYPE_QSTRING
);
154 str
= qobject_to_qstring(obj
);
155 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].decoded
) == 0);
161 static void simple_number(void)
173 { "-0", 0, .skip
= 1 },
177 for (i
= 0; test_cases
[i
].encoded
; i
++) {
181 obj
= qobject_from_json(test_cases
[i
].encoded
);
182 g_assert(obj
!= NULL
);
183 g_assert(qobject_type(obj
) == QTYPE_QINT
);
185 qint
= qobject_to_qint(obj
);
186 g_assert(qint_get_int(qint
) == test_cases
[i
].decoded
);
187 if (test_cases
[i
].skip
== 0) {
190 str
= qobject_to_json(obj
);
191 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
199 static void float_number(void)
209 { "-32.12313", -32.12313 },
210 { "-32.20e-10", -32.20e-10, .skip
= 1 },
214 for (i
= 0; test_cases
[i
].encoded
; i
++) {
218 obj
= qobject_from_json(test_cases
[i
].encoded
);
219 g_assert(obj
!= NULL
);
220 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
222 qfloat
= qobject_to_qfloat(obj
);
223 g_assert(qfloat_get_double(qfloat
) == test_cases
[i
].decoded
);
225 if (test_cases
[i
].skip
== 0) {
228 str
= qobject_to_json(obj
);
229 g_assert(strcmp(qstring_get_str(str
), test_cases
[i
].encoded
) == 0);
237 static void vararg_number(void)
243 int64_t value64
= 0x2342342343LL
;
244 double valuef
= 2.323423423;
246 obj
= qobject_from_jsonf("%d", value
);
247 g_assert(obj
!= NULL
);
248 g_assert(qobject_type(obj
) == QTYPE_QINT
);
250 qint
= qobject_to_qint(obj
);
251 g_assert(qint_get_int(qint
) == value
);
255 obj
= qobject_from_jsonf("%" PRId64
, value64
);
256 g_assert(obj
!= NULL
);
257 g_assert(qobject_type(obj
) == QTYPE_QINT
);
259 qint
= qobject_to_qint(obj
);
260 g_assert(qint_get_int(qint
) == value64
);
264 obj
= qobject_from_jsonf("%f", valuef
);
265 g_assert(obj
!= NULL
);
266 g_assert(qobject_type(obj
) == QTYPE_QFLOAT
);
268 qfloat
= qobject_to_qfloat(obj
);
269 g_assert(qfloat_get_double(qfloat
) == valuef
);
274 static void keyword_literal(void)
280 obj
= qobject_from_json("true");
281 g_assert(obj
!= NULL
);
282 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
284 qbool
= qobject_to_qbool(obj
);
285 g_assert(qbool_get_int(qbool
) != 0);
287 str
= qobject_to_json(obj
);
288 g_assert(strcmp(qstring_get_str(str
), "true") == 0);
293 obj
= qobject_from_json("false");
294 g_assert(obj
!= NULL
);
295 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
297 qbool
= qobject_to_qbool(obj
);
298 g_assert(qbool_get_int(qbool
) == 0);
300 str
= qobject_to_json(obj
);
301 g_assert(strcmp(qstring_get_str(str
), "false") == 0);
306 obj
= qobject_from_jsonf("%i", false);
307 g_assert(obj
!= NULL
);
308 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
310 qbool
= qobject_to_qbool(obj
);
311 g_assert(qbool_get_int(qbool
) == 0);
315 obj
= qobject_from_jsonf("%i", true);
316 g_assert(obj
!= NULL
);
317 g_assert(qobject_type(obj
) == QTYPE_QBOOL
);
319 qbool
= qobject_to_qbool(obj
);
320 g_assert(qbool_get_int(qbool
) != 0);
325 typedef struct LiteralQDictEntry LiteralQDictEntry
;
326 typedef struct LiteralQObject LiteralQObject
;
328 struct LiteralQObject
334 LiteralQDictEntry
*qdict
;
335 LiteralQObject
*qlist
;
339 struct LiteralQDictEntry
342 LiteralQObject value
;
345 #define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
346 #define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
347 #define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
348 #define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
350 typedef struct QListCompareHelper
353 LiteralQObject
*objs
;
355 } QListCompareHelper
;
357 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
);
359 static void compare_helper(QObject
*obj
, void *opaque
)
361 QListCompareHelper
*helper
= opaque
;
363 if (helper
->result
== 0) {
367 if (helper
->objs
[helper
->index
].type
== QTYPE_NONE
) {
372 helper
->result
= compare_litqobj_to_qobj(&helper
->objs
[helper
->index
++], obj
);
375 static int compare_litqobj_to_qobj(LiteralQObject
*lhs
, QObject
*rhs
)
377 if (lhs
->type
!= qobject_type(rhs
)) {
383 return lhs
->value
.qint
== qint_get_int(qobject_to_qint(rhs
));
385 return (strcmp(lhs
->value
.qstr
, qstring_get_str(qobject_to_qstring(rhs
))) == 0);
389 for (i
= 0; lhs
->value
.qdict
[i
].key
; i
++) {
390 QObject
*obj
= qdict_get(qobject_to_qdict(rhs
), lhs
->value
.qdict
[i
].key
);
392 if (!compare_litqobj_to_qobj(&lhs
->value
.qdict
[i
].value
, obj
)) {
400 QListCompareHelper helper
;
403 helper
.objs
= lhs
->value
.qlist
;
406 qlist_iter(qobject_to_qlist(rhs
), compare_helper
, &helper
);
408 return helper
.result
;
417 static void simple_dict(void)
422 LiteralQObject decoded
;
425 .encoded
= "{\"foo\": 42, \"bar\": \"hello world\"}",
426 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
427 { "foo", QLIT_QINT(42) },
428 { "bar", QLIT_QSTR("hello world") },
433 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
437 .encoded
= "{\"foo\": 43}",
438 .decoded
= QLIT_QDICT(((LiteralQDictEntry
[]){
439 { "foo", QLIT_QINT(43) },
446 for (i
= 0; test_cases
[i
].encoded
; i
++) {
450 obj
= qobject_from_json(test_cases
[i
].encoded
);
451 g_assert(obj
!= NULL
);
452 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
454 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
456 str
= qobject_to_json(obj
);
459 obj
= qobject_from_json(qstring_get_str(str
));
460 g_assert(obj
!= NULL
);
461 g_assert(qobject_type(obj
) == QTYPE_QDICT
);
463 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
469 static void simple_list(void)
474 LiteralQObject decoded
;
477 .encoded
= "[43,42]",
478 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
486 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
493 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
499 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
500 QLIT_QDICT(((LiteralQDictEntry
[]){
509 for (i
= 0; test_cases
[i
].encoded
; i
++) {
513 obj
= qobject_from_json(test_cases
[i
].encoded
);
514 g_assert(obj
!= NULL
);
515 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
517 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
519 str
= qobject_to_json(obj
);
522 obj
= qobject_from_json(qstring_get_str(str
));
523 g_assert(obj
!= NULL
);
524 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
526 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
532 static void simple_whitespace(void)
537 LiteralQObject decoded
;
540 .encoded
= " [ 43 , 42 ]",
541 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
548 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
549 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
551 QLIT_QDICT(((LiteralQDictEntry
[]){
552 { "h", QLIT_QSTR("b") },
554 QLIT_QLIST(((LiteralQObject
[]){
561 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
562 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
564 QLIT_QDICT(((LiteralQDictEntry
[]){
565 { "h", QLIT_QSTR("b") },
566 { "a", QLIT_QINT(32) },
568 QLIT_QLIST(((LiteralQObject
[]){
577 for (i
= 0; test_cases
[i
].encoded
; i
++) {
581 obj
= qobject_from_json(test_cases
[i
].encoded
);
582 g_assert(obj
!= NULL
);
583 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
585 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
587 str
= qobject_to_json(obj
);
590 obj
= qobject_from_json(qstring_get_str(str
));
591 g_assert(obj
!= NULL
);
592 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
594 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
601 static void simple_varargs(void)
603 QObject
*embedded_obj
;
605 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
608 QLIT_QLIST(((LiteralQObject
[]){
614 embedded_obj
= qobject_from_json("[32, 42]");
615 g_assert(embedded_obj
!= NULL
);
617 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
618 g_assert(obj
!= NULL
);
620 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
625 static void empty_input(void)
627 const char *empty
= "";
629 QObject
*obj
= qobject_from_json(empty
);
630 g_assert(obj
== NULL
);
633 static void unterminated_string(void)
635 QObject
*obj
= qobject_from_json("\"abc");
636 g_assert(obj
== NULL
);
639 static void unterminated_sq_string(void)
641 QObject
*obj
= qobject_from_json("'abc");
642 g_assert(obj
== NULL
);
645 static void unterminated_escape(void)
647 QObject
*obj
= qobject_from_json("\"abc\\\"");
648 g_assert(obj
== NULL
);
651 static void unterminated_array(void)
653 QObject
*obj
= qobject_from_json("[32");
654 g_assert(obj
== NULL
);
657 static void unterminated_array_comma(void)
659 QObject
*obj
= qobject_from_json("[32,");
660 g_assert(obj
== NULL
);
663 static void invalid_array_comma(void)
665 QObject
*obj
= qobject_from_json("[32,}");
666 g_assert(obj
== NULL
);
669 static void unterminated_dict(void)
671 QObject
*obj
= qobject_from_json("{'abc':32");
672 g_assert(obj
== NULL
);
675 static void unterminated_dict_comma(void)
677 QObject
*obj
= qobject_from_json("{'abc':32,");
678 g_assert(obj
== NULL
);
681 static void invalid_dict_comma(void)
683 QObject
*obj
= qobject_from_json("{'abc':32,}");
684 g_assert(obj
== NULL
);
687 static void unterminated_literal(void)
689 QObject
*obj
= qobject_from_json("nul");
690 g_assert(obj
== NULL
);
693 int main(int argc
, char **argv
)
695 g_test_init(&argc
, &argv
, NULL
);
697 g_test_add_func("/literals/string/simple", simple_string
);
698 g_test_add_func("/literals/string/escaped", escaped_string
);
699 g_test_add_func("/literals/string/single_quote", single_quote_string
);
700 g_test_add_func("/literals/string/vararg", vararg_string
);
702 g_test_add_func("/literals/number/simple", simple_number
);
703 g_test_add_func("/literals/number/float", float_number
);
704 g_test_add_func("/literals/number/vararg", vararg_number
);
706 g_test_add_func("/literals/keyword", keyword_literal
);
708 g_test_add_func("/dicts/simple_dict", simple_dict
);
709 g_test_add_func("/lists/simple_list", simple_list
);
711 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
713 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
715 g_test_add_func("/errors/empty_input", empty_input
);
716 g_test_add_func("/errors/unterminated/string", unterminated_string
);
717 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
718 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
719 g_test_add_func("/errors/unterminated/array", unterminated_array
);
720 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
721 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
722 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
723 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
724 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
725 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);