summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-01-01 14:33:03 +0000
committerPeter Maydell <peter.maydell@linaro.org>2021-01-01 14:33:03 +0000
commit1f7c02797fa189ce4b34382020bbce63262a5758 (patch)
tree467ab5404de2084c44df0f9d97b8524fa210c789 /tests
parent50536341b47f1e6478c42d4b4a1337b72762721b (diff)
parent4ac76ba414ecb94f086d73621775d8b38b6f0a43 (diff)
downloadfocaccia-qemu-1f7c02797fa189ce4b34382020bbce63262a5758.tar.gz
focaccia-qemu-1f7c02797fa189ce4b34382020bbce63262a5758.zip
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2020-12-19' into staging
QAPI patches patches for 2020-12-19

# gpg: Signature made Sat 19 Dec 2020 09:40:05 GMT
# gpg:                using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653
# gpg:                issuer "armbru@redhat.com"
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full]
# gpg:                 aka "Markus Armbruster <armbru@pond.sub.org>" [full]
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867  4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-qapi-2020-12-19: (33 commits)
  qobject: Make QString immutable
  block: Use GString instead of QString to build filenames
  keyval: Use GString to accumulate value strings
  json: Use GString instead of QString to accumulate strings
  migration: Replace migration's JSON writer by the general one
  qobject: Factor JSON writer out of qobject_to_json()
  qobject: Factor quoted_str() out of to_json()
  qobject: Drop qstring_get_try_str()
  qobject: Drop qobject_get_try_str()
  Revert "qobject: let object_property_get_str() use new API"
  block: Avoid qobject_get_try_str()
  qmp: Fix tracing of non-string command IDs
  qobject: Move internals to qobject-internal.h
  hw/rdma: Replace QList by GQueue
  Revert "qstring: add qstring_free()"
  qobject: Change qobject_to_json()'s value to GString
  qobject: Use GString instead of QString to accumulate JSON
  qobject: Make qobject_to_json_pretty() take a pretty argument
  monitor: Use GString instead of QString for output buffer
  hmp: Simplify how qmp_human_monitor_command() gets output
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/check-qjson.c195
-rw-r--r--tests/check-qnum.c8
-rw-r--r--tests/check-qobject.c3
-rw-r--r--tests/check-qstring.c16
-rw-r--r--tests/qtest/libqtest.c20
-rw-r--r--tests/test-clone-visitor.c7
-rw-r--r--tests/test-qobject-output-visitor.c48
-rw-r--r--tests/test-string-output-visitor.c4
-rw-r--r--tests/test-visitor-serialization.c181
9 files changed, 197 insertions, 285 deletions
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 9a02079099..c845f91d43 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -35,17 +35,15 @@ static QString *from_json_str(const char *jstr, bool single, Error **errp)
 
 static char *to_json_str(QString *str)
 {
-    QString *json = qobject_to_json(QOBJECT(str));
-    char *jstr;
+    GString *json = qobject_to_json(QOBJECT(str));
 
     if (!json) {
         return NULL;
     }
     /* peel off double quotes */
-    jstr = g_strndup(qstring_get_str(json) + 1,
-                     qstring_get_length(json) - 2);
-    qobject_unref(json);
-    return jstr;
+    g_string_truncate(json, json->len - 1);
+    g_string_erase(json, 0, 1);
+    return g_string_free(json, false);
 }
 
 static void escaped_string(void)
