]> git.proxmox.com Git - qemu.git/blobdiff - check-qjson.c
qemu-char: Print strerror message on failure
[qemu.git] / check-qjson.c
index 17533897837682866e36686cb3a831fbf683167e..64fcdcb4ad0ac5c113d8ddd343375b0c46bf20ce 100644 (file)
@@ -9,7 +9,6 @@
  *
  */
 #include <check.h>
-#include <stdbool.h>
 
 #include "qstring.h"
 #include "qint.h"
@@ -27,12 +26,20 @@ START_TEST(escaped_string)
     struct {
         const char *encoded;
         const char *decoded;
+        int skip;
     } test_cases[] = {
+        { "\"\\b\"", "\b" },
+        { "\"\\f\"", "\f" },
+        { "\"\\n\"", "\n" },
+        { "\"\\r\"", "\r" },
+        { "\"\\t\"", "\t" },
+        { "\"\\/\"", "\\/" },
+        { "\"\\\\\"", "\\" },
         { "\"\\\"\"", "\"" },
         { "\"hello world \\\"embedded string\\\"\"",
           "hello world \"embedded string\"" },
         { "\"hello world\\nwith new line\"", "hello world\nwith new line" },
-        { "\"single byte utf-8 \\u0020\"", "single byte utf-8  " },
+        { "\"single byte utf-8 \\u0020\"", "single byte utf-8  ", .skip = 1 },
         { "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
         { "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
         {}
@@ -48,7 +55,17 @@ START_TEST(escaped_string)
         fail_unless(qobject_type(obj) == QTYPE_QSTRING);
         
         str = qobject_to_qstring(obj);
-        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+        fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0,
+                    "%s != %s\n", qstring_get_str(str), test_cases[i].decoded);
+
+        if (test_cases[i].skip == 0) {
+            str = qobject_to_json(obj);
+            fail_unless(strcmp(qstring_get_str(str),test_cases[i].encoded) == 0,
+                        "%s != %s\n", qstring_get_str(str),
+                                      test_cases[i].encoded);
+
+            qobject_decref(obj);
+        }
 
         QDECREF(str);
     }
@@ -80,6 +97,11 @@ START_TEST(simple_string)
         str = qobject_to_qstring(obj);
         fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
 
+        str = qobject_to_json(obj);
+        fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+
+        qobject_decref(obj);
+        
         QDECREF(str);
     }
 }
@@ -149,12 +171,13 @@ START_TEST(simple_number)
     struct {
         const char *encoded;
         int64_t decoded;
+        int skip;
     } test_cases[] = {
         { "0", 0 },
         { "1234", 1234 },
         { "1", 1 },
         { "-32", -32 },
-        { "-0", 0 },
+        { "-0", 0, .skip = 1 },
         { },
     };
 
@@ -168,6 +191,13 @@ START_TEST(simple_number)
 
         qint = qobject_to_qint(obj);
         fail_unless(qint_get_int(qint) == test_cases[i].decoded);
+        if (test_cases[i].skip == 0) {
+            QString *str;
+
+            str = qobject_to_json(obj);
+            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+            QDECREF(str);
+        }
 
         QDECREF(qint);
     }
@@ -180,11 +210,12 @@ START_TEST(float_number)
     struct {
         const char *encoded;
         double decoded;
+        int skip;
     } test_cases[] = {
         { "32.43", 32.43 },
         { "0.222", 0.222 },
         { "-32.12313", -32.12313 },
-        { "-32.20e-10", -32.20e-10 },
+        { "-32.20e-10", -32.20e-10, .skip = 1 },
         { },
     };
 
@@ -199,6 +230,14 @@ START_TEST(float_number)
         qfloat = qobject_to_qfloat(obj);
         fail_unless(qfloat_get_double(qfloat) == test_cases[i].decoded);
 
+        if (test_cases[i].skip == 0) {
+            QString *str;
+
+            str = qobject_to_json(obj);
+            fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+            QDECREF(str);
+        }
+
         QDECREF(qfloat);
     }
 }
@@ -246,6 +285,7 @@ START_TEST(keyword_literal)
 {
     QObject *obj;
     QBool *qbool;
+    QString *str;
 
     obj = qobject_from_json("true");
     fail_unless(obj != NULL);
@@ -254,6 +294,10 @@ START_TEST(keyword_literal)
     qbool = qobject_to_qbool(obj);
     fail_unless(qbool_get_int(qbool) != 0);
 
+    str = qobject_to_json(obj);
+    fail_unless(strcmp(qstring_get_str(str), "true") == 0);
+    QDECREF(str);
+
     QDECREF(qbool);
 
     obj = qobject_from_json("false");
@@ -263,6 +307,10 @@ START_TEST(keyword_literal)
     qbool = qobject_to_qbool(obj);
     fail_unless(qbool_get_int(qbool) == 0);
 
+    str = qobject_to_json(obj);
+    fail_unless(strcmp(qstring_get_str(str), "false") == 0);
+    QDECREF(str);
+
     QDECREF(qbool);
 
     obj = qobject_from_jsonf("%i", false);
@@ -385,7 +433,7 @@ START_TEST(simple_dict)
         LiteralQObject decoded;
     } test_cases[] = {
         {
-            .encoded = "{\"foo\":42,\"bar\":\"hello world\"}",
+            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
             .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
                         { "foo", QLIT_QINT(42) },
                         { "bar", QLIT_QSTR("hello world") },
@@ -397,7 +445,7 @@ START_TEST(simple_dict)
                         { }
                     })),
         }, {
-            .encoded = "{\"foo\":43}",
+            .encoded = "{\"foo\": 43}",
             .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
                         { "foo", QLIT_QINT(43) },
                         { }
@@ -408,6 +456,7 @@ START_TEST(simple_dict)
 
     for (i = 0; test_cases[i].encoded; i++) {
         QObject *obj;
+        QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded);
         fail_unless(obj != NULL);
@@ -415,7 +464,16 @@ START_TEST(simple_dict)
 
         fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
 
+        str = qobject_to_json(obj);
         qobject_decref(obj);
+
+        obj = qobject_from_json(qstring_get_str(str));
+        fail_unless(obj != NULL);
+        fail_unless(qobject_type(obj) == QTYPE_QDICT);
+
+        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        qobject_decref(obj);
+        QDECREF(str);
     }
 }
 END_TEST
