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.
13 #include "qapi/qmp/qstring.h"
14 #include "qapi/qmp/qint.h"
15 #include "qapi/qmp/qdict.h"
16 #include "qapi/qmp/qlist.h"
17 #include "qapi/qmp/qfloat.h"
18 #include "qapi/qmp/qbool.h"
19 #include "qapi/qmp/qjson.h"
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);
470 * this generates json of the form:
471 * a(0,m) = [0, 1, ..., m-1]
476 * 'key(n-1)': a(n-1,m)
479 static void gen_test_json(GString
*gstr
, int nest_level_max
,
485 if (nest_level_max
== 0) {
486 g_string_append(gstr
, "[");
487 for (i
= 0; i
< elem_count
; i
++) {
488 g_string_append_printf(gstr
, "%d", i
);
489 if (i
< elem_count
- 1) {
490 g_string_append_printf(gstr
, ", ");
493 g_string_append(gstr
, "]");
497 g_string_append(gstr
, "{");
498 for (i
= 0; i
< nest_level_max
; i
++) {
499 g_string_append_printf(gstr
, "'key%d': ", i
);
500 gen_test_json(gstr
, i
, elem_count
);
501 if (i
< nest_level_max
- 1) {
502 g_string_append(gstr
, ",");
505 g_string_append(gstr
, "}");
508 static void large_dict(void)
510 GString
*gstr
= g_string_new("");
513 gen_test_json(gstr
, 10, 100);
514 obj
= qobject_from_json(gstr
->str
);
515 g_assert(obj
!= NULL
);
518 g_string_free(gstr
, true);
521 static void simple_list(void)
526 LiteralQObject decoded
;
529 .encoded
= "[43,42]",
530 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
538 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
545 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
551 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
552 QLIT_QDICT(((LiteralQDictEntry
[]){
561 for (i
= 0; test_cases
[i
].encoded
; i
++) {
565 obj
= qobject_from_json(test_cases
[i
].encoded
);
566 g_assert(obj
!= NULL
);
567 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
569 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
571 str
= qobject_to_json(obj
);
574 obj
= qobject_from_json(qstring_get_str(str
));
575 g_assert(obj
!= NULL
);
576 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
578 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
584 static void simple_whitespace(void)
589 LiteralQObject decoded
;
592 .encoded
= " [ 43 , 42 ]",
593 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
600 .encoded
= " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
601 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
603 QLIT_QDICT(((LiteralQDictEntry
[]){
604 { "h", QLIT_QSTR("b") },
606 QLIT_QLIST(((LiteralQObject
[]){
613 .encoded
= " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
614 .decoded
= QLIT_QLIST(((LiteralQObject
[]){
616 QLIT_QDICT(((LiteralQDictEntry
[]){
617 { "h", QLIT_QSTR("b") },
618 { "a", QLIT_QINT(32) },
620 QLIT_QLIST(((LiteralQObject
[]){
629 for (i
= 0; test_cases
[i
].encoded
; i
++) {
633 obj
= qobject_from_json(test_cases
[i
].encoded
);
634 g_assert(obj
!= NULL
);
635 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
637 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
639 str
= qobject_to_json(obj
);
642 obj
= qobject_from_json(qstring_get_str(str
));
643 g_assert(obj
!= NULL
);
644 g_assert(qobject_type(obj
) == QTYPE_QLIST
);
646 g_assert(compare_litqobj_to_qobj(&test_cases
[i
].decoded
, obj
) == 1);
653 static void simple_varargs(void)
655 QObject
*embedded_obj
;
657 LiteralQObject decoded
= QLIT_QLIST(((LiteralQObject
[]){
660 QLIT_QLIST(((LiteralQObject
[]){
666 embedded_obj
= qobject_from_json("[32, 42]");
667 g_assert(embedded_obj
!= NULL
);
669 obj
= qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj
);
670 g_assert(obj
!= NULL
);
672 g_assert(compare_litqobj_to_qobj(&decoded
, obj
) == 1);
677 static void empty_input(void)
679 const char *empty
= "";
681 QObject
*obj
= qobject_from_json(empty
);
682 g_assert(obj
== NULL
);
685 static void unterminated_string(void)
687 QObject
*obj
= qobject_from_json("\"abc");
688 g_assert(obj
== NULL
);
691 static void unterminated_sq_string(void)
693 QObject
*obj
= qobject_from_json("'abc");
694 g_assert(obj
== NULL
);
697 static void unterminated_escape(void)
699 QObject
*obj
= qobject_from_json("\"abc\\\"");
700 g_assert(obj
== NULL
);
703 static void unterminated_array(void)
705 QObject
*obj
= qobject_from_json("[32");
706 g_assert(obj
== NULL
);
709 static void unterminated_array_comma(void)
711 QObject
*obj
= qobject_from_json("[32,");
712 g_assert(obj
== NULL
);
715 static void invalid_array_comma(void)
717 QObject
*obj
= qobject_from_json("[32,}");
718 g_assert(obj
== NULL
);
721 static void unterminated_dict(void)
723 QObject
*obj
= qobject_from_json("{'abc':32");
724 g_assert(obj
== NULL
);
727 static void unterminated_dict_comma(void)
729 QObject
*obj
= qobject_from_json("{'abc':32,");
730 g_assert(obj
== NULL
);
733 static void invalid_dict_comma(void)
735 QObject
*obj
= qobject_from_json("{'abc':32,}");
736 g_assert(obj
== NULL
);
739 static void unterminated_literal(void)
741 QObject
*obj
= qobject_from_json("nul");
742 g_assert(obj
== NULL
);
745 int main(int argc
, char **argv
)
747 g_test_init(&argc
, &argv
, NULL
);
749 g_test_add_func("/literals/string/simple", simple_string
);
750 g_test_add_func("/literals/string/escaped", escaped_string
);
751 g_test_add_func("/literals/string/single_quote", single_quote_string
);
752 g_test_add_func("/literals/string/vararg", vararg_string
);
754 g_test_add_func("/literals/number/simple", simple_number
);
755 g_test_add_func("/literals/number/float", float_number
);
756 g_test_add_func("/literals/number/vararg", vararg_number
);
758 g_test_add_func("/literals/keyword", keyword_literal
);
760 g_test_add_func("/dicts/simple_dict", simple_dict
);
761 g_test_add_func("/dicts/large_dict", large_dict
);
762 g_test_add_func("/lists/simple_list", simple_list
);
764 g_test_add_func("/whitespace/simple_whitespace", simple_whitespace
);
766 g_test_add_func("/varargs/simple_varargs", simple_varargs
);
768 g_test_add_func("/errors/empty_input", empty_input
);
769 g_test_add_func("/errors/unterminated/string", unterminated_string
);
770 g_test_add_func("/errors/unterminated/escape", unterminated_escape
);
771 g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string
);
772 g_test_add_func("/errors/unterminated/array", unterminated_array
);
773 g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma
);
774 g_test_add_func("/errors/unterminated/dict", unterminated_dict
);
775 g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma
);
776 g_test_add_func("/errors/invalid_array_comma", invalid_array_comma
);
777 g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma
);
778 g_test_add_func("/errors/unterminated/literal", unterminated_literal
);