@@ -91,7 +89,7 @@ static void escaped_string(void)
         for (j = 0; j < 2; j++) {
             if (test_cases[i].utf8_out) {
                 cstr = from_json_str(test_cases[i].json_in, j, &error_abort);
-                g_assert_cmpstr(qstring_get_try_str(cstr),
+                g_assert_cmpstr(qstring_get_str(cstr),
                                 ==, test_cases[i].utf8_out);
                 if (!test_cases[i].skip) {
                     jstr = to_json_str(cstr);
@@ -753,7 +751,7 @@ static void utf8_string(void)
             /* Parse @json_in, expect @utf8_out */
             if (utf8_out) {
                 str = from_json_str(json_in, j, &error_abort);
-                g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_out);
+                g_assert_cmpstr(qstring_get_str(str), ==, utf8_out);
                 qobject_unref(str);
             } else {
                 str = from_json_str(json_in, j, NULL);
@@ -784,125 +782,129 @@ static void utf8_string(void)
             /* Parse @json_out right back, unless it has replacements */
             if (!strstr(json_out, "\\uFFFD")) {
                 str = from_json_str(json_out, j, &error_abort);
-                g_assert_cmpstr(qstring_get_try_str(str), ==, utf8_in);
+                g_assert_cmpstr(qstring_get_str(str), ==, utf8_in);
                 qobject_unref(str);
             }
         }
     }
 }
 
-static void simple_number(void)
+static void int_number(void)
 {
-    int i;
     struct {
         const char *encoded;
         int64_t decoded;
-        int skip;
+        const char *reencoded;
     } test_cases[] = {
         { "0", 0 },
         { "1234", 1234 },
         { "1", 1 },
         { "-32", -32 },
-        { "-0", 0, .skip = 1 },
-        { },
+        { "-0", 0, "0" },
+        {},
     };
+    int i;
+    QNum *qnum;
+    int64_t ival;
+    uint64_t uval;
+    GString *str;
 
     for (i = 0; test_cases[i].encoded; i++) {
-        QNum *qnum;
-        int64_t val;
-
         qnum = qobject_to(QNum,
                           qobject_from_json(test_cases[i].encoded,
                                             &error_abort));
         g_assert(qnum);
-        g_assert(qnum_get_try_int(qnum, &val));
-        g_assert_cmpint(val, ==, test_cases[i].decoded);
-        if (test_cases[i].skip == 0) {
-            QString *str;
-
-            str = qobject_to_json(QOBJECT(qnum));
-            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
-            qobject_unref(str);
+        g_assert(qnum_get_try_int(qnum, &ival));
+        g_assert_cmpint(ival, ==, test_cases[i].decoded);
+        if (test_cases[i].decoded >= 0) {
+            g_assert(qnum_get_try_uint(qnum, &uval));
+            g_assert_cmpuint(uval, ==, (uint64_t)test_cases[i].decoded);
+        } else {
+            g_assert(!qnum_get_try_uint(qnum, &uval));
         }
+        g_assert_cmpfloat(qnum_get_double(qnum), ==,
+                          (double)test_cases[i].decoded);
+
+        str = qobject_to_json(QOBJECT(qnum));
+        g_assert_cmpstr(str->str, ==,
+                        test_cases[i].reencoded ?: test_cases[i].encoded);
+        g_string_free(str, true);
 
         qobject_unref(qnum);
     }
 }
 
-static void large_number(void)
+static void uint_number(void)
 {
-    const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
-    const char *gtu64 = "18446744073709551616"; /* 2^64 */
-    const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
+    struct {
+        const char *encoded;
+        uint64_t decoded;
+        const char *reencoded;
+    } test_cases[] = {
+        { "9223372036854775808", (uint64_t)1 << 63 },
+        { "18446744073709551615", UINT64_MAX },
+        {},
+    };
+    int i;
     QNum *qnum;
-    QString *str;
-    uint64_t val;
     int64_t ival;
+    uint64_t uval;
+    GString *str;
 
-    qnum = qobject_to(QNum, qobject_from_json(maxu64, &error_abort));
-    g_assert(qnum);
-    g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
-    g_assert(!qnum_get_try_int(qnum, &ival));
-
-    str = qobject_to_json(QOBJECT(qnum));
-    g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
-    qobject_unref(str);
-    qobject_unref(qnum);
-
-    qnum = qobject_to(QNum, qobject_from_json(gtu64, &error_abort));
-    g_assert(qnum);
-    g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
-    g_assert(!qnum_get_try_uint(qnum, &val));
-    g_assert(!qnum_get_try_int(qnum, &ival));
-
-    str = qobject_to_json(QOBJECT(qnum));
-    g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
-    qobject_unref(str);
-    qobject_unref(qnum);
+    for (i = 0; test_cases[i].encoded; i++) {
+        qnum = qobject_to(QNum,
+                          qobject_from_json(test_cases[i].encoded,
+                                            &error_abort));
+        g_assert(qnum);
+        g_assert(qnum_get_try_uint(qnum, &uval));
+        g_assert_cmpuint(uval, ==, test_cases[i].decoded);
+        g_assert(!qnum_get_try_int(qnum, &ival));
+        g_assert_cmpfloat(qnum_get_double(qnum), ==,
+                          (double)test_cases[i].decoded);
 
-    qnum = qobject_to(QNum, qobject_from_json(lti64, &error_abort));
-    g_assert(qnum);
-    g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
-    g_assert(!qnum_get_try_uint(qnum, &val));
-    g_assert(!qnum_get_try_int(qnum, &ival));
+        str = qobject_to_json(QOBJECT(qnum));
+        g_assert_cmpstr(str->str, ==,
+                        test_cases[i].reencoded ?: test_cases[i].encoded);
+        g_string_free(str, true);
 
-    str = qobject_to_json(QOBJECT(qnum));
-    g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
-    qobject_unref(str);
-    qobject_unref(qnum);
+        qobject_unref(qnum);
+    }
 }
 
 static void float_number(void)
 {
-    int i;
     struct {
         const char *encoded;
         double decoded;
-        int skip;
+        const char *reencoded;
     } test_cases[] = {
         { "32.43", 32.43 },
         { "0.222", 0.222 },
-        { "-32.12313", -32.12313 },
-        { "-32.20e-10", -32.20e-10, .skip = 1 },
-        { },
+        { "-32.12313", -32.12313, "-32.123130000000003" },
+        { "-32.20e-10", -32.20e-10, "-3.22e-09" },
+        { "18446744073709551616", 0x1p64, "1.8446744073709552e+19" },
+        { "-9223372036854775809", -0x1p63, "-9.2233720368547758e+18" },
+        {},
     };
+    int i;
+    QNum *qnum;
+    int64_t ival;
+    uint64_t uval;
+    GString *str;
 
     for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QNum *qnum;
-
-        obj = qobject_from_json(test_cases[i].encoded, &error_abort);
-        qnum = qobject_to(QNum, obj);
+        qnum = qobject_to(QNum,
+                          qobject_from_json(test_cases[i].encoded,
+                                            &error_abort));
         g_assert(qnum);
-        g_assert(qnum_get_double(qnum) == test_cases[i].decoded);
+        g_assert_cmpfloat(qnum_get_double(qnum), ==, test_cases[i].decoded);
+        g_assert(!qnum_get_try_int(qnum, &ival));
+        g_assert(!qnum_get_try_uint(qnum, &uval));
 
-        if (test_cases[i].skip == 0) {
-            QString *str;
-
-            str = qobject_to_json(obj);
-            g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
-            qobject_unref(str);
-        }
+        str = qobject_to_json(QOBJECT(qnum));
+        g_assert_cmpstr(str->str, ==,
+                        test_cases[i].reencoded ?: test_cases[i].encoded);
+        g_string_free(str, true);
 
         qobject_unref(qnum);
     }
@@ -913,7 +915,7 @@ static void keyword_literal(void)
     QObject *obj;
     QBool *qbool;
     QNull *null;
-    QString *str;
+    GString *str;
 
     obj = qobject_from_json("true", &error_abort);
     qbool = qobject_to(QBool, obj);
@@ -921,8 +923,8 @@ static void keyword_literal(void)
     g_assert(qbool_get_bool(qbool) == true);
 
     str = qobject_to_json(obj);
-    g_assert(strcmp(qstring_get_str(str), "true") == 0);
-    qobject_unref(str);
+    g_assert_cmpstr(str->str, ==, "true");
+    g_string_free(str, true);
 
     qobject_unref(qbool);
 
@@ -932,8 +934,8 @@ static void keyword_literal(void)
     g_assert(qbool_get_bool(qbool) == false);
 
     str = qobject_to_json(obj);
-    g_assert(strcmp(qstring_get_str(str), "false") == 0);
-    qobject_unref(str);
+    g_assert_cmpstr(str->str, ==, "false");
+    g_string_free(str, true);
 
     qobject_unref(qbool);
 
@@ -1019,9 +1021,8 @@ static void interpolation_valid(void)
 
     /* string */
 
-    qstr = qobject_to(QString,
-                     qobject_from_jsonf_nofail("%s", value_s));
-    g_assert_cmpstr(qstring_get_try_str(qstr), ==, value_s);
+    qstr = qobject_to(QString, qobject_from_jsonf_nofail("%s", value_s));
+    g_assert_cmpstr(qstring_get_str(qstr), ==, value_s);
     qobject_unref(qstr);
 
     /* object */
@@ -1083,7 +1084,7 @@ static void simple_dict(void)
 
     for (i = 0; test_cases[i].encoded; i++) {
         QObject *obj;
-        QString *str;
+        GString *str;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
@@ -1091,10 +1092,10 @@ static void simple_dict(void)
         str = qobject_to_json(obj);
         qobject_unref(obj);
 
-        obj = qobject_from_json(qstring_get_str(str), &error_abort);
+        obj = qobject_from_json(str->str, &error_abort);
         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
         qobject_unref(obj);
-        qobject_unref(str);
+        g_string_free(str, true);
     }
 }
 
@@ -1192,7 +1193,7 @@ static void simple_list(void)
 
     for (i = 0; test_cases[i].encoded; i++) {
         QObject *obj;
-        QString *str;
+        GString *str;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
@@ -1200,10 +1201,10 @@ static void simple_list(void)
         str = qobject_to_json(obj);
         qobject_unref(obj);
 
-        obj = qobject_from_json(qstring_get_str(str), &error_abort);
+        obj = qobject_from_json(str->str, &error_abort);
         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
         qobject_unref(obj);
-        qobject_unref(str);
+        g_string_free(str, true);
     }
 }
 
