qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 13/14] qapi: Support pretty printing in JSON outp


From: Eric Blake
Subject: [Qemu-devel] [PATCH v2 13/14] qapi: Support pretty printing in JSON output visitor
Date: Mon, 21 Dec 2015 17:31:07 -0700

Similar to pretty printing in the QObject visitor.  The rickiest
parts are the fact that during type_any(), we have to coordinate
with QObject to also print pretty; and the fact that the testsuite
now has to honor parameterization on whether pretty printing is
enabled.

Signed-off-by: Eric Blake <address@hidden>

---
v2: rebase to earlier changes
---
 include/qapi/json-output-visitor.h |   2 +-
 migration/savevm.c                 |   2 +-
 qapi/json-output-visitor.c         |  25 +++++-
 tests/test-json-output-visitor.c   | 160 ++++++++++++++++++++++++++-----------
 4 files changed, 136 insertions(+), 53 deletions(-)

diff --git a/include/qapi/json-output-visitor.h 
b/include/qapi/json-output-visitor.h
index 5be5a13..e5e16e6 100644
--- a/include/qapi/json-output-visitor.h
+++ b/include/qapi/json-output-visitor.h
@@ -15,7 +15,7 @@

 typedef struct JsonOutputVisitor JsonOutputVisitor;

-JsonOutputVisitor *json_output_visitor_new(void);
+JsonOutputVisitor *json_output_visitor_new(bool pretty);
 void json_output_visitor_cleanup(JsonOutputVisitor *v);
 void json_output_visitor_reset(JsonOutputVisitor *v);

diff --git a/migration/savevm.c b/migration/savevm.c
index a739b8b..9a05a3d 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1077,7 +1077,7 @@ void qemu_savevm_state_complete_precopy(QEMUFile *f, bool 
iterable_only)
         return;
     }

-    vmdesc_jov = json_output_visitor_new();
+    vmdesc_jov = json_output_visitor_new(false);
     vmdesc = json_output_get_visitor(vmdesc_jov);
     visit_start_struct(vmdesc, NULL, NULL, 0, &error_abort);
     tmp_i = TARGET_PAGE_SIZE;
diff --git a/qapi/json-output-visitor.c b/qapi/json-output-visitor.c
index 8183b85..0c5be38 100644
--- a/qapi/json-output-visitor.c
+++ b/qapi/json-output-visitor.c
@@ -18,6 +18,7 @@
 struct JsonOutputVisitor {
     Visitor visitor;
     QString *str;
+    bool pretty;
     bool comma;
     unsigned int depth;
 };
@@ -33,10 +34,13 @@ static void json_output_name(JsonOutputVisitor *jov, const 
char *name)
         jov->str = qstring_new();
     }
     if (jov->comma) {
-        qstring_append(jov->str, ", ");
+        qstring_append(jov->str, jov->pretty ? "," : ", ");
     } else {
         jov->comma = true;
     }
+    if (jov->pretty && jov->depth) {
+        qstring_append_format(jov->str, "\n%*s", 4 * jov->depth, "");
+    }
     if (name && jov->depth) {
         qstring_append_json_string(jov->str, name);
         qstring_append(jov->str, ": ");
@@ -59,6 +63,9 @@ static void json_output_end_struct(Visitor *v)
     JsonOutputVisitor *jov = to_jov(v);
     assert(jov->depth);
     jov->depth--;
+    if (jov->pretty) {
+        qstring_append_format(jov->str, "\n%*s", 4 * jov->depth, "");
+    }
     qstring_append(jov->str, "}");
     jov->comma = true;
 }
@@ -86,6 +93,9 @@ static void json_output_end_list(Visitor *v)
     JsonOutputVisitor *jov = to_jov(v);
     assert(jov->depth);
     jov->depth--;
+    if (jov->pretty) {
+        qstring_append_format(jov->str, "\n%*s", 4 * jov->depth, "");
+    }
     qstring_append(jov->str, "]");
     jov->comma = true;
 }
@@ -135,7 +145,15 @@ static void json_output_type_any(Visitor *v, const char 
*name, QObject **obj,
                                  Error **errp)
 {
     JsonOutputVisitor *jov = to_jov(v);
-    QString *str = qobject_to_json(*obj);
+    QString *str;
+
+    if (jov->pretty) {
+        char *prefix = g_strdup_printf("%*s", 4 * jov->depth, "");
+        str = qobject_to_json_pretty_prefix(*obj, prefix);
+        g_free(prefix);
+    } else {
+        str = qobject_to_json(*obj);
+    }
     assert(str);
     json_output_name(jov, name);
     qstring_append(jov->str, qstring_get_str(str));
@@ -179,11 +197,12 @@ void json_output_visitor_cleanup(JsonOutputVisitor *v)
     g_free(v);
 }