@@ -462,6 +520,7 @@ START_TEST(simple_list)
 
     for (i = 0; test_cases[i].encoded; i++) {
         QObject *obj;
+        QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded);
         fail_unless(obj != NULL);
@@ -469,7 +528,16 @@ START_TEST(simple_list)
 
         fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
 
+        str = qobject_to_json(obj);
         qobject_decref(obj);
+
+        obj = qobject_from_json(qstring_get_str(str));
+        fail_unless(obj != NULL);
+        fail_unless(qobject_type(obj) == QTYPE_QLIST);
+
+        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        qobject_decref(obj);
+        QDECREF(str);
     }
 }
 END_TEST
@@ -521,6 +589,7 @@ START_TEST(simple_whitespace)
 
     for (i = 0; test_cases[i].encoded; i++) {
         QObject *obj;
+        QString *str;
 
         obj = qobject_from_json(test_cases[i].encoded);
         fail_unless(obj != NULL);
@@ -528,7 +597,17 @@ START_TEST(simple_whitespace)
 
         fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
 
+        str = qobject_to_json(obj);
         qobject_decref(obj);
+
+        obj = qobject_from_json(qstring_get_str(str));
+        fail_unless(obj != NULL);
+        fail_unless(qobject_type(obj) == QTYPE_QLIST);
+
+        fail_unless(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+
+        qobject_decref(obj);
+        QDECREF(str);
     }
 }
 END_TEST
@@ -558,11 +637,92 @@ START_TEST(simple_varargs)
 }
 END_TEST
 
+START_TEST(empty_input)
+{
+    const char *empty = "";
+
+    QObject *obj = qobject_from_json(empty);
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_string)
+{
+    QObject *obj = qobject_from_json("\"abc");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_sq_string)
+{
+    QObject *obj = qobject_from_json("'abc");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_escape)
+{
+    QObject *obj = qobject_from_json("\"abc\\\"");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_array)
+{
+    QObject *obj = qobject_from_json("[32");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_array_comma)
+{
+    QObject *obj = qobject_from_json("[32,");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(invalid_array_comma)
+{
+    QObject *obj = qobject_from_json("[32,}");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_dict)
+{
+    QObject *obj = qobject_from_json("{'abc':32");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_dict_comma)
+{
+    QObject *obj = qobject_from_json("{'abc':32,");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+#if 0
+START_TEST(invalid_dict_comma)
+{
+    QObject *obj = qobject_from_json("{'abc':32,}");
+    fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_literal)
+{
+    QObject *obj = qobject_from_json("nul");
+    fail_unless(obj == NULL);
+}
+END_TEST
+#endif
+
 static Suite *qjson_suite(void)
 {
     Suite *suite;
     TCase *string_literals, *number_literals, *keyword_literals;
-    TCase *dicts, *lists, *whitespace, *varargs;
+    TCase *dicts, *lists, *whitespace, *varargs, *errors;
 
     string_literals = tcase_create("String Literals");
     tcase_add_test(string_literals, simple_string);
@@ -588,6 +748,22 @@ static Suite *qjson_suite(void)
     varargs = tcase_create("Varargs");
     tcase_add_test(varargs, simple_varargs);
 
+    errors = tcase_create("Invalid JSON");
+    tcase_add_test(errors, empty_input);
+    tcase_add_test(errors, unterminated_string);
+    tcase_add_test(errors, unterminated_escape);
+    tcase_add_test(errors, unterminated_sq_string);
+    tcase_add_test(errors, unterminated_array);
+    tcase_add_test(errors, unterminated_array_comma);
+    tcase_add_test(errors, invalid_array_comma);
+    tcase_add_test(errors, unterminated_dict);
+    tcase_add_test(errors, unterminated_dict_comma);
+#if 0
+    /* FIXME: this print parse error messages on stderr.  */
+    tcase_add_test(errors, invalid_dict_comma);
+    tcase_add_test(errors, unterminated_literal);
+#endif
+
     suite = suite_create("QJSON test-suite");
     suite_add_tcase(suite, string_literals);
     suite_add_tcase(suite, number_literals);
@@ -596,6 +772,7 @@ static Suite *qjson_suite(void)
     suite_add_tcase(suite, lists);
     suite_add_tcase(suite, whitespace);
     suite_add_tcase(suite, varargs);
+    suite_add_tcase(suite, errors);
 
     return suite;
 }