@@ -1254,7 +1255,7 @@ static void simple_whitespace(void)
 
     for (i = 0; test_cases[i].encoded; i++) {
         QObject *obj;
-        QString *str;
+        GString *str;
 
         obj = qobject_from_json(test_cases[i].encoded, &error_abort);
         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
@@ -1262,11 +1263,11 @@ static void simple_whitespace(void)
         str = qobject_to_json(obj);
         qobject_unref(obj);
 
-        obj = qobject_from_json(qstring_get_str(str), &error_abort);
+        obj = qobject_from_json(str->str, &error_abort);
         g_assert(qlit_equal_qobject(&test_cases[i].decoded, obj));
 
         qobject_unref(obj);
-        qobject_unref(str);
+        g_string_free(str, true);
     }
 }
 
@@ -1479,8 +1480,8 @@ int main(int argc, char **argv)
     g_test_add_func("/literals/string/quotes", string_with_quotes);
     g_test_add_func("/literals/string/utf8", utf8_string);
 
-    g_test_add_func("/literals/number/simple", simple_number);
-    g_test_add_func("/literals/number/large", large_number);
+    g_test_add_func("/literals/number/int", int_number);
+    g_test_add_func("/literals/number/uint", uint_number);
     g_test_add_func("/literals/number/float", float_number);
 
     g_test_add_func("/literals/keyword", keyword_literal);
diff --git a/tests/check-qnum.c b/tests/check-qnum.c
index 4105015872..b85fca2302 100644
--- a/tests/check-qnum.c
+++ b/tests/check-qnum.c
@@ -147,7 +147,13 @@ static void qnum_to_string_test(void)
 
     qn = qnum_from_double(0.42);
     tmp = qnum_to_string(qn);
-    g_assert_cmpstr(tmp, ==, "0.42");
+    g_assert_cmpstr(tmp, ==, "0.41999999999999998");
+    g_free(tmp);
+    qobject_unref(qn);
+
+    qn = qnum_from_double(2.718281828459045);
+    tmp = qnum_to_string(qn);
+    g_assert_cmpstr(tmp, ==, "2.7182818284590451");
     g_free(tmp);
     qobject_unref(qn);
 }
diff --git a/tests/check-qobject.c b/tests/check-qobject.c
index 6b6deaeb8b..c1713d15af 100644
--- a/tests/check-qobject.c
+++ b/tests/check-qobject.c
@@ -155,8 +155,7 @@ static void qobject_is_equal_string_test(void)
     str_case = qstring_from_str("Foo");
 
     /* Should yield "foo" */
-    str_built = qstring_from_substr("form", 0, 2);
-    qstring_append_chr(str_built, 'o');
+    str_built = qstring_from_substr("buffoon", 3, 6);
 
     check_unequal(str_base, str_whitespace_0, str_whitespace_1,
                   str_whitespace_2, str_whitespace_3, str_case);