-JsonOutputVisitor *json_output_visitor_new(void)
+JsonOutputVisitor *json_output_visitor_new(bool pretty)
 {
     JsonOutputVisitor *v;

     v = g_malloc0(sizeof(*v));
+    v->pretty = pretty;

     v->visitor.start_struct = json_output_start_struct;
     v->visitor.end_struct = json_output_end_struct;
diff --git a/tests/test-json-output-visitor.c b/tests/test-json-output-visitor.c
index f884a03..0ddb7da 100644
--- a/tests/test-json-output-visitor.c
+++ b/tests/test-json-output-visitor.c
@@ -22,9 +22,10 @@ typedef struct TestOutputVisitorData {
 } TestOutputVisitorData;

 static void visitor_output_setup(TestOutputVisitorData *data,
-                                 const void *unused)
+                                 const void *arg)
 {
-    data->jov = json_output_visitor_new();
+    const bool *pretty = arg;
+    data->jov = json_output_visitor_new(*pretty);
     g_assert(data->jov);

     data->ov = json_output_get_visitor(data->jov);
@@ -157,8 +158,9 @@ static void test_visitor_out_struct(TestOutputVisitorData 
*data,
 }

 static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
-                                           const void *unused)
+                                           const void *arg)
 {
+    const bool *pretty = arg;
     int64_t value = 42;
     UserDefTwo *ud2;
     const char *string = "user def string";
@@ -188,27 +190,51 @@ static void 
test_visitor_out_struct_nested(TestOutputVisitorData *data,
     visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);

     out = json_output_get_string(data->jov);
-    g_assert_cmpstr(out, ==,
-                    "{"
-                     "\"string0\": \"forty two\", "
-                     "\"dict1\": {"
-                      "\"string1\": \"forty three\", "
-                      "\"dict2\": {"
-                       "\"userdef\": {"
-                        "\"integer\": 42, "
-                        "\"string\": \"user def string\""
-                        "}, "
-                       "\"string\": \"forty four\""
-                       "}, "
-                      "\"dict3\": {"
-                       "\"userdef\": {"
-                        "\"integer\": 42, "
-                        "\"string\": \"user def string\""
-                        "}, "
-                      "\"string\": \"forty five\""
-                      "}"
-                     "}"
-                    "}");
+    if (*pretty) {
+        g_assert_cmpstr(out, ==,
+                        "{\n"
+                        "    \"string0\": \"forty two\",\n"
+                        "    \"dict1\": {\n"
+                        "        \"string1\": \"forty three\",\n"
+                        "        \"dict2\": {\n"
+                        "            \"userdef\": {\n"
+                        "                \"integer\": 42,\n"
+                        "                \"string\": \"user def string\"\n"
+                        "            },\n"
+                        "            \"string\": \"forty four\"\n"
+                        "        },\n"
+                        "        \"dict3\": {\n"
+                        "            \"userdef\": {\n"
+                        "                \"integer\": 42,\n"
+                        "                \"string\": \"user def string\"\n"
+                        "            },\n"
+                        "            \"string\": \"forty five\"\n"
+                        "        }\n"
+                        "    }\n"
+                        "}");
+    } else {
+        g_assert_cmpstr(out, ==,
+                        "{"
+                         "\"string0\": \"forty two\", "
+                         "\"dict1\": {"
+                          "\"string1\": \"forty three\", "
+                          "\"dict2\": {"
+                           "\"userdef\": {"
+                            "\"integer\": 42, "
+                            "\"string\": \"user def string\""
+                            "}, "
+                           "\"string\": \"forty four\""
+                           "}, "
+                          "\"dict3\": {"
+                           "\"userdef\": {"
+                            "\"integer\": 42, "
+                            "\"string\": \"user def string\""
+                            "}, "
+                          "\"string\": \"forty five\""
+                          "}"
+                         "}"
+                        "}");
+    }
     qapi_free_UserDefTwo(ud2);
     g_free(out);
 }
@@ -287,16 +313,23 @@ static void test_visitor_out_list(TestOutputVisitorData 
*data,
 }

 static void test_visitor_out_any(TestOutputVisitorData *data,
-                                 const void *unused)
+                                 const void *arg)
 {
+    const bool *pretty = arg;
     QObject *qobj;
     QDict *qdict;
     char *out;

     qobj = QOBJECT(qint_from_int(-42));
+    visit_start_list(data->ov, NULL, NULL, 0, &error_abort);
     visit_type_any(data->ov, NULL, &qobj, &error_abort);
+    visit_end_list(data->ov);
     out = json_output_get_string(data->jov);
-    g_assert_cmpstr(out, ==, "-42");
+    if (*pretty) {
+        g_assert_cmpstr(out, ==, "[\n    -42\n]");
+    } else {
+        g_assert_cmpstr(out, ==, "[-42]");
+    }
     qobject_decref(qobj);
     g_free(out);

@@ -305,15 +338,30 @@ static void test_visitor_out_any(TestOutputVisitorData 
*data,
     qdict_put(qdict, "boolean", qbool_from_bool(true));
     qdict_put(qdict, "string", qstring_from_str("foo"));
     qobj = QOBJECT(qdict);
+    visit_start_list(data->ov, NULL, NULL, 0, &error_abort);
     visit_type_any(data->ov, NULL, &qobj, &error_abort);
+    visit_end_list(data->ov);
     qobject_decref(qobj);
     out = json_output_get_string(data->jov);
-    g_assert_cmpstr(out, ==,
-                    "{"
-                     "\"integer\": -42, "
-                     "\"boolean\": true, "
-                     "\"string\": \"foo\""
-                    "}");
+    if (*pretty) {
+        g_assert_cmpstr(out, ==,
+                        "[\n"
+                        "    {\n"
+                        "        \"integer\": -42,\n"
+                        "        \"boolean\": true,\n"
+                        "        \"string\": \"foo\"\n"
+                        "    }\n"
+                        "]");
+    } else {
+        g_assert_cmpstr(out, ==,
+                        "["
+                         "{"
+                          "\"integer\": -42, "
+                          "\"boolean\": true, "
+                          "\"string\": \"foo\""
+                         "}"
+                        "]");
+    }
     g_free(out);
 }

@@ -380,37 +428,53 @@ static void test_visitor_out_empty(TestOutputVisitorData 
*data,
     g_free(out);
 }

-static void output_visitor_test_add(const char *testpath,
+static void output_visitor_test_add(const char *testpath, bool *data,
                                     void (*test_func)(TestOutputVisitorData *,
                                                       const void *))
 {
-    g_test_add(testpath, TestOutputVisitorData, NULL, visitor_output_setup,
+    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
                test_func, visitor_output_teardown);
 }

 int main(int argc, char **argv)
 {
+    bool plain = false;
+    bool pretty = true;
+
     g_test_init(&argc, &argv, NULL);

-    output_visitor_test_add("/visitor/json/int", test_visitor_out_int);
-    output_visitor_test_add("/visitor/json/bool", test_visitor_out_bool);
-    output_visitor_test_add("/visitor/json/number", test_visitor_out_number);
-    output_visitor_test_add("/visitor/json/string", test_visitor_out_string);
-    output_visitor_test_add("/visitor/json/enum", test_visitor_out_enum);
-    output_visitor_test_add("/visitor/json/enum-errors",
+    output_visitor_test_add("/visitor/json/int", &plain,
+                            test_visitor_out_int);
+    output_visitor_test_add("/visitor/json/bool", &plain,
+                            test_visitor_out_bool);
+    output_visitor_test_add("/visitor/json/number", &plain,
+                            test_visitor_out_number);
+    output_visitor_test_add("/visitor/json/string", &plain,
+                            test_visitor_out_string);
+    output_visitor_test_add("/visitor/json/enum", &plain,
+                            test_visitor_out_enum);
+    output_visitor_test_add("/visitor/json/enum-errors", &plain,
                             test_visitor_out_enum_errors);
-    output_visitor_test_add("/visitor/json/struct", test_visitor_out_struct);
-    output_visitor_test_add("/visitor/json/struct-nested",
+    output_visitor_test_add("/visitor/json/struct", &plain,
+                            test_visitor_out_struct);
+    output_visitor_test_add("/visitor/json/struct-nested", &plain,
                             test_visitor_out_struct_nested);
-    output_visitor_test_add("/visitor/json/struct-errors",
+    output_visitor_test_add("/visitor/json-pretty/struct-nested", &pretty,
+                            test_visitor_out_struct_nested);
+    output_visitor_test_add("/visitor/json/struct-errors", &plain,
                             test_visitor_out_struct_errors);
-    output_visitor_test_add("/visitor/json/list", test_visitor_out_list);
-    output_visitor_test_add("/visitor/json/any", test_visitor_out_any);
-    output_visitor_test_add("/visitor/json/union-flat",
+    output_visitor_test_add("/visitor/json/list", &plain,
+                            test_visitor_out_list);
+    output_visitor_test_add("/visitor/json/any", &plain,
+                            test_visitor_out_any);
+    output_visitor_test_add("/visitor/json-pretty/any", &pretty,
+                            test_visitor_out_any);
+    output_visitor_test_add("/visitor/json/union-flat", &plain,
                             test_visitor_out_union_flat);
-    output_visitor_test_add("/visitor/json/alternate",
+    output_visitor_test_add("/visitor/json/alternate", &plain,
                             test_visitor_out_alternate);
-    output_visitor_test_add("/visitor/json/empty", test_visitor_out_empty);
+    output_visitor_test_add("/visitor/json/empty", &plain,
+                            test_visitor_out_empty);

     g_test_run();

-- 
2.4.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]