diff --git a/tests/check-qstring.c b/tests/check-qstring.c
index 2d079921e3..4bf9772093 100644
--- a/tests/check-qstring.c
+++ b/tests/check-qstring.c
@@ -47,21 +47,6 @@ static void qstring_get_str_test(void)
     qobject_unref(qstring);
 }
 
-static void qstring_append_chr_test(void)
-{
-    int i;
-    QString *qstring;
-    const char *str = "qstring append char unit-test";
-
-    qstring = qstring_new();
-
-    for (i = 0; str[i]; i++)
-        qstring_append_chr(qstring, str[i]);
-
-    g_assert(strcmp(str, qstring_get_str(qstring)) == 0);
-    qobject_unref(qstring);
-}
-
 static void qstring_from_substr_test(void)
 {
     QString *qs;
@@ -90,7 +75,6 @@ int main(int argc, char **argv)
 
     g_test_add_func("/public/from_str", qstring_from_str_test);
     g_test_add_func("/public/get_str", qstring_get_str_test);
-    g_test_add_func("/public/append_chr", qstring_append_chr_test);
     g_test_add_func("/public/from_substr", qstring_from_substr_test);
     g_test_add_func("/public/to_qstring", qobject_to_qstring_test);
 
diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c
index e49f3a1e45..8e93b0a707 100644
--- a/tests/qtest/libqtest.c
+++ b/tests/qtest/libqtest.c
@@ -652,27 +652,25 @@ void qmp_fd_vsend_fds(int fd, int *fds, size_t fds_num,
     /* No need to send anything for an empty QObject.  */
     if (qobj) {
         int log = getenv("QTEST_LOG") != NULL;
-        QString *qstr = qobject_to_json(qobj);
-        const char *str;
+        GString *str = qobject_to_json(qobj);
 
         /*
          * BUG: QMP doesn't react to input until it sees a newline, an
          * object, or an array.  Work-around: give it a newline.
          */
-        qstring_append_chr(qstr, '\n');
-        str = qstring_get_str(qstr);
+        g_string_append_c(str, '\n');
 
         if (log) {
-            fprintf(stderr, "%s", str);
+            fprintf(stderr, "%s", str->str);
         }
         /* Send QMP request */
         if (fds && fds_num > 0) {
-            socket_send_fds(fd, fds, fds_num, str, qstring_get_length(qstr));
+            socket_send_fds(fd, fds, fds_num, str->str, str->len);
         } else {
-            socket_send(fd, str, qstring_get_length(qstr));
+            socket_send(fd, str->str, str->len);
         }
 
-        qobject_unref(qstr);
+        g_string_free(str, true);
         qobject_unref(qobj);
     }
 }
@@ -1197,9 +1195,9 @@ void qtest_qmp_assert_success(QTestState *qts, const char *fmt, ...)
 
     g_assert(response);
     if (!qdict_haskey(response, "return")) {
-        QString *s = qobject_to_json_pretty(QOBJECT(response));
-        g_test_message("%s", qstring_get_str(s));
-        qobject_unref(s);
+        GString *s = qobject_to_json_pretty(QOBJECT(response), true);
+        g_test_message("%s", s->str);
+        g_string_free(s, true);
     }
     g_assert(qdict_haskey(response, "return"));
     qobject_unref(response);
diff --git a/tests/test-clone-visitor.c b/tests/test-clone-visitor.c
index 5e1e8b2f5e..4944b3d857 100644
--- a/tests/test-clone-visitor.c
+++ b/tests/test-clone-visitor.c
@@ -65,16 +65,13 @@ static void test_clone_alternate(void)
 
 static void test_clone_list_union(void)
 {
-    uint8List *src, *dst;
+    uint8List *src = NULL, *dst;
     uint8List *tmp = NULL;
     int i;
 
     /* Build list in reverse */
     for (i = 10; i; i--) {
-        src = g_new0(uint8List, 1);
-        src->next = tmp;
-        src->value = i;
-        tmp = src;
+        QAPI_LIST_PREPEND(src, i);
     }
 
     dst = QAPI_CLONE(uint8List, src);
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index 1c856d9bd2..b20ab8b29b 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -223,7 +223,8 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
                                   const void *unused)
 {
     const char *value_str = "list value";
-    TestStructList *p, *head = NULL;
+    TestStruct *value;
+    TestStructList *head = NULL;
     const int max_items = 10;
     bool value_bool = true;
     int value_int = 10;
@@ -233,14 +234,12 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
 
     /* Build the list in reverse order... */
     for (i = 0; i < max_items; i++) {
-        p = g_malloc0(sizeof(*p));
-        p->value = g_malloc0(sizeof(*p->value));
-        p->value->integer = value_int + (max_items - i - 1);
-        p->value->boolean = value_bool;
-        p->value->string = g_strdup(value_str);
-
-        p->next = head;
-        head = p;
+        value = g_malloc0(sizeof(*value));
+        value->integer = value_int + (max_items - i - 1);
+        value->boolean = value_bool;
+        value->string = g_strdup(value_str);
+
+        QAPI_LIST_PREPEND(head, value);
     }
 
     visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
@@ -270,26 +269,25 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
 static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
                                             const void *unused)
 {
-    UserDefTwoList *p, *head = NULL;
+    UserDefTwo *value;
+    UserDefTwoList *head = NULL;
     const char string[] = "foo bar";
     int i, max_count = 1024;
 
     for (i = 0; i < max_count; i++) {
-        p = g_malloc0(sizeof(*p));
-        p->value = g_malloc0(sizeof(*p->value));
-
-        p->value->string0 = g_strdup(string);
-        p->value->dict1 = g_new0(UserDefTwoDict, 1);
-        p->value->dict1->string1 = g_strdup(string);
-        p->value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
-        p->value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
-        p->value->dict1->dict2->userdef->string = g_strdup(string);
-        p->value->dict1->dict2->userdef->integer = 42;
-        p->value->dict1->dict2->string = g_strdup(string);
-        p->value->dict1->has_dict3 = false;
-
-        p->next = head;
-        head = p;
+        value = g_malloc0(sizeof(*value));
+
+        value->string0 = g_strdup(string);
+        value->dict1 = g_new0(UserDefTwoDict, 1);
+        value->dict1->string1 = g_strdup(string);
+        value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
+        value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
+        value->dict1->dict2->userdef->string = g_strdup(string);
+        value->dict1->dict2->userdef->integer = 42;
+        value->dict1->dict2->string = g_strdup(string);
+        value->dict1->has_dict3 = false;
+
+        QAPI_LIST_PREPEND(head, value);
     }
 
     qapi_free_UserDefTwoList(head);
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 9f6581439a..0dae04b960 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -130,13 +130,13 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
 static void test_visitor_out_number(TestOutputVisitorData *data,
                                     const void *unused)
 {
-    double value = 3.14;
+    double value = 3.1415926535897932;
     char *str;
 
     visit_type_number(data->ov, NULL, &value, &error_abort);
 
     str = visitor_get(data);
-    g_assert_cmpstr(str, ==, "3.140000");
+    g_assert_cmpstr(str, ==, "3.1415926535897931");
 }
 
 static void test_visitor_out_string(TestOutputVisitorData *data,
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index 1c5a8b94ea..4629958647 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -55,7 +55,6 @@ typedef struct PrimitiveType {
         int16_t s16;
         int32_t s32;
         int64_t s64;
-        intmax_t max;
     } value;
     enum PrimitiveTypeKind type;
     const char *description;
@@ -307,25 +306,46 @@ static void test_primitives(gconstpointer opaque)
                      &error_abort);
 
     g_assert(pt_copy != NULL);
-    if (pt->type == PTYPE_STRING) {
+    switch (pt->type) {
+    case PTYPE_STRING:
         g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
         g_free((char *)pt_copy->value.string);
-    } else if (pt->type == PTYPE_NUMBER) {
-        GString *double_expected = g_string_new("");
-        GString *double_actual = g_string_new("");
-        /* we serialize with %f for our reference visitors, so rather than fuzzy
-         * floating math to test "equality", just compare the formatted values
-         */
-        g_string_printf(double_expected, "%.6f", pt->value.number);
-        g_string_printf(double_actual, "%.6f", pt_copy->value.number);
-        g_assert_cmpstr(double_actual->str, ==, double_expected->str);
-
-        g_string_free(double_expected, true);
-        g_string_free(double_actual, true);
-    } else if (pt->type == PTYPE_BOOLEAN) {
-        g_assert_cmpint(!!pt->value.max, ==, !!pt->value.max);
-    } else {
-        g_assert_cmpint(pt->value.max, ==, pt_copy->value.max);
+        break;
+    case PTYPE_BOOLEAN:
+        g_assert_cmpint(pt->value.boolean, ==, pt->value.boolean);
+        break;
+    case PTYPE_NUMBER:
+        g_assert_cmpfloat(pt->value.number, ==, pt_copy->value.number);
+        break;
+    case PTYPE_INTEGER:
+        g_assert_cmpint(pt->value.integer, ==, pt_copy->value.integer);
+        break;
+    case PTYPE_U8:
+        g_assert_cmpuint(pt->value.u8, ==, pt_copy->value.u8);
+        break;
+    case PTYPE_U16:
+        g_assert_cmpuint(pt->value.u16, ==, pt_copy->value.u16);
+        break;
+    case PTYPE_U32:
+        g_assert_cmpuint(pt->value.u32, ==, pt_copy->value.u32);
+        break;
+    case PTYPE_U64:
+        g_assert_cmpuint(pt->value.u64, ==, pt_copy->value.u64);
+        break;
+    case PTYPE_S8:
+        g_assert_cmpint(pt->value.s8, ==, pt_copy->value.s8);
+        break;
+    case PTYPE_S16:
+        g_assert_cmpint(pt->value.s16, ==, pt_copy->value.s16);
+        break;
+    case PTYPE_S32:
+        g_assert_cmpint(pt->value.s32, ==, pt_copy->value.s32);
+        break;
+    case PTYPE_S64:
+        g_assert_cmpint(pt->value.s64, ==, pt_copy->value.s64);
+        break;
+    case PTYPE_EOL:
+        g_assert_not_reached();
     }
 
     ops->cleanup(serialize_data);
@@ -351,135 +371,51 @@ static void test_primitive_lists(gconstpointer opaque)
     for (i = 0; i < 32; i++) {
         switch (pl.type) {
         case PTYPE_STRING: {
-            strList *tmp = g_new0(strList, 1);
-            tmp->value = g_strdup(pt->value.string);
-            if (pl.value.strings == NULL) {
-                pl.value.strings = tmp;
-            } else {
-                tmp->next = pl.value.strings;
-                pl.value.strings = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.strings, g_strdup(pt->value.string));
             break;
         }
         case PTYPE_INTEGER: {
-            intList *tmp = g_new0(intList, 1);
-            tmp->value = pt->value.integer;
-            if (pl.value.integers == NULL) {
-                pl.value.integers = tmp;
-            } else {
-                tmp->next = pl.value.integers;
-                pl.value.integers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.integers, pt->value.integer);
             break;
         }
         case PTYPE_S8: {
-            int8List *tmp = g_new0(int8List, 1);
-            tmp->value = pt->value.s8;
-            if (pl.value.s8_integers == NULL) {
-                pl.value.s8_integers = tmp;
-            } else {
-                tmp->next = pl.value.s8_integers;
-                pl.value.s8_integers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.s8_integers, pt->value.s8);
             break;
         }
         case PTYPE_S16: {
-            int16List *tmp = g_new0(int16List, 1);
-            tmp->value = pt->value.s16;
-            if (pl.value.s16_integers == NULL) {
-                pl.value.s16_integers = tmp;
-            } else {
-                tmp->next = pl.value.s16_integers;
-                pl.value.s16_integers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.s16_integers, pt->value.s16);
             break;
         }
         case PTYPE_S32: {
-            int32List *tmp = g_new0(int32List, 1);
-            tmp->value = pt->value.s32;
-            if (pl.value.s32_integers == NULL) {
-                pl.value.s32_integers = tmp;
-            } else {
-                tmp->next = pl.value.s32_integers;
-                pl.value.s32_integers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.s32_integers, pt->value.s32);
             break;
         }
         case PTYPE_S64: {
-            int64List *tmp = g_new0(int64List, 1);
-            tmp->value = pt->value.s64;
-            if (pl.value.s64_integers == NULL) {
-                pl.value.s64_integers = tmp;
-            } else {
-                tmp->next = pl.value.s64_integers;
-                pl.value.s64_integers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.s64_integers, pt->value.s64);
             break;
         }
         case PTYPE_U8: {
-            uint8List *tmp = g_new0(uint8List, 1);
-            tmp->value = pt->value.u8;
-            if (pl.value.u8_integers == NULL) {
-                pl.value.u8_integers = tmp;
-            } else {
-                tmp->next = pl.value.u8_integers;
-                pl.value.u8_integers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.u8_integers, pt->value.u8);
             break;
         }
         case PTYPE_U16: {
-            uint16List *tmp = g_new0(uint16List, 1);
-            tmp->value = pt->value.u16;
-            if (pl.value.u16_integers == NULL) {
-                pl.value.u16_integers = tmp;
-            } else {
-                tmp->next = pl.value.u16_integers;
-                pl.value.u16_integers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.u16_integers, pt->value.u16);
             break;
         }
         case PTYPE_U32: {
-            uint32List *tmp = g_new0(uint32List, 1);
-            tmp->value = pt->value.u32;
-            if (pl.value.u32_integers == NULL) {
-                pl.value.u32_integers = tmp;
-            } else {
-                tmp->next = pl.value.u32_integers;
-                pl.value.u32_integers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.u32_integers, pt->value.u32);
             break;
         }
         case PTYPE_U64: {
-            uint64List *tmp = g_new0(uint64List, 1);
-            tmp->value = pt->value.u64;
-            if (pl.value.u64_integers == NULL) {
-                pl.value.u64_integers = tmp;
-            } else {
-                tmp->next = pl.value.u64_integers;
-                pl.value.u64_integers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.u64_integers, pt->value.u64);
             break;
         }
         case PTYPE_NUMBER: {
-            numberList *tmp = g_new0(numberList, 1);
-            tmp->value = pt->value.number;
-            if (pl.value.numbers == NULL) {
-                pl.value.numbers = tmp;
-            } else {
-                tmp->next = pl.value.numbers;
-                pl.value.numbers = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.numbers, pt->value.number);
             break;
         }
         case PTYPE_BOOLEAN: {
-            boolList *tmp = g_new0(boolList, 1);
-            tmp->value = pt->value.boolean;
-            if (pl.value.booleans == NULL) {
-                pl.value.booleans = tmp;
-            } else {
-                tmp->next = pl.value.booleans;
-                pl.value.booleans = tmp;
-            }
+            QAPI_LIST_PREPEND(pl.value.booleans, pt->value.boolean);
             break;
         }
         default:
@@ -704,10 +640,7 @@ static void test_nested_struct_list(gconstpointer opaque)
     int i = 0;
 
     for (i = 0; i < 8; i++) {
-        tmp = g_new0(UserDefTwoList, 1);
-        tmp->value = nested_struct_create();
-        tmp->next = listp;
-        listp = tmp;
+        QAPI_LIST_PREPEND(listp, nested_struct_create());
     }
 
     ops->serialize(listp, &serialize_data, visit_nested_struct_list,
@@ -790,10 +723,6 @@ static PrimitiveType pt_values[] = {
         .value.boolean = 0,
     },
     /* number tests (double) */
-    /* note: we format these to %.6f before comparing, since that's how
-     * we serialize them and it doesn't make sense to check precision
-     * beyond that.
-     */
     {
         .description = "number_sanity1",
         .type = PTYPE_NUMBER,
@@ -802,7 +731,7 @@ static PrimitiveType pt_values[] = {
     {
         .description = "number_sanity2",
         .type = PTYPE_NUMBER,
-        .value.number = 3.14159265,
+        .value.number = 3.141593,
     },
     {
         .description = "number_min",
@@ -1028,15 +957,15 @@ static void qmp_deserialize(void **native_out, void *datap,
                             VisitorFunc visit, Error **errp)
 {
     QmpSerializeData *d = datap;
-    QString *output_json;
+    GString *output_json;
     QObject *obj_orig, *obj;
 
     visit_complete(d->qov, &d->obj);
     obj_orig = d->obj;
     output_json = qobject_to_json(obj_orig);
-    obj = qobject_from_json(qstring_get_str(output_json), &error_abort);
+    obj = qobject_from_json(output_json->str, &error_abort);
 
-    qobject_unref(output_json);
+    g_string_free(output_json, true);
     d->qiv = qobject_input_visitor_new(obj);
     qobject_unref(obj_orig);
     qobject_unref(obj);