]> xenbits.xensource.com Git - qemu-upstream-4.5-testing.git/commitdiff
test makefile overhaul
authorPaolo Bonzini <pbonzini@redhat.com>
Wed, 28 Mar 2012 13:42:01 +0000 (15:42 +0200)
committerAnthony Liguori <aliguori@us.ibm.com>
Fri, 30 Mar 2012 13:14:11 +0000 (08:14 -0500)
This introduces new test reporting infrastructure based on
gtester and gtester-report.

Also, all existing tests are moved to tests/, and tests/Makefile
is reorganized to factor out the commonalities in the rules.

Signed-off-by: Anthony Liguori <aliguori@linux.vnet.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
29 files changed:
check-qdict.c [deleted file]
check-qfloat.c [deleted file]
check-qint.c [deleted file]
check-qjson.c [deleted file]
check-qlist.c [deleted file]
check-qstring.c [deleted file]
rules.mak
scripts/gtester-cat [new file with mode: 0755]
test-coroutine.c [deleted file]
test-qmp-commands.c [deleted file]
test-qmp-input-strict.c [deleted file]
test-qmp-input-visitor.c [deleted file]
test-qmp-output-visitor.c [deleted file]
test-string-input-visitor.c [deleted file]
test-string-output-visitor.c [deleted file]
tests/Makefile
tests/check-qdict.c [new file with mode: 0644]
tests/check-qfloat.c [new file with mode: 0644]
tests/check-qint.c [new file with mode: 0644]
tests/check-qjson.c [new file with mode: 0644]
tests/check-qlist.c [new file with mode: 0644]
tests/check-qstring.c [new file with mode: 0644]
tests/test-coroutine.c [new file with mode: 0644]
tests/test-qmp-commands.c [new file with mode: 0644]
tests/test-qmp-input-strict.c [new file with mode: 0644]
tests/test-qmp-input-visitor.c [new file with mode: 0644]
tests/test-qmp-output-visitor.c [new file with mode: 0644]
tests/test-string-input-visitor.c [new file with mode: 0644]
tests/test-string-output-visitor.c [new file with mode: 0644]

diff --git a/check-qdict.c b/check-qdict.c
deleted file mode 100644 (file)
index fc0d276..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * QDict unit-tests.
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#include <glib.h>
-
-#include "qint.h"
-#include "qdict.h"
-#include "qstring.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qdict_new_test(void)
-{
-    QDict *qdict;
-
-    qdict = qdict_new();
-    g_assert(qdict != NULL);
-    g_assert(qdict_size(qdict) == 0);
-    g_assert(qdict->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
-
-    // destroy doesn't exit yet
-    g_free(qdict);
-}
-
-static void qdict_put_obj_test(void)
-{
-    QInt *qi;
-    QDict *qdict;
-    QDictEntry *ent;
-    const int num = 42;
-
-    qdict = qdict_new();
-
-    // key "" will have tdb hash 12345
-    qdict_put_obj(qdict, "", QOBJECT(qint_from_int(num)));
-
-    g_assert(qdict_size(qdict) == 1);
-    ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
-    qi = qobject_to_qint(ent->value);
-    g_assert(qint_get_int(qi) == num);
-
-    // destroy doesn't exit yet
-    QDECREF(qi);
-    g_free(ent->key);
-    g_free(ent);
-    g_free(qdict);
-}
-
-static void qdict_destroy_simple_test(void)
-{
-    QDict *qdict;
-
-    qdict = qdict_new();
-    qdict_put_obj(qdict, "num", QOBJECT(qint_from_int(0)));
-    qdict_put_obj(qdict, "str", QOBJECT(qstring_from_str("foo")));
-
-    QDECREF(qdict);
-}
-
-static void qdict_get_test(void)
-{
-    QInt *qi;
-    QObject *obj;
-    const int value = -42;
-    const char *key = "test";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(value));
-
-    obj = qdict_get(tests_dict, key);
-    g_assert(obj != NULL);
-
-    qi = qobject_to_qint(obj);
-    g_assert(qint_get_int(qi) == value);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_int_test(void)
-{
-    int ret;
-    const int value = 100;
-    const char *key = "int";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(value));
-
-    ret = qdict_get_int(tests_dict, key);
-    g_assert(ret == value);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_try_int_test(void)
-{
-    int ret;
-    const int value = 100;
-    const char *key = "int";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(value));
-
-    ret = qdict_get_try_int(tests_dict, key, 0);
-    g_assert(ret == value);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_str_test(void)
-{
-    const char *p;
-    const char *key = "key";
-    const char *str = "string";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qstring_from_str(str));
-
-    p = qdict_get_str(tests_dict, key);
-    g_assert(p != NULL);
-    g_assert(strcmp(p, str) == 0);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_try_str_test(void)
-{
-    const char *p;
-    const char *key = "key";
-    const char *str = "string";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qstring_from_str(str));
-
-    p = qdict_get_try_str(tests_dict, key);
-    g_assert(p != NULL);
-    g_assert(strcmp(p, str) == 0);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_haskey_not_test(void)
-{
-    QDict *tests_dict = qdict_new();
-    g_assert(qdict_haskey(tests_dict, "test") == 0);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_haskey_test(void)
-{
-    const char *key = "test";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(0));
-    g_assert(qdict_haskey(tests_dict, key) == 1);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_del_test(void)
-{
-    const char *key = "key test";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qstring_from_str("foo"));
-    g_assert(qdict_size(tests_dict) == 1);
-
-    qdict_del(tests_dict, key);
-
-    g_assert(qdict_size(tests_dict) == 0);
-    g_assert(qdict_haskey(tests_dict, key) == 0);
-
-    QDECREF(tests_dict);
-}
-
-static void qobject_to_qdict_test(void)
-{
-    QDict *tests_dict = qdict_new();
-    g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_iterapi_test(void)
-{
-    int count;
-    const QDictEntry *ent;
-    QDict *tests_dict = qdict_new();
-
-    g_assert(qdict_first(tests_dict) == NULL);
-
-    qdict_put(tests_dict, "key1", qint_from_int(1));
-    qdict_put(tests_dict, "key2", qint_from_int(2));
-    qdict_put(tests_dict, "key3", qint_from_int(3));
-
-    count = 0;
-    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
-        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
-        count++;
-    }
-
-    g_assert(count == qdict_size(tests_dict));
-
-    /* Do it again to test restarting */
-    count = 0;
-    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
-        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
-        count++;
-    }
-
-    g_assert(count == qdict_size(tests_dict));
-
-    QDECREF(tests_dict);
-}
-
-/*
- * Errors test-cases
- */
-
-static void qdict_put_exists_test(void)
-{
-    int value;
-    const char *key = "exists";
-    QDict *tests_dict = qdict_new();
-
-    qdict_put(tests_dict, key, qint_from_int(1));
-    qdict_put(tests_dict, key, qint_from_int(2));
-
-    value = qdict_get_int(tests_dict, key);
-    g_assert(value == 2);
-
-    g_assert(qdict_size(tests_dict) == 1);
-
-    QDECREF(tests_dict);
-}
-
-static void qdict_get_not_exists_test(void)
-{
-    QDict *tests_dict = qdict_new();
-    g_assert(qdict_get(tests_dict, "foo") == NULL);
-
-    QDECREF(tests_dict);
-}
-
-/*
- * Stress test-case
- *
- * This is a lot big for a unit-test, but there is no other place
- * to have it.
- */
-
-static void remove_dots(char *string)
-{
-    char *p = strchr(string, ':');
-    if (p)
-        *p = '\0';
-}
-
-static QString *read_line(FILE *file, char *key)
-{
-    char value[128];
-
-    if (fscanf(file, "%127s%127s", key, value) == EOF) {
-        return NULL;
-    }
-    remove_dots(key);
-    return qstring_from_str(value);
-}
-
-#define reset_file(file)    fseek(file, 0L, SEEK_SET)
-
-static void qdict_stress_test(void)
-{
-    size_t lines;
-    char key[128];
-    FILE *test_file;
-    QDict *qdict;
-    QString *value;
-    const char *test_file_path = "qdict-test-data.txt";
-
-    test_file = fopen(test_file_path, "r");
-    g_assert(test_file != NULL);
-
-    // Create the dict
-    qdict = qdict_new();
-    g_assert(qdict != NULL);
-
-    // Add everything from the test file
-    for (lines = 0;; lines++) {
-        value = read_line(test_file, key);
-        if (!value)
-            break;
-
-        qdict_put(qdict, key, value);
-    }
-    g_assert(qdict_size(qdict) == lines);
-
-    // Check if everything is really in there
-    reset_file(test_file);
-    for (;;) {
-        const char *str1, *str2;
-
-        value = read_line(test_file, key);
-        if (!value)
-            break;
-
-        str1 = qstring_get_str(value);
-
-        str2 = qdict_get_str(qdict, key);
-        g_assert(str2 != NULL);
-
-        g_assert(strcmp(str1, str2) == 0);
-
-        QDECREF(value);
-    }
-
-    // Delete everything
-    reset_file(test_file);
-    for (;;) {
-        value = read_line(test_file, key);
-        if (!value)
-            break;
-
-        qdict_del(qdict, key);
-        QDECREF(value);
-
-        g_assert(qdict_haskey(qdict, key) == 0);
-    }
-    fclose(test_file);
-
-    g_assert(qdict_size(qdict) == 0);
-    QDECREF(qdict);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/new", qdict_new_test);
-    g_test_add_func("/public/put_obj", qdict_put_obj_test);
-    g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
-
-    /* Continue, but now with fixtures */
-    g_test_add_func("/public/get", qdict_get_test);
-    g_test_add_func("/public/get_int", qdict_get_int_test);
-    g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
-    g_test_add_func("/public/get_str", qdict_get_str_test);
-    g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
-    g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
-    g_test_add_func("/public/haskey", qdict_haskey_test);
-    g_test_add_func("/public/del", qdict_del_test);
-    g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
-    g_test_add_func("/public/iterapi", qdict_iterapi_test);
-
-    g_test_add_func("/errors/put_exists", qdict_put_exists_test);
-    g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
-
-    /* The Big one */
-    if (g_test_slow()) {
-        g_test_add_func("/stress/test", qdict_stress_test);
-    }
-
-    return g_test_run();
-}
diff --git a/check-qfloat.c b/check-qfloat.c
deleted file mode 100644 (file)
index cdc66ea..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * QFloat unit-tests.
- *
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-#include <glib.h>
-
-#include "qfloat.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qfloat_from_double_test(void)
-{
-    QFloat *qf;
-    const double value = -42.23423;
-
-    qf = qfloat_from_double(value);
-    g_assert(qf != NULL);
-    g_assert(qf->value == value);
-    g_assert(qf->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
-
-    // destroy doesn't exit yet
-    g_free(qf);
-}
-
-static void qfloat_destroy_test(void)
-{
-    QFloat *qf = qfloat_from_double(0.0);
-    QDECREF(qf);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/from_double", qfloat_from_double_test);
-    g_test_add_func("/public/destroy", qfloat_destroy_test);
-
-    return g_test_run();
-}
diff --git a/check-qint.c b/check-qint.c
deleted file mode 100644 (file)
index 5a27119..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * QInt unit-tests.
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#include <glib.h>
-
-#include "qint.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qint_from_int_test(void)
-{
-    QInt *qi;
-    const int value = -42;
-
-    qi = qint_from_int(value);
-    g_assert(qi != NULL);
-    g_assert(qi->value == value);
-    g_assert(qi->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
-
-    // destroy doesn't exit yet
-    g_free(qi);
-}
-
-static void qint_destroy_test(void)
-{
-    QInt *qi = qint_from_int(0);
-    QDECREF(qi);
-}
-
-static void qint_from_int64_test(void)
-{
-    QInt *qi;
-    const int64_t value = 0x1234567890abcdefLL;
-
-    qi = qint_from_int(value);
-    g_assert((int64_t) qi->value == value);
-
-    QDECREF(qi);
-}
-
-static void qint_get_int_test(void)
-{
-    QInt *qi;
-    const int value = 123456;
-
-    qi = qint_from_int(value);
-    g_assert(qint_get_int(qi) == value);
-
-    QDECREF(qi);
-}
-
-static void qobject_to_qint_test(void)
-{
-    QInt *qi;
-
-    qi = qint_from_int(0);
-    g_assert(qobject_to_qint(QOBJECT(qi)) == qi);
-
-    QDECREF(qi);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/from_int", qint_from_int_test);
-    g_test_add_func("/public/destroy", qint_destroy_test);
-    g_test_add_func("/public/from_int64", qint_from_int64_test);
-    g_test_add_func("/public/get_int", qint_get_int_test);
-    g_test_add_func("/public/to_qint", qobject_to_qint_test);
-
-    return g_test_run();
-}
diff --git a/check-qjson.c b/check-qjson.c
deleted file mode 100644 (file)
index 526e25e..0000000
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-#include <glib.h>
-
-#include "qstring.h"
-#include "qint.h"
-#include "qdict.h"
-#include "qlist.h"
-#include "qfloat.h"
-#include "qbool.h"
-#include "qjson.h"
-
-#include "qemu-common.h"
-
-static void escaped_string(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        const char *decoded;
-        int skip;
-    } test_cases[] = {
-        { "\"\\b\"", "\b" },
-        { "\"\\f\"", "\f" },
-        { "\"\\n\"", "\n" },
-        { "\"\\r\"", "\r" },
-        { "\"\\t\"", "\t" },
-        { "\"/\"", "/" },
-        { "\"\\/\"", "/", .skip = 1 },
-        { "\"\\\\\"", "\\" },
-        { "\"\\\"\"", "\"" },
-        { "\"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  ", .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" },
-        {}
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        
-        str = qobject_to_qstring(obj);
-        g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
-
-        if (test_cases[i].skip == 0) {
-            str = qobject_to_json(obj);
-            g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
-            qobject_decref(obj);
-        }
-
-        QDECREF(str);
-    }
-}
-
-static void simple_string(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        const char *decoded;
-    } test_cases[] = {
-        { "\"hello world\"", "hello world" },
-        { "\"the quick brown fox jumped over the fence\"",
-          "the quick brown fox jumped over the fence" },
-        {}
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        
-        str = qobject_to_qstring(obj);
-        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
-
-        str = qobject_to_json(obj);
-        g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
-
-        qobject_decref(obj);
-        
-        QDECREF(str);
-    }
-}
-
-static void single_quote_string(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        const char *decoded;
-    } test_cases[] = {
-        { "'hello world'", "hello world" },
-        { "'the quick brown fox \\' jumped over the fence'",
-          "the quick brown fox ' jumped over the fence" },
-        {}
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        
-        str = qobject_to_qstring(obj);
-        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
-
-        QDECREF(str);
-    }
-}
-
-static void vararg_string(void)
-{
-    int i;
-    struct {
-        const char *decoded;
-    } test_cases[] = {
-        { "hello world" },
-        { "the quick brown fox jumped over the fence" },
-        {}
-    };
-
-    for (i = 0; test_cases[i].decoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_jsonf("%s", test_cases[i].decoded);
-
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        
-        str = qobject_to_qstring(obj);
-        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
-
-        QDECREF(str);
-    }
-}
-
-static void simple_number(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        int64_t decoded;
-        int skip;
-    } test_cases[] = {
-        { "0", 0 },
-        { "1234", 1234 },
-        { "1", 1 },
-        { "-32", -32 },
-        { "-0", 0, .skip = 1 },
-        { },
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QInt *qint;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QINT);
-
-        qint = qobject_to_qint(obj);
-        g_assert(qint_get_int(qint) == test_cases[i].decoded);
-        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);
-            QDECREF(str);
-        }
-
-        QDECREF(qint);
-    }
-}
-
-static void float_number(void)
-{
-    int i;
-    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, .skip = 1 },
-        { },
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QFloat *qfloat;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QFLOAT);
-
-        qfloat = qobject_to_qfloat(obj);
-        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
-
-        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);
-            QDECREF(str);
-        }
-
-        QDECREF(qfloat);
-    }
-}
-
-static void vararg_number(void)
-{
-    QObject *obj;
-    QInt *qint;
-    QFloat *qfloat;
-    int value = 0x2342;
-    int64_t value64 = 0x2342342343LL;
-    double valuef = 2.323423423;
-
-    obj = qobject_from_jsonf("%d", value);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QINT);
-
-    qint = qobject_to_qint(obj);
-    g_assert(qint_get_int(qint) == value);
-
-    QDECREF(qint);
-
-    obj = qobject_from_jsonf("%" PRId64, value64);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QINT);
-
-    qint = qobject_to_qint(obj);
-    g_assert(qint_get_int(qint) == value64);
-
-    QDECREF(qint);
-
-    obj = qobject_from_jsonf("%f", valuef);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
-
-    qfloat = qobject_to_qfloat(obj);
-    g_assert(qfloat_get_double(qfloat) == valuef);
-
-    QDECREF(qfloat);
-}
-
-static void keyword_literal(void)
-{
-    QObject *obj;
-    QBool *qbool;
-    QString *str;
-
-    obj = qobject_from_json("true");
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-
-    qbool = qobject_to_qbool(obj);
-    g_assert(qbool_get_int(qbool) != 0);
-
-    str = qobject_to_json(obj);
-    g_assert(strcmp(qstring_get_str(str), "true") == 0);
-    QDECREF(str);
-
-    QDECREF(qbool);
-
-    obj = qobject_from_json("false");
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-
-    qbool = qobject_to_qbool(obj);
-    g_assert(qbool_get_int(qbool) == 0);
-
-    str = qobject_to_json(obj);
-    g_assert(strcmp(qstring_get_str(str), "false") == 0);
-    QDECREF(str);
-
-    QDECREF(qbool);
-
-    obj = qobject_from_jsonf("%i", false);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-
-    qbool = qobject_to_qbool(obj);
-    g_assert(qbool_get_int(qbool) == 0);
-
-    QDECREF(qbool);
-    
-    obj = qobject_from_jsonf("%i", true);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-
-    qbool = qobject_to_qbool(obj);
-    g_assert(qbool_get_int(qbool) != 0);
-
-    QDECREF(qbool);
-}
-
-typedef struct LiteralQDictEntry LiteralQDictEntry;
-typedef struct LiteralQObject LiteralQObject;
-
-struct LiteralQObject
-{
-    int type;
-    union {
-        int64_t qint;
-        const char *qstr;
-        LiteralQDictEntry *qdict;
-        LiteralQObject *qlist;
-    } value;
-};
-
-struct LiteralQDictEntry
-{
-    const char *key;
-    LiteralQObject value;
-};
-
-#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
-#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
-#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
-#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
-
-typedef struct QListCompareHelper
-{
-    int index;
-    LiteralQObject *objs;
-    int result;
-} QListCompareHelper;
-
-static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
-
-static void compare_helper(QObject *obj, void *opaque)
-{
-    QListCompareHelper *helper = opaque;
-
-    if (helper->result == 0) {
-        return;
-    }
-
-    if (helper->objs[helper->index].type == QTYPE_NONE) {
-        helper->result = 0;
-        return;
-    }
-
-    helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
-}
-
-static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
-{
-    if (lhs->type != qobject_type(rhs)) {
-        return 0;
-    }
-
-    switch (lhs->type) {
-    case QTYPE_QINT:
-        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
-    case QTYPE_QSTRING:
-        return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
-    case QTYPE_QDICT: {
-        int i;
-
-        for (i = 0; lhs->value.qdict[i].key; i++) {
-            QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
-
-            if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
-                return 0;
-            }
-        }
-
-        return 1;
-    }
-    case QTYPE_QLIST: {
-        QListCompareHelper helper;
-
-        helper.index = 0;
-        helper.objs = lhs->value.qlist;
-        helper.result = 1;
-        
-        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
-
-        return helper.result;
-    }
-    default:
-        break;
-    }
-
-    return 0;
-}
-
-static void simple_dict(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        LiteralQObject decoded;
-    } test_cases[] = {
-        {
-            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
-            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
-                        { "foo", QLIT_QINT(42) },
-                        { "bar", QLIT_QSTR("hello world") },
-                        { }
-                    })),
-        }, {
-            .encoded = "{}",
-            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
-                        { }
-                    })),
-        }, {
-            .encoded = "{\"foo\": 43}",
-            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
-                        { "foo", QLIT_QINT(43) },
-                        { }
-                    })),
-        },
-        { }
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QDICT);
-
-        g_assert(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));
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QDICT);
-
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
-        qobject_decref(obj);
-        QDECREF(str);
-    }
-}
-
-static void simple_list(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        LiteralQObject decoded;
-    } test_cases[] = {
-        {
-            .encoded = "[43,42]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QINT(42),
-                        { }
-                    })),
-        },
-        {
-            .encoded = "[43]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        { }
-                    })),
-        },
-        {
-            .encoded = "[]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        { }
-                    })),
-        },
-        {
-            .encoded = "[{}]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QDICT(((LiteralQDictEntry[]){
-                                    {},
-                                        })),
-                        {},
-                            })),
-        },
-        { }
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-        g_assert(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));
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
-        qobject_decref(obj);
-        QDECREF(str);
-    }
-}
-
-static void simple_whitespace(void)
-{
-    int i;
-    struct {
-        const char *encoded;
-        LiteralQObject decoded;
-    } test_cases[] = {
-        {
-            .encoded = " [ 43 , 42 ]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QINT(42),
-                        { }
-                    })),
-        },
-        {
-            .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QDICT(((LiteralQDictEntry[]){
-                                    { "h", QLIT_QSTR("b") },
-                                    { }})),
-                        QLIT_QLIST(((LiteralQObject[]){
-                                    { }})),
-                        QLIT_QINT(42),
-                        { }
-                    })),
-        },
-        {
-            .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
-            .decoded = QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(43),
-                        QLIT_QDICT(((LiteralQDictEntry[]){
-                                    { "h", QLIT_QSTR("b") },
-                                    { "a", QLIT_QINT(32) },
-                                    { }})),
-                        QLIT_QLIST(((LiteralQObject[]){
-                                    { }})),
-                        QLIT_QINT(42),
-                        { }
-                    })),
-        },
-        { }
-    };
-
-    for (i = 0; test_cases[i].encoded; i++) {
-        QObject *obj;
-        QString *str;
-
-        obj = qobject_from_json(test_cases[i].encoded);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-        g_assert(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));
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
-
-        qobject_decref(obj);
-        QDECREF(str);
-    }
-}
-
-static void simple_varargs(void)
-{
-    QObject *embedded_obj;
-    QObject *obj;
-    LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
-            QLIT_QINT(1),
-            QLIT_QINT(2),
-            QLIT_QLIST(((LiteralQObject[]){
-                        QLIT_QINT(32),
-                        QLIT_QINT(42),
-                        {}})),
-            {}}));
-
-    embedded_obj = qobject_from_json("[32, 42]");
-    g_assert(embedded_obj != NULL);
-
-    obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
-    g_assert(obj != NULL);
-
-    g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
-
-    qobject_decref(obj);
-}
-
-static void empty_input(void)
-{
-    const char *empty = "";
-
-    QObject *obj = qobject_from_json(empty);
-    g_assert(obj == NULL);
-}
-
-static void unterminated_string(void)
-{
-    QObject *obj = qobject_from_json("\"abc");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_sq_string(void)
-{
-    QObject *obj = qobject_from_json("'abc");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_escape(void)
-{
-    QObject *obj = qobject_from_json("\"abc\\\"");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_array(void)
-{
-    QObject *obj = qobject_from_json("[32");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_array_comma(void)
-{
-    QObject *obj = qobject_from_json("[32,");
-    g_assert(obj == NULL);
-}
-
-static void invalid_array_comma(void)
-{
-    QObject *obj = qobject_from_json("[32,}");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_dict(void)
-{
-    QObject *obj = qobject_from_json("{'abc':32");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_dict_comma(void)
-{
-    QObject *obj = qobject_from_json("{'abc':32,");
-    g_assert(obj == NULL);
-}
-
-static void invalid_dict_comma(void)
-{
-    QObject *obj = qobject_from_json("{'abc':32,}");
-    g_assert(obj == NULL);
-}
-
-static void unterminated_literal(void)
-{
-    QObject *obj = qobject_from_json("nul");
-    g_assert(obj == NULL);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/literals/string/simple", simple_string);
-    g_test_add_func("/literals/string/escaped", escaped_string);
-    g_test_add_func("/literals/string/single_quote", single_quote_string);
-    g_test_add_func("/literals/string/vararg", vararg_string);
-
-    g_test_add_func("/literals/number/simple", simple_number);
-    g_test_add_func("/literals/number/float", float_number);
-    g_test_add_func("/literals/number/vararg", vararg_number);
-
-    g_test_add_func("/literals/keyword", keyword_literal);
-
-    g_test_add_func("/dicts/simple_dict", simple_dict);
-    g_test_add_func("/lists/simple_list", simple_list);
-
-    g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
-
-    g_test_add_func("/varargs/simple_varargs", simple_varargs);
-
-    g_test_add_func("/errors/empty_input", empty_input);
-    g_test_add_func("/errors/unterminated/string", unterminated_string);
-    g_test_add_func("/errors/unterminated/escape", unterminated_escape);
-    g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
-    g_test_add_func("/errors/unterminated/array", unterminated_array);
-    g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
-    g_test_add_func("/errors/unterminated/dict", unterminated_dict);
-    g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
-    g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
-    g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
-    g_test_add_func("/errors/unterminated/literal", unterminated_literal);
-
-    return g_test_run();
-}
diff --git a/check-qlist.c b/check-qlist.c
deleted file mode 100644 (file)
index 501ba26..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * QList unit-tests.
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#include <glib.h>
-
-#include "qint.h"
-#include "qlist.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qlist_new_test(void)
-{
-    QList *qlist;
-
-    qlist = qlist_new();
-    g_assert(qlist != NULL);
-    g_assert(qlist->base.refcnt == 1);
-    g_assert(qobject_type(QOBJECT(qlist)) == QTYPE_QLIST);
-
-    // destroy doesn't exist yet
-    g_free(qlist);
-}
-
-static void qlist_append_test(void)
-{
-    QInt *qi;
-    QList *qlist;
-    QListEntry *entry;
-
-    qi = qint_from_int(42);
-
-    qlist = qlist_new();
-    qlist_append(qlist, qi);
-
-    entry = QTAILQ_FIRST(&qlist->head);
-    g_assert(entry != NULL);
-    g_assert(entry->value == QOBJECT(qi));
-
-    // destroy doesn't exist yet
-    QDECREF(qi);
-    g_free(entry);
-    g_free(qlist);
-}
-
-static void qobject_to_qlist_test(void)
-{
-    QList *qlist;
-
-    qlist = qlist_new();
-
-    g_assert(qobject_to_qlist(QOBJECT(qlist)) == qlist);
-
-    // destroy doesn't exist yet
-    g_free(qlist);
-}
-
-static void qlist_destroy_test(void)
-{
-    int i;
-    QList *qlist;
-
-    qlist = qlist_new();
-
-    for (i = 0; i < 42; i++)
-        qlist_append(qlist, qint_from_int(i));
-
-    QDECREF(qlist);
-}
-
-static int iter_called;
-static const int iter_max = 42;
-
-static void iter_func(QObject *obj, void *opaque)
-{
-    QInt *qi;
-
-    g_assert(opaque == NULL);
-
-    qi = qobject_to_qint(obj);
-    g_assert(qi != NULL);
-    g_assert((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
-
-    iter_called++;
-}
-
-static void qlist_iter_test(void)
-{
-    int i;
-    QList *qlist;
-
-    qlist = qlist_new();
-
-    for (i = 0; i < iter_max; i++)
-        qlist_append(qlist, qint_from_int(i));
-
-    iter_called = 0;
-    qlist_iter(qlist, iter_func, NULL);
-
-    g_assert(iter_called == iter_max);
-
-    QDECREF(qlist);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/new", qlist_new_test);
-    g_test_add_func("/public/append", qlist_append_test);
-    g_test_add_func("/public/to_qlist", qobject_to_qlist_test);
-    g_test_add_func("/public/destroy", qlist_destroy_test);
-    g_test_add_func("/public/iter", qlist_iter_test);
-
-    return g_test_run();
-}
diff --git a/check-qstring.c b/check-qstring.c
deleted file mode 100644 (file)
index addad6c..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * QString unit-tests.
- *
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- */
-#include <glib.h>
-
-#include "qstring.h"
-#include "qemu-common.h"
-
-/*
- * Public Interface test-cases
- *
- * (with some violations to access 'private' data)
- */
-
-static void qstring_from_str_test(void)
-{
-    QString *qstring;
-    const char *str = "QEMU";
-
-    qstring = qstring_from_str(str);
-    g_assert(qstring != NULL);
-    g_assert(qstring->base.refcnt == 1);
-    g_assert(strcmp(str, qstring->string) == 0);
-    g_assert(qobject_type(QOBJECT(qstring)) == QTYPE_QSTRING);
-
-    // destroy doesn't exit yet
-    g_free(qstring->string);
-    g_free(qstring);
-}
-
-static void qstring_destroy_test(void)
-{
-    QString *qstring = qstring_from_str("destroy test");
-    QDECREF(qstring);
-}
-
-static void qstring_get_str_test(void)
-{
-    QString *qstring;
-    const char *ret_str;
-    const char *str = "QEMU/KVM";
-
-    qstring = qstring_from_str(str);
-    ret_str = qstring_get_str(qstring);
-    g_assert(strcmp(ret_str, str) == 0);
-
-    QDECREF(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);
-    QDECREF(qstring);
-}
-
-static void qstring_from_substr_test(void)
-{
-    QString *qs;
-
-    qs = qstring_from_substr("virtualization", 3, 9);
-    g_assert(qs != NULL);
-    g_assert(strcmp(qstring_get_str(qs), "tualiza") == 0);
-
-    QDECREF(qs);
-}
-
-
-static void qobject_to_qstring_test(void)
-{
-    QString *qstring;
-
-    qstring = qstring_from_str("foo");
-    g_assert(qobject_to_qstring(QOBJECT(qstring)) == qstring);
-
-    QDECREF(qstring);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/public/from_str", qstring_from_str_test);
-    g_test_add_func("/public/destroy", qstring_destroy_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);
-
-    return g_test_run();
-}
index 04a91983ec26e6d398f01a2780663c7e2cac729f..c30093c116067457d9063fc8bfc1f09594cd1156 100644 (file)
--- a/rules.mak
+++ b/rules.mak
@@ -47,7 +47,7 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
 cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
               >/dev/null 2>&1 && echo OK), $2, $3)
 
-VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi
+VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.sh
 set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
 
 # find-in-path
diff --git a/scripts/gtester-cat b/scripts/gtester-cat
new file mode 100755 (executable)
index 0000000..061a952
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# Copyright IBM, Corp. 2012
+#
+# Authors:
+#  Anthony Liguori <aliguori@us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPLv2 or later.
+# See the COPYING file in the top-level directory.
+
+cat <<EOF
+<?xml version="1.0"?>
+<gtester>
+ <info>
+  <package>qemu</package>
+  <version>0.0</version>
+  <revision>rev</revision>
+ </info>
+EOF
+
+sed \
+  -e '/<?xml/d' \
+  -e '/^<gtester>$/d' \
+  -e '/<info>/,/<\/info>/d' \
+  -e '$b' \
+  -e '/^<\/gtester>$/d' "$@"
diff --git a/test-coroutine.c b/test-coroutine.c
deleted file mode 100644 (file)
index e5d14eb..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Coroutine tests
- *
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include <glib.h>
-#include "qemu-coroutine.h"
-
-/*
- * Check that qemu_in_coroutine() works
- */
-
-static void coroutine_fn verify_in_coroutine(void *opaque)
-{
-    g_assert(qemu_in_coroutine());
-}
-
-static void test_in_coroutine(void)
-{
-    Coroutine *coroutine;
-
-    g_assert(!qemu_in_coroutine());
-
-    coroutine = qemu_coroutine_create(verify_in_coroutine);
-    qemu_coroutine_enter(coroutine, NULL);
-}
-
-/*
- * Check that qemu_coroutine_self() works
- */
-
-static void coroutine_fn verify_self(void *opaque)
-{
-    g_assert(qemu_coroutine_self() == opaque);
-}
-
-static void test_self(void)
-{
-    Coroutine *coroutine;
-
-    coroutine = qemu_coroutine_create(verify_self);
-    qemu_coroutine_enter(coroutine, coroutine);
-}
-
-/*
- * Check that coroutines may nest multiple levels
- */
-
-typedef struct {
-    unsigned int n_enter;   /* num coroutines entered */
-    unsigned int n_return;  /* num coroutines returned */
-    unsigned int max;       /* maximum level of nesting */
-} NestData;
-
-static void coroutine_fn nest(void *opaque)
-{
-    NestData *nd = opaque;
-
-    nd->n_enter++;
-
-    if (nd->n_enter < nd->max) {
-        Coroutine *child;
-
-        child = qemu_coroutine_create(nest);
-        qemu_coroutine_enter(child, nd);
-    }
-
-    nd->n_return++;
-}
-
-static void test_nesting(void)
-{
-    Coroutine *root;
-    NestData nd = {
-        .n_enter  = 0,
-        .n_return = 0,
-        .max      = 128,
-    };
-
-    root = qemu_coroutine_create(nest);
-    qemu_coroutine_enter(root, &nd);
-
-    /* Must enter and return from max nesting level */
-    g_assert_cmpint(nd.n_enter, ==, nd.max);
-    g_assert_cmpint(nd.n_return, ==, nd.max);
-}
-
-/*
- * Check that yield/enter transfer control correctly
- */
-
-static void coroutine_fn yield_5_times(void *opaque)
-{
-    bool *done = opaque;
-    int i;
-
-    for (i = 0; i < 5; i++) {
-        qemu_coroutine_yield();
-    }
-    *done = true;
-}
-
-static void test_yield(void)
-{
-    Coroutine *coroutine;
-    bool done = false;
-    int i = -1; /* one extra time to return from coroutine */
-
-    coroutine = qemu_coroutine_create(yield_5_times);
-    while (!done) {
-        qemu_coroutine_enter(coroutine, &done);
-        i++;
-    }
-    g_assert_cmpint(i, ==, 5); /* coroutine must yield 5 times */
-}
-
-/*
- * Check that creation, enter, and return work
- */
-
-static void coroutine_fn set_and_exit(void *opaque)
-{
-    bool *done = opaque;
-
-    *done = true;
-}
-
-static void test_lifecycle(void)
-{
-    Coroutine *coroutine;
-    bool done = false;
-
-    /* Create, enter, and return from coroutine */
-    coroutine = qemu_coroutine_create(set_and_exit);
-    qemu_coroutine_enter(coroutine, &done);
-    g_assert(done); /* expect done to be true (first time) */
-
-    /* Repeat to check that no state affects this test */
-    done = false;
-    coroutine = qemu_coroutine_create(set_and_exit);
-    qemu_coroutine_enter(coroutine, &done);
-    g_assert(done); /* expect done to be true (second time) */
-}
-
-/*
- * Lifecycle benchmark
- */
-
-static void coroutine_fn empty_coroutine(void *opaque)
-{
-    /* Do nothing */
-}
-
-static void perf_lifecycle(void)
-{
-    Coroutine *coroutine;
-    unsigned int i, max;
-    double duration;
-
-    max = 1000000;
-
-    g_test_timer_start();
-    for (i = 0; i < max; i++) {
-        coroutine = qemu_coroutine_create(empty_coroutine);
-        qemu_coroutine_enter(coroutine, NULL);
-    }
-    duration = g_test_timer_elapsed();
-
-    g_test_message("Lifecycle %u iterations: %f s\n", max, duration);
-}
-
-static void perf_nesting(void)
-{
-    unsigned int i, maxcycles, maxnesting;
-    double duration;
-
-    maxcycles = 100000000;
-    maxnesting = 20000;
-    Coroutine *root;
-    NestData nd = {
-        .n_enter  = 0,
-        .n_return = 0,
-        .max      = maxnesting,
-    };
-
-    g_test_timer_start();
-    for (i = 0; i < maxcycles; i++) {
-        root = qemu_coroutine_create(nest);
-        qemu_coroutine_enter(root, &nd);
-    }
-    duration = g_test_timer_elapsed();
-
-    g_test_message("Nesting %u iterations of %u depth each: %f s\n",
-        maxcycles, maxnesting, duration);
-}
-
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-    g_test_add_func("/basic/lifecycle", test_lifecycle);
-    g_test_add_func("/basic/yield", test_yield);
-    g_test_add_func("/basic/nesting", test_nesting);
-    g_test_add_func("/basic/self", test_self);
-    g_test_add_func("/basic/in_coroutine", test_in_coroutine);
-    if (g_test_perf()) {
-        g_test_add_func("/perf/lifecycle", perf_lifecycle);
-        g_test_add_func("/perf/nesting", perf_nesting);
-    }
-    return g_test_run();
-}
diff --git a/test-qmp-commands.c b/test-qmp-commands.c
deleted file mode 100644 (file)
index 60cbf01..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-#include <glib.h>
-#include "qemu-objects.h"
-#include "test-qmp-commands.h"
-#include "qapi/qmp-core.h"
-#include "module.h"
-
-void qmp_user_def_cmd(Error **errp)
-{
-}
-
-void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
-{
-}
-
-UserDefTwo * qmp_user_def_cmd2(UserDefOne * ud1a, UserDefOne * ud1b, Error **errp)
-{
-    UserDefTwo *ret;
-    UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
-    UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
-
-    ud1c->string = strdup(ud1a->string);
-    ud1c->integer = ud1a->integer;
-    ud1d->string = strdup(ud1b->string);
-    ud1d->integer = ud1b->integer;
-
-    ret = g_malloc0(sizeof(UserDefTwo));
-    ret->string = strdup("blah1");
-    ret->dict.string = strdup("blah2");
-    ret->dict.dict.userdef = ud1c;
-    ret->dict.dict.string = strdup("blah3");
-    ret->dict.has_dict2 = true;
-    ret->dict.dict2.userdef = ud1d;
-    ret->dict.dict2.string = strdup("blah4");
-
-    return ret;
-}
-
-/* test commands with no input and no return value */
-static void test_dispatch_cmd(void)
-{
-    QDict *req = qdict_new();
-    QObject *resp;
-
-    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd")));
-
-    resp = qmp_dispatch(QOBJECT(req));
-    assert(resp != NULL);
-    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
-
-    qobject_decref(resp);
-    QDECREF(req);
-}
-
-/* test commands that return an error due to invalid parameters */
-static void test_dispatch_cmd_error(void)
-{
-    QDict *req = qdict_new();
-    QObject *resp;
-
-    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
-
-    resp = qmp_dispatch(QOBJECT(req));
-    assert(resp != NULL);
-    assert(qdict_haskey(qobject_to_qdict(resp), "error"));
-
-    qobject_decref(resp);
-    QDECREF(req);
-}
-
-/* test commands that involve both input parameters and return values */
-static void test_dispatch_cmd_io(void)
-{
-    QDict *req = qdict_new();
-    QDict *args = qdict_new();
-    QDict *ud1a = qdict_new();
-    QDict *ud1b = qdict_new();
-    QObject *resp;
-
-    qdict_put_obj(ud1a, "integer", QOBJECT(qint_from_int(42)));
-    qdict_put_obj(ud1a, "string", QOBJECT(qstring_from_str("hello")));
-    qdict_put_obj(ud1b, "integer", QOBJECT(qint_from_int(422)));
-    qdict_put_obj(ud1b, "string", QOBJECT(qstring_from_str("hello2")));
-    qdict_put_obj(args, "ud1a", QOBJECT(ud1a));
-    qdict_put_obj(args, "ud1b", QOBJECT(ud1b));
-    qdict_put_obj(req, "arguments", QOBJECT(args));
-
-    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
-
-    /* TODO: put in full payload and check for errors */
-    resp = qmp_dispatch(QOBJECT(req));
-    assert(resp != NULL);
-    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
-
-    qobject_decref(resp);
-    QDECREF(req);
-}
-
-/* test generated dealloc functions for generated types */
-static void test_dealloc_types(void)
-{
-    UserDefOne *ud1test, *ud1a, *ud1b;
-    UserDefOneList *ud1list;
-
-    ud1test = g_malloc0(sizeof(UserDefOne));
-    ud1test->integer = 42;
-    ud1test->string = g_strdup("hi there 42");
-
-    qapi_free_UserDefOne(ud1test);
-
-    ud1a = g_malloc0(sizeof(UserDefOne));
-    ud1a->integer = 43;
-    ud1a->string = g_strdup("hi there 43");
-
-    ud1b = g_malloc0(sizeof(UserDefOne));
-    ud1b->integer = 44;
-    ud1b->string = g_strdup("hi there 44");
-
-    ud1list = g_malloc0(sizeof(UserDefOneList));
-    ud1list->value = ud1a;
-    ud1list->next = g_malloc0(sizeof(UserDefOneList));
-    ud1list->next->value = ud1b;
-
-    qapi_free_UserDefOneList(ud1list);
-}
-
-int main(int argc, char **argv)
-{
-    g_test_init(&argc, &argv, NULL);
-
-    g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
-    g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
-    g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
-    g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
-
-    module_call_init(MODULE_INIT_QAPI);
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-qmp-input-strict.c b/test-qmp-input-strict.c
deleted file mode 100644 (file)
index f6df8cb..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * QMP Input Visitor unit-tests (strict mode).
- *
- * Copyright (C) 2011-2012 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *  Paolo Bonzini <pbonzini@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-#include <stdarg.h>
-
-#include "qapi/qmp-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestInputVisitorData {
-    QObject *obj;
-    QmpInputVisitor *qiv;
-} TestInputVisitorData;
-
-static void validate_teardown(TestInputVisitorData *data,
-                               const void *unused)
-{
-    qobject_decref(data->obj);
-    data->obj = NULL;
-
-    if (data->qiv) {
-        qmp_input_visitor_cleanup(data->qiv);
-        data->qiv = NULL;
-    }
-}
-
-/* This is provided instead of a test setup function so that the JSON
-   string used by the tests are kept in the test functions (and not
-   int main()) */
-static GCC_FMT_ATTR(2, 3)
-Visitor *validate_test_init(TestInputVisitorData *data,
-                             const char *json_string, ...)
-{
-    Visitor *v;
-    va_list ap;
-
-    va_start(ap, json_string);
-    data->obj = qobject_from_jsonv(json_string, &ap);
-    va_end(ap);
-
-    g_assert(data->obj != NULL);
-
-    data->qiv = qmp_input_visitor_new_strict(data->obj);
-    g_assert(data->qiv != NULL);
-
-    v = qmp_input_get_visitor(data->qiv);
-    g_assert(v != NULL);
-
-    return v;
-}
-
-typedef struct TestStruct
-{
-    int64_t integer;
-    bool boolean;
-    char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
-                                  const char *name, Error **errp)
-{
-    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
-                       errp);
-
-    visit_type_int(v, &(*obj)->integer, "integer", errp);
-    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
-    visit_type_str(v, &(*obj)->string, "string", errp);
-
-    visit_end_struct(v, errp);
-}
-
-static void test_validate_struct(TestInputVisitorData *data,
-                                  const void *unused)
-{
-    TestStruct *p = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
-
-    visit_type_TestStruct(v, &p, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_free(p->string);
-    g_free(p);
-}
-
-static void test_validate_struct_nested(TestInputVisitorData *data,
-                                         const void *unused)
-{
-    UserDefNested *udp = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
-
-    visit_type_UserDefNested(v, &udp, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    qapi_free_UserDefNested(udp);
-}
-
-static void test_validate_list(TestInputVisitorData *data,
-                                const void *unused)
-{
-    UserDefOneList *head = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
-
-    visit_type_UserDefOneList(v, &head, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    qapi_free_UserDefOneList(head);
-}
-
-static void test_validate_union(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    UserDefUnion *tmp = NULL;
-    Visitor *v;
-    Error *errp = NULL;
-
-    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
-
-    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    qapi_free_UserDefUnion(tmp);
-}
-
-static void test_validate_fail_struct(TestInputVisitorData *data,
-                                       const void *unused)
-{
-    TestStruct *p = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
-
-    visit_type_TestStruct(v, &p, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    if (p) {
-        g_free(p->string);
-    }
-    g_free(p);
-}
-
-static void test_validate_fail_struct_nested(TestInputVisitorData *data,
-                                              const void *unused)
-{
-    UserDefNested *udp = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
-
-    visit_type_UserDefNested(v, &udp, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    qapi_free_UserDefNested(udp);
-}
-
-static void test_validate_fail_list(TestInputVisitorData *data,
-                                     const void *unused)
-{
-    UserDefOneList *head = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
-
-    visit_type_UserDefOneList(v, &head, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    qapi_free_UserDefOneList(head);
-}
-
-static void test_validate_fail_union(TestInputVisitorData *data,
-                                      const void *unused)
-{
-    UserDefUnion *tmp = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }");
-
-    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    qapi_free_UserDefUnion(tmp);
-}
-
-static void validate_test_add(const char *testpath,
-                               TestInputVisitorData *data,
-                               void (*test_func)(TestInputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
-               validate_teardown);
-}
-
-int main(int argc, char **argv)
-{
-    TestInputVisitorData testdata;
-
-    g_test_init(&argc, &argv, NULL);
-
-    validate_test_add("/visitor/input-strict/pass/struct",
-                       &testdata, test_validate_struct);
-    validate_test_add("/visitor/input-strict/pass/struct-nested",
-                       &testdata, test_validate_struct_nested);
-    validate_test_add("/visitor/input-strict/pass/list",
-                       &testdata, test_validate_list);
-    validate_test_add("/visitor/input-strict/pass/union",
-                       &testdata, test_validate_union);
-    validate_test_add("/visitor/input-strict/fail/struct",
-                       &testdata, test_validate_fail_struct);
-    validate_test_add("/visitor/input-strict/fail/struct-nested",
-                       &testdata, test_validate_fail_struct_nested);
-    validate_test_add("/visitor/input-strict/fail/list",
-                       &testdata, test_validate_fail_list);
-    validate_test_add("/visitor/input-strict/fail/union",
-                       &testdata, test_validate_fail_union);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c
deleted file mode 100644 (file)
index c30fdc4..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * QMP Input Visitor unit-tests.
- *
- * Copyright (C) 2011 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-#include <stdarg.h>
-
-#include "qapi/qmp-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestInputVisitorData {
-    QObject *obj;
-    QmpInputVisitor *qiv;
-} TestInputVisitorData;
-
-static void visitor_input_teardown(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    qobject_decref(data->obj);
-    data->obj = NULL;
-
-    if (data->qiv) {
-        qmp_input_visitor_cleanup(data->qiv);
-        data->qiv = NULL;
-    }
-}
-
-/* This is provided instead of a test setup function so that the JSON
-   string used by the tests are kept in the test functions (and not
-   int main()) */
-static GCC_FMT_ATTR(2, 3)
-Visitor *visitor_input_test_init(TestInputVisitorData *data,
-                                 const char *json_string, ...)
-{
-    Visitor *v;
-    va_list ap;
-
-    va_start(ap, json_string);
-    data->obj = qobject_from_jsonv(json_string, &ap);
-    va_end(ap);
-
-    g_assert(data->obj != NULL);
-
-    data->qiv = qmp_input_visitor_new(data->obj);
-    g_assert(data->qiv != NULL);
-
-    v = qmp_input_get_visitor(data->qiv);
-    g_assert(v != NULL);
-
-    return v;
-}
-
-static void test_visitor_in_int(TestInputVisitorData *data,
-                                const void *unused)
-{
-    int64_t res = 0, value = -42;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "%" PRId64, value);
-
-    visit_type_int(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, value);
-}
-
-static void test_visitor_in_bool(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    Error *errp = NULL;
-    bool res = false;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "true");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, true);
-}
-
-static void test_visitor_in_number(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    double res = 0, value = 3.14;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "%f", value);
-
-    visit_type_number(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpfloat(res, ==, value);
-}
-
-static void test_visitor_in_string(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    char *res = NULL, *value = (char *) "Q E M U";
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "%s", value);
-
-    visit_type_str(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpstr(res, ==, value);
-
-    g_free(res);
-}
-
-static void test_visitor_in_enum(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    Error *errp = NULL;
-    Visitor *v;
-    EnumOne i;
-
-    for (i = 0; EnumOne_lookup[i]; i++) {
-        EnumOne res = -1;
-
-        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
-
-        visit_type_EnumOne(v, &res, NULL, &errp);
-        g_assert(!error_is_set(&errp));
-        g_assert_cmpint(i, ==, res);
-
-        visitor_input_teardown(data, NULL);
-    }
-
-    data->obj = NULL;
-    data->qiv = NULL;
-}
-
-typedef struct TestStruct
-{
-    int64_t integer;
-    bool boolean;
-    char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
-                                  const char *name, Error **errp)
-{
-    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
-                       errp);
-
-    visit_type_int(v, &(*obj)->integer, "integer", errp);
-    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
-    visit_type_str(v, &(*obj)->string, "string", errp);
-
-    visit_end_struct(v, errp);
-}
-
-static void test_visitor_in_struct(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    TestStruct *p = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
-
-    visit_type_TestStruct(v, &p, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(p->integer, ==, -42);
-    g_assert(p->boolean == true);
-    g_assert_cmpstr(p->string, ==, "foo");
-
-    g_free(p->string);
-    g_free(p);
-}
-
-static void check_and_free_str(char *str, const char *cmp)
-{
-    g_assert_cmpstr(str, ==, cmp);
-    g_free(str);
-}
-
-static void test_visitor_in_struct_nested(TestInputVisitorData *data,
-                                          const void *unused)
-{
-    UserDefNested *udp = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
-
-    visit_type_UserDefNested(v, &udp, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-
-    check_and_free_str(udp->string0, "string0");
-    check_and_free_str(udp->dict1.string1, "string1");
-    g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
-    check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
-    check_and_free_str(udp->dict1.dict2.string2, "string2");
-    g_assert(udp->dict1.has_dict3 == false);
-
-    g_free(udp->dict1.dict2.userdef1);
-    g_free(udp);
-}
-
-static void test_visitor_in_list(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    UserDefOneList *item, *head = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-    int i;
-
-    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
-
-    visit_type_UserDefOneList(v, &head, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert(head != NULL);
-
-    for (i = 0, item = head; item; item = item->next, i++) {
-        char string[12];
-
-        snprintf(string, sizeof(string), "string%d", i);
-        g_assert_cmpstr(item->value->string, ==, string);
-        g_assert_cmpint(item->value->integer, ==, 42 + i);
-    }
-
-    qapi_free_UserDefOneList(head);
-}
-
-static void test_visitor_in_union(TestInputVisitorData *data,
-                                  const void *unused)
-{
-    Visitor *v;
-    Error *err = NULL;
-    UserDefUnion *tmp;
-
-    v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
-
-    visit_type_UserDefUnion(v, &tmp, NULL, &err);
-    g_assert(err == NULL);
-    g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B);
-    g_assert_cmpint(tmp->b->integer, ==, 42);
-    qapi_free_UserDefUnion(tmp);
-}
-
-static void input_visitor_test_add(const char *testpath,
-                                   TestInputVisitorData *data,
-                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
-               visitor_input_teardown);
-}
-
-static void test_visitor_in_errors(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    TestStruct *p = NULL;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
-
-    visit_type_TestStruct(v, &p, NULL, &errp);
-    g_assert(error_is_set(&errp));
-    g_assert(p->string == NULL);
-
-    g_free(p->string);
-    g_free(p);
-}
-
-int main(int argc, char **argv)
-{
-    TestInputVisitorData in_visitor_data;
-
-    g_test_init(&argc, &argv, NULL);
-
-    input_visitor_test_add("/visitor/input/int",
-                           &in_visitor_data, test_visitor_in_int);
-    input_visitor_test_add("/visitor/input/bool",
-                           &in_visitor_data, test_visitor_in_bool);
-    input_visitor_test_add("/visitor/input/number",
-                           &in_visitor_data, test_visitor_in_number);
-    input_visitor_test_add("/visitor/input/string",
-                            &in_visitor_data, test_visitor_in_string);
-    input_visitor_test_add("/visitor/input/enum",
-                            &in_visitor_data, test_visitor_in_enum);
-    input_visitor_test_add("/visitor/input/struct",
-                            &in_visitor_data, test_visitor_in_struct);
-    input_visitor_test_add("/visitor/input/struct-nested",
-                            &in_visitor_data, test_visitor_in_struct_nested);
-    input_visitor_test_add("/visitor/input/list",
-                            &in_visitor_data, test_visitor_in_list);
-    input_visitor_test_add("/visitor/input/union",
-                            &in_visitor_data, test_visitor_in_union);
-    input_visitor_test_add("/visitor/input/errors",
-                            &in_visitor_data, test_visitor_in_errors);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c
deleted file mode 100644 (file)
index 24a6359..0000000
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * QMP Output Visitor unit-tests.
- *
- * Copyright (C) 2011 Red Hat Inc.
- *
- * Authors:
- *  Luiz Capitulino <lcapitulino@redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-
-#include "qapi/qmp-output-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestOutputVisitorData {
-    QmpOutputVisitor *qov;
-    Visitor *ov;
-} TestOutputVisitorData;
-
-static void visitor_output_setup(TestOutputVisitorData *data,
-                                 const void *unused)
-{
-    data->qov = qmp_output_visitor_new();
-    g_assert(data->qov != NULL);
-
-    data->ov = qmp_output_get_visitor(data->qov);
-    g_assert(data->ov != NULL);
-}
-
-static void visitor_output_teardown(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    qmp_output_visitor_cleanup(data->qov);
-    data->qov = NULL;
-    data->ov = NULL;
-}
-
-static void test_visitor_out_int(TestOutputVisitorData *data,
-                                 const void *unused)
-{
-    int64_t value = -42;
-    Error *errp = NULL;
-    QObject *obj;
-
-    visit_type_int(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QINT);
-    g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_bool(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    Error *errp = NULL;
-    bool value = true;
-    QObject *obj;
-
-    visit_type_bool(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QBOOL);
-    g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_number(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    double value = 3.14;
-    Error *errp = NULL;
-    QObject *obj;
-
-    visit_type_number(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
-    g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_string(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    char *string = (char *) "Q E M U";
-    Error *errp = NULL;
-    QObject *obj;
-
-    visit_type_str(data->ov, &string, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QSTRING);
-    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_no_string(TestOutputVisitorData *data,
-                                       const void *unused)
-{
-    char *string = NULL;
-    Error *errp = NULL;
-    QObject *obj;
-
-    /* A null string should return "" */
-    visit_type_str(data->ov, &string, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QSTRING);
-    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
-
-    qobject_decref(obj);
-}
-
-static void test_visitor_out_enum(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    Error *errp = NULL;
-    QObject *obj;
-    EnumOne i;
-
-    for (i = 0; i < ENUM_ONE_MAX; i++) {
-        visit_type_EnumOne(data->ov, &i, "unused", &errp);
-        g_assert(!error_is_set(&errp));
-
-        obj = qmp_output_get_qobject(data->qov);
-        g_assert(obj != NULL);
-        g_assert(qobject_type(obj) == QTYPE_QSTRING);
-        g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
-                        EnumOne_lookup[i]);
-        qobject_decref(obj);
-    }
-}
-
-static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
-                                         const void *unused)
-{
-    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
-    Error *errp;
-
-    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
-        errp = NULL;
-        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
-        g_assert(error_is_set(&errp) == true);
-        error_free(errp);
-    }
-}
-
-typedef struct TestStruct
-{
-    int64_t integer;
-    bool boolean;
-    char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
-                                  const char *name, Error **errp)
-{
-    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
-                       errp);
-
-    visit_type_int(v, &(*obj)->integer, "integer", errp);
-    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
-    visit_type_str(v, &(*obj)->string, "string", errp);
-
-    visit_end_struct(v, errp);
-}
-
-static void test_visitor_out_struct(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    TestStruct test_struct = { .integer = 42,
-                               .boolean = false,
-                               .string = (char *) "foo"};
-    TestStruct *p = &test_struct;
-    Error *errp = NULL;
-    QObject *obj;
-    QDict *qdict;
-
-    visit_type_TestStruct(data->ov, &p, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QDICT);
-
-    qdict = qobject_to_qdict(obj);
-    g_assert_cmpint(qdict_size(qdict), ==, 3);
-    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
-    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
-    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
-
-    QDECREF(qdict);
-}
-
-static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
-                                           const void *unused)
-{
-    int64_t value = 42;
-    Error *errp = NULL;
-    UserDefNested *ud2;
-    QObject *obj;
-    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
-    const char *string = "user def string";
-    const char *strings[] = { "forty two", "forty three", "forty four",
-                              "forty five" };
-
-    ud2 = g_malloc0(sizeof(*ud2));
-    ud2->string0 = g_strdup(strings[0]);
-
-    ud2->dict1.string1 = g_strdup(strings[1]);
-    ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
-    ud2->dict1.dict2.userdef1->string = g_strdup(string);
-    ud2->dict1.dict2.userdef1->integer = value;
-    ud2->dict1.dict2.string2 = g_strdup(strings[2]);
-
-    ud2->dict1.has_dict3 = true;
-    ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
-    ud2->dict1.dict3.userdef2->string = g_strdup(string);
-    ud2->dict1.dict3.userdef2->integer = value;
-    ud2->dict1.dict3.string3 = g_strdup(strings[3]);
-
-    visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
-    g_assert(!error_is_set(&errp));
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QDICT);
-
-    qdict = qobject_to_qdict(obj);
-    g_assert_cmpint(qdict_size(qdict), ==, 2);
-    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
-
-    dict1 = qdict_get_qdict(qdict, "dict1");
-    g_assert_cmpint(qdict_size(dict1), ==, 3);
-    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
-
-    dict2 = qdict_get_qdict(dict1, "dict2");
-    g_assert_cmpint(qdict_size(dict2), ==, 2);
-    g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
-    userdef = qdict_get_qdict(dict2, "userdef1");
-    g_assert_cmpint(qdict_size(userdef), ==, 2);
-    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
-    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
-
-    dict3 = qdict_get_qdict(dict1, "dict3");
-    g_assert_cmpint(qdict_size(dict3), ==, 2);
-    g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
-    userdef = qdict_get_qdict(dict3, "userdef2");
-    g_assert_cmpint(qdict_size(userdef), ==, 2);
-    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
-    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
-
-    QDECREF(qdict);
-    qapi_free_UserDefNested(ud2);
-}
-
-static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
-                                           const void *unused)
-{
-    EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
-    UserDefOne u = { 0 }, *pu = &u;
-    Error *errp;
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
-        errp = NULL;
-        u.has_enum1 = true;
-        u.enum1 = bad_values[i];
-        visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
-        g_assert(error_is_set(&errp) == true);
-        error_free(errp);
-    }
-}
-
-typedef struct TestStructList
-{
-    TestStruct *value;
-    struct TestStructList *next;
-} TestStructList;
-
-static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
-                                      const char *name, Error **errp)
-{
-    GenericList *i, **head = (GenericList **)obj;
-
-    visit_start_list(v, name, errp);
-
-    for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
-        TestStructList *native_i = (TestStructList *)i;
-        visit_type_TestStruct(v, &native_i->value, NULL, errp);
-    }
-
-    visit_end_list(v, errp);
-}
-
-static void test_visitor_out_list(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    char *value_str = (char *) "list value";
-    TestStructList *p, *head = NULL;
-    const int max_items = 10;
-    bool value_bool = true;
-    int value_int = 10;
-    Error *errp = NULL;
-    QListEntry *entry;
-    QObject *obj;
-    QList *qlist;
-    int i;
-
-    for (i = 0; i < max_items; i++) {
-        p = g_malloc0(sizeof(*p));
-        p->value = g_malloc0(sizeof(*p->value));
-        p->value->integer = value_int;
-        p->value->boolean = value_bool;
-        p->value->string = value_str;
-
-        p->next = head;
-        head = p;
-    }
-
-    visit_type_TestStructList(data->ov, &head, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-
-    obj = qmp_output_get_qobject(data->qov);
-    g_assert(obj != NULL);
-    g_assert(qobject_type(obj) == QTYPE_QLIST);
-
-    qlist = qobject_to_qlist(obj);
-    g_assert(!qlist_empty(qlist));
-
-    i = 0;
-    QLIST_FOREACH_ENTRY(qlist, entry) {
-        QDict *qdict;
-
-        g_assert(qobject_type(entry->value) == QTYPE_QDICT);
-        qdict = qobject_to_qdict(entry->value);
-        g_assert_cmpint(qdict_size(qdict), ==, 3);
-        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
-        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
-        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
-        i++;
-    }
-    g_assert_cmpint(i, ==, max_items);
-
-    QDECREF(qlist);
-
-    for (p = head; p;) {
-        TestStructList *tmp = p->next;
-        g_free(p->value);
-        g_free(p);
-        p = tmp;
-    }
-}
-
-static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
-                                            const void *unused)
-{
-    UserDefNestedList *p, *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.string1 = g_strdup(string);
-        p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
-        p->value->dict1.dict2.userdef1->string = g_strdup(string);
-        p->value->dict1.dict2.userdef1->integer = 42;
-        p->value->dict1.dict2.string2 = g_strdup(string);
-        p->value->dict1.has_dict3 = false;
-
-        p->next = head;
-        head = p;
-    }
-
-    qapi_free_UserDefNestedList(head);
-}
-
-static void test_visitor_out_union(TestOutputVisitorData *data,
-                                   const void *unused)
-{
-    QObject *arg, *qvalue;
-    QDict *qdict, *value;
-
-    Error *err = NULL;
-
-    UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion));
-    tmp->kind = USER_DEF_UNION_KIND_A;
-    tmp->a = g_malloc0(sizeof(UserDefA));
-    tmp->a->boolean = true;
-
-    visit_type_UserDefUnion(data->ov, &tmp, NULL, &err);
-    g_assert(err == NULL);
-    arg = qmp_output_get_qobject(data->qov);
-
-    g_assert(qobject_type(arg) == QTYPE_QDICT);
-    qdict = qobject_to_qdict(arg);
-
-    g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a");
-
-    qvalue = qdict_get(qdict, "data");
-    g_assert(data != NULL);
-    g_assert(qobject_type(qvalue) == QTYPE_QDICT);
-    value = qobject_to_qdict(qvalue);
-    g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true);
-
-    qapi_free_UserDefUnion(tmp);
-    QDECREF(qdict);
-}
-
-static void output_visitor_test_add(const char *testpath,
-                                    TestOutputVisitorData *data,
-                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
-               test_func, visitor_output_teardown);
-}
-
-int main(int argc, char **argv)
-{
-    TestOutputVisitorData out_visitor_data;
-
-    g_test_init(&argc, &argv, NULL);
-
-    output_visitor_test_add("/visitor/output/int",
-                            &out_visitor_data, test_visitor_out_int);
-    output_visitor_test_add("/visitor/output/bool",
-                            &out_visitor_data, test_visitor_out_bool);
-    output_visitor_test_add("/visitor/output/number",
-                            &out_visitor_data, test_visitor_out_number);
-    output_visitor_test_add("/visitor/output/string",
-                            &out_visitor_data, test_visitor_out_string);
-    output_visitor_test_add("/visitor/output/no-string",
-                            &out_visitor_data, test_visitor_out_no_string);
-    output_visitor_test_add("/visitor/output/enum",
-                            &out_visitor_data, test_visitor_out_enum);
-    output_visitor_test_add("/visitor/output/enum-errors",
-                            &out_visitor_data, test_visitor_out_enum_errors);
-    output_visitor_test_add("/visitor/output/struct",
-                            &out_visitor_data, test_visitor_out_struct);
-    output_visitor_test_add("/visitor/output/struct-nested",
-                            &out_visitor_data, test_visitor_out_struct_nested);
-    output_visitor_test_add("/visitor/output/struct-errors",
-                            &out_visitor_data, test_visitor_out_struct_errors);
-    output_visitor_test_add("/visitor/output/list",
-                            &out_visitor_data, test_visitor_out_list);
-    output_visitor_test_add("/visitor/output/list-qapi-free",
-                            &out_visitor_data, test_visitor_out_list_qapi_free);
-    output_visitor_test_add("/visitor/output/union",
-                            &out_visitor_data, test_visitor_out_union);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-string-input-visitor.c b/test-string-input-visitor.c
deleted file mode 100644 (file)
index 5370e32..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * String Input Visitor unit-tests.
- *
- * Copyright (C) 2012 Red Hat Inc.
- *
- * Authors:
- *  Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-input-visitor)
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-#include <stdarg.h>
-
-#include "qapi/string-input-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestInputVisitorData {
-    StringInputVisitor *siv;
-} TestInputVisitorData;
-
-static void visitor_input_teardown(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    if (data->siv) {
-        string_input_visitor_cleanup(data->siv);
-        data->siv = NULL;
-    }
-}
-
-/* This is provided instead of a test setup function so that the JSON
-   string used by the tests are kept in the test functions (and not
-   int main()) */
-static
-Visitor *visitor_input_test_init(TestInputVisitorData *data,
-                                 const char *string)
-{
-    Visitor *v;
-
-    data->siv = string_input_visitor_new(string);
-    g_assert(data->siv != NULL);
-
-    v = string_input_get_visitor(data->siv);
-    g_assert(v != NULL);
-
-    return v;
-}
-
-static void test_visitor_in_int(TestInputVisitorData *data,
-                                const void *unused)
-{
-    int64_t res = 0, value = -42;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "-42");
-
-    visit_type_int(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, value);
-}
-
-static void test_visitor_in_bool(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    Error *errp = NULL;
-    bool res = false;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "true");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, true);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "yes");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, true);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "on");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, true);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "false");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, false);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "no");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, false);
-    visitor_input_teardown(data, unused);
-
-    v = visitor_input_test_init(data, "off");
-
-    visit_type_bool(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpint(res, ==, false);
-}
-
-static void test_visitor_in_number(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    double res = 0, value = 3.14;
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, "3.14");
-
-    visit_type_number(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpfloat(res, ==, value);
-}
-
-static void test_visitor_in_string(TestInputVisitorData *data,
-                                   const void *unused)
-{
-    char *res = NULL, *value = (char *) "Q E M U";
-    Error *errp = NULL;
-    Visitor *v;
-
-    v = visitor_input_test_init(data, value);
-
-    visit_type_str(v, &res, NULL, &errp);
-    g_assert(!error_is_set(&errp));
-    g_assert_cmpstr(res, ==, value);
-
-    g_free(res);
-}
-
-static void test_visitor_in_enum(TestInputVisitorData *data,
-                                 const void *unused)
-{
-    Error *errp = NULL;
-    Visitor *v;
-    EnumOne i;
-
-    for (i = 0; EnumOne_lookup[i]; i++) {
-        EnumOne res = -1;
-
-        v = visitor_input_test_init(data, EnumOne_lookup[i]);
-
-        visit_type_EnumOne(v, &res, NULL, &errp);
-        g_assert(!error_is_set(&errp));
-        g_assert_cmpint(i, ==, res);
-
-        visitor_input_teardown(data, NULL);
-    }
-
-    data->siv = NULL;
-}
-
-static void input_visitor_test_add(const char *testpath,
-                                   TestInputVisitorData *data,
-                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
-               visitor_input_teardown);
-}
-
-int main(int argc, char **argv)
-{
-    TestInputVisitorData in_visitor_data;
-
-    g_test_init(&argc, &argv, NULL);
-
-    input_visitor_test_add("/string-visitor/input/int",
-                           &in_visitor_data, test_visitor_in_int);
-    input_visitor_test_add("/string-visitor/input/bool",
-                           &in_visitor_data, test_visitor_in_bool);
-    input_visitor_test_add("/string-visitor/input/number",
-                           &in_visitor_data, test_visitor_in_number);
-    input_visitor_test_add("/string-visitor/input/string",
-                            &in_visitor_data, test_visitor_in_string);
-    input_visitor_test_add("/string-visitor/input/enum",
-                            &in_visitor_data, test_visitor_in_enum);
-
-    g_test_run();
-
-    return 0;
-}
diff --git a/test-string-output-visitor.c b/test-string-output-visitor.c
deleted file mode 100644 (file)
index 22909b8..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * String Output Visitor unit-tests.
- *
- * Copyright (C) 2012 Red Hat Inc.
- *
- * Authors:
- *  Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-output-visitor)
- *
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
- * See the COPYING file in the top-level directory.
- */
-
-#include <glib.h>
-
-#include "qapi/string-output-visitor.h"
-#include "test-qapi-types.h"
-#include "test-qapi-visit.h"
-#include "qemu-objects.h"
-
-typedef struct TestOutputVisitorData {
-    StringOutputVisitor *sov;
-    Visitor *ov;
-} TestOutputVisitorData;
-
-static void visitor_output_setup(TestOutputVisitorData *data,
-                                 const void *unused)
-{
-    data->sov = string_output_visitor_new();
-    g_assert(data->sov != NULL);
-
-    data->ov = string_output_get_visitor(data->sov);
-    g_assert(data->ov != NULL);
-}
-
-static void visitor_output_teardown(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    string_output_visitor_cleanup(data->sov);
-    data->sov = NULL;
-    data->ov = NULL;
-}
-
-static void test_visitor_out_int(TestOutputVisitorData *data,
-                                 const void *unused)
-{
-    int64_t value = -42;
-    Error *errp = NULL;
-    char *str;
-
-    visit_type_int(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, "-42");
-    g_free(str);
-}
-
-static void test_visitor_out_bool(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    Error *errp = NULL;
-    bool value = true;
-    char *str;
-
-    visit_type_bool(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, "true");
-    g_free(str);
-}
-
-static void test_visitor_out_number(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    double value = 3.14;
-    Error *errp = NULL;
-    char *str;
-
-    visit_type_number(data->ov, &value, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, "3.14");
-    g_free(str);
-}
-
-static void test_visitor_out_string(TestOutputVisitorData *data,
-                                    const void *unused)
-{
-    char *string = (char *) "Q E M U";
-    Error *errp = NULL;
-    char *str;
-
-    visit_type_str(data->ov, &string, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, string);
-    g_free(str);
-}
-
-static void test_visitor_out_no_string(TestOutputVisitorData *data,
-                                       const void *unused)
-{
-    char *string = NULL;
-    Error *errp = NULL;
-    char *str;
-
-    /* A null string should return "" */
-    visit_type_str(data->ov, &string, NULL, &errp);
-    g_assert(error_is_set(&errp) == 0);
-
-    str = string_output_get_string(data->sov);
-    g_assert(str != NULL);
-    g_assert_cmpstr(str, ==, "");
-    g_free(str);
-}
-
-static void test_visitor_out_enum(TestOutputVisitorData *data,
-                                  const void *unused)
-{
-    Error *errp = NULL;
-    char *str;
-    EnumOne i;
-
-    for (i = 0; i < ENUM_ONE_MAX; i++) {
-        visit_type_EnumOne(data->ov, &i, "unused", &errp);
-        g_assert(!error_is_set(&errp));
-
-        str = string_output_get_string(data->sov);
-        g_assert(str != NULL);
-        g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
-       g_free(str);
-    }
-}
-
-static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
-                                         const void *unused)
-{
-    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
-    Error *errp;
-
-    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
-        errp = NULL;
-        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
-        g_assert(error_is_set(&errp) == true);
-        error_free(errp);
-    }
-}
-
-static void output_visitor_test_add(const char *testpath,
-                                    TestOutputVisitorData *data,
-                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
-{
-    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
-               test_func, visitor_output_teardown);
-}
-
-int main(int argc, char **argv)
-{
-    TestOutputVisitorData out_visitor_data;
-
-    g_test_init(&argc, &argv, NULL);
-
-    output_visitor_test_add("/string-visitor/output/int",
-                            &out_visitor_data, test_visitor_out_int);
-    output_visitor_test_add("/string-visitor/output/bool",
-                            &out_visitor_data, test_visitor_out_bool);
-    output_visitor_test_add("/string-visitor/output/number",
-                            &out_visitor_data, test_visitor_out_number);
-    output_visitor_test_add("/string-visitor/output/string",
-                            &out_visitor_data, test_visitor_out_string);
-    output_visitor_test_add("/string-visitor/output/no-string",
-                            &out_visitor_data, test_visitor_out_no_string);
-    output_visitor_test_add("/string-visitor/output/enum",
-                            &out_visitor_data, test_visitor_out_enum);
-    output_visitor_test_add("/string-visitor/output/enum-errors",
-                            &out_visitor_data, test_visitor_out_enum_errors);
-
-    g_test_run();
-
-    return 0;
-}
index 2a2fff7c6d6fffc7dd4c8e78cd7a08dac1106d7d..17f6eced0d340e6802f1fee70ca54ed133960d0a 100644 (file)
 export SRC_PATH
 
-CHECKS = check-qdict check-qfloat check-qint check-qstring check-qlist
-CHECKS += check-qjson test-qmp-output-visitor test-qmp-input-visitor
-CHECKS += test-string-input-visitor test-string-output-visitor test-coroutine
-CHECKS += test-qmp-commands
-CHECKS += $(SRC_PATH)/tests/qemu-iotests-quick.sh
-
-check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
-
-check-qint: check-qint.o qint.o $(tools-obj-y)
-check-qstring: check-qstring.o qstring.o $(tools-obj-y)
-check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(tools-obj-y)
-check-qlist: check-qlist.o qlist.o qint.o $(tools-obj-y)
-check-qfloat: check-qfloat.o qfloat.o $(tools-obj-y)
-check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
-test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
-
-test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-input-strict.o \
-test-string-input-visitor.o test-string-output-visitor.o \
-       test-qmp-commands.o: QEMU_CFLAGS += -I $(qapi-dir)
-
-$(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
+check-unit-y = tests/check-qdict$(EXESUF)
+check-unit-y += tests/check-qfloat$(EXESUF)
+check-unit-y += tests/check-qint$(EXESUF)
+check-unit-y += tests/check-qstring$(EXESUF)
+check-unit-y += tests/check-qlist$(EXESUF)
+check-unit-y += tests/check-qjson$(EXESUF)
+check-unit-y += tests/test-qmp-output-visitor$(EXESUF)
+check-unit-y += tests/test-qmp-input-visitor$(EXESUF)
+check-unit-y += tests/test-qmp-input-strict$(EXESUF)
+check-unit-y += tests/test-qmp-commands$(EXESUF)
+check-unit-y += tests/test-string-input-visitor$(EXESUF)
+check-unit-y += tests/test-string-output-visitor$(EXESUF)
+check-unit-y += tests/test-coroutine$(EXESUF)
+
+check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
+
+GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
+
+test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
+       tests/check-qlist.o tests/check-qfloat.o tests/check-qjson.o \
+       tests/test-coroutine.o tests/test-string-output-visitor.o \
+       tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
+       tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
+       tests/test-qmp-commands.o
+
+test-qapi-obj-y =  $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y)
+test-qapi-obj-y += tests/test-qapi-visit.o tests/test-qapi-types.o
+test-qapi-obj-y += module.o
+
+$(test-obj-y): $(GENERATED_HEADERS)
+$(test-obj-y): QEMU_INCLUDES += -Itests
+
+tests/check-qint$(EXESUF): tests/check-qint.o qint.o $(tools-obj-y)
+tests/check-qstring$(EXESUF): tests/check-qstring.o qstring.o $(tools-obj-y)
+tests/check-qdict$(EXESUF): tests/check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(tools-obj-y)
+tests/check-qlist$(EXESUF): tests/check-qlist.o qlist.o qint.o $(tools-obj-y)
+tests/check-qfloat$(EXESUF): tests/check-qfloat.o qfloat.o $(tools-obj-y)
+tests/check-qjson$(EXESUF): tests/check-qjson.o $(qobject-obj-y) $(tools-obj-y)
+tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(coroutine-obj-y) $(tools-obj-y)
+
+tests/test-qapi-types.c tests/test-qapi-types.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
-       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
-$(qapi-dir)/test-qapi-visit.c $(qapi-dir)/test-qapi-visit.h :\
+       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o tests -p "test-" < $<, "  GEN   $@")
+tests/test-qapi-visit.c tests/test-qapi-visit.h :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
-       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
-$(qapi-dir)/test-qmp-commands.h $(qapi-dir)/test-qmp-marshal.c :\
+       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o tests -p "test-" < $<, "  GEN   $@")
+tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
-           $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, "  GEN   $@")
+       $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o tests -p "test-" < $<, "  GEN   $@")
 
 
-test-string-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-string-output-visitor: test-string-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
+tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
+tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y)
+tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y)
+tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
+tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
 
-test-string-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-string-input-visitor: test-string-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+.PHONY: check-help
+check-help:
+       @echo "Regression testing targets:"
+       @echo
+       @echo " make check                Run all tests"
+       @echo " make check-unit           Run qobject tests"
+       @echo " make check-block          Run block tests"
+       @echo " make check-report.html    Generates an HTML test report"
+       @echo
+       @echo "Please note that HTML reports do not regenerate if the unit tests"
+       @echo "has not changed."
+       @echo
+       @echo "The variable SPEED can be set to control the gtester speed setting."
+       @echo "Default options are -k and (for make V=1) --verbose; they can be"
+       @echo "changed with variable GTESTER_OPTIONS."
 
-test-qmp-input-strict.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-qmp-input-strict: test-qmp-input-strict.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+.SECONDARY:
 
-test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+SPEED = quick
+GTESTER_OPTIONS = -k $(if $(V),--verbose,-q)
 
-test-qmp-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
-test-qmp-input-visitor: test-qmp-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+# gtester tests, possibly with verbose output
 
-test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
-test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
+.PHONY: $(patsubst %, check-%, $(check-unit-y))
+$(patsubst %, check-%, $(check-unit-y)): check-%: %
+       $(call quiet-command,gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
 
-$(SRC_PATH)/tests/qemu-iotests-quick.sh: qemu-img qemu-io
+# gtester tests with XML output
 
+check-report-unit.xml: $(check-unit-y)
+       $(call quiet-command,gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $^, "GTESTER $@")
 
-.PHONY: check check-block
+# Reports and overall runs
 
-check: $(CHECKS)
-       $(call quiet-command, gtester $(CHECKS), "  CHECK")
+check-report.xml: check-report-unit.xml
+       $(call quiet-command,$(SRC_PATH)/scripts/gtester-cat $^ > $@, "  GEN    $@")
 
-check-block:
-       $(call quiet-command, $(SHELL) $(SRC_PATH)/tests/check-block.sh , "  CHECK")
+check-report.html: check-report.xml
+       $(call quiet-command,gtester-report $< > $@, "  GEN    $@")
+
+
+# Other tests
+
+.PHONY: check-tests/qemu-iotests-quick.sh
+check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF)
+       $<
+
+# Consolidated targets
+
+.PHONY: check-unit check
+check-unit: $(patsubst %,check-%, $(check-unit-y))
+check-block: $(patsubst %,check-%, $(check-block-y))
+check: check-unit
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
new file mode 100644 (file)
index 0000000..fc0d276
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * QDict unit-tests.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include <glib.h>
+
+#include "qint.h"
+#include "qdict.h"
+#include "qstring.h"
+#include "qemu-common.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qdict_new_test(void)
+{
+    QDict *qdict;
+
+    qdict = qdict_new();
+    g_assert(qdict != NULL);
+    g_assert(qdict_size(qdict) == 0);
+    g_assert(qdict->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qdict)) == QTYPE_QDICT);
+
+    // destroy doesn't exit yet
+    g_free(qdict);
+}
+
+static void qdict_put_obj_test(void)
+{
+    QInt *qi;
+    QDict *qdict;
+    QDictEntry *ent;
+    const int num = 42;
+
+    qdict = qdict_new();
+
+    // key "" will have tdb hash 12345
+    qdict_put_obj(qdict, "", QOBJECT(qint_from_int(num)));
+
+    g_assert(qdict_size(qdict) == 1);
+    ent = QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]);
+    qi = qobject_to_qint(ent->value);
+    g_assert(qint_get_int(qi) == num);
+
+    // destroy doesn't exit yet
+    QDECREF(qi);
+    g_free(ent->key);
+    g_free(ent);
+    g_free(qdict);
+}
+
+static void qdict_destroy_simple_test(void)
+{
+    QDict *qdict;
+
+    qdict = qdict_new();
+    qdict_put_obj(qdict, "num", QOBJECT(qint_from_int(0)));
+    qdict_put_obj(qdict, "str", QOBJECT(qstring_from_str("foo")));
+
+    QDECREF(qdict);
+}
+
+static void qdict_get_test(void)
+{
+    QInt *qi;
+    QObject *obj;
+    const int value = -42;
+    const char *key = "test";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(value));
+
+    obj = qdict_get(tests_dict, key);
+    g_assert(obj != NULL);
+
+    qi = qobject_to_qint(obj);
+    g_assert(qint_get_int(qi) == value);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_int_test(void)
+{
+    int ret;
+    const int value = 100;
+    const char *key = "int";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(value));
+
+    ret = qdict_get_int(tests_dict, key);
+    g_assert(ret == value);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_try_int_test(void)
+{
+    int ret;
+    const int value = 100;
+    const char *key = "int";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(value));
+
+    ret = qdict_get_try_int(tests_dict, key, 0);
+    g_assert(ret == value);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_str_test(void)
+{
+    const char *p;
+    const char *key = "key";
+    const char *str = "string";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qstring_from_str(str));
+
+    p = qdict_get_str(tests_dict, key);
+    g_assert(p != NULL);
+    g_assert(strcmp(p, str) == 0);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_try_str_test(void)
+{
+    const char *p;
+    const char *key = "key";
+    const char *str = "string";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qstring_from_str(str));
+
+    p = qdict_get_try_str(tests_dict, key);
+    g_assert(p != NULL);
+    g_assert(strcmp(p, str) == 0);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_haskey_not_test(void)
+{
+    QDict *tests_dict = qdict_new();
+    g_assert(qdict_haskey(tests_dict, "test") == 0);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_haskey_test(void)
+{
+    const char *key = "test";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(0));
+    g_assert(qdict_haskey(tests_dict, key) == 1);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_del_test(void)
+{
+    const char *key = "key test";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qstring_from_str("foo"));
+    g_assert(qdict_size(tests_dict) == 1);
+
+    qdict_del(tests_dict, key);
+
+    g_assert(qdict_size(tests_dict) == 0);
+    g_assert(qdict_haskey(tests_dict, key) == 0);
+
+    QDECREF(tests_dict);
+}
+
+static void qobject_to_qdict_test(void)
+{
+    QDict *tests_dict = qdict_new();
+    g_assert(qobject_to_qdict(QOBJECT(tests_dict)) == tests_dict);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_iterapi_test(void)
+{
+    int count;
+    const QDictEntry *ent;
+    QDict *tests_dict = qdict_new();
+
+    g_assert(qdict_first(tests_dict) == NULL);
+
+    qdict_put(tests_dict, "key1", qint_from_int(1));
+    qdict_put(tests_dict, "key2", qint_from_int(2));
+    qdict_put(tests_dict, "key3", qint_from_int(3));
+
+    count = 0;
+    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
+        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
+        count++;
+    }
+
+    g_assert(count == qdict_size(tests_dict));
+
+    /* Do it again to test restarting */
+    count = 0;
+    for (ent = qdict_first(tests_dict); ent; ent = qdict_next(tests_dict, ent)){
+        g_assert(qdict_haskey(tests_dict, qdict_entry_key(ent)) == 1);
+        count++;
+    }
+
+    g_assert(count == qdict_size(tests_dict));
+
+    QDECREF(tests_dict);
+}
+
+/*
+ * Errors test-cases
+ */
+
+static void qdict_put_exists_test(void)
+{
+    int value;
+    const char *key = "exists";
+    QDict *tests_dict = qdict_new();
+
+    qdict_put(tests_dict, key, qint_from_int(1));
+    qdict_put(tests_dict, key, qint_from_int(2));
+
+    value = qdict_get_int(tests_dict, key);
+    g_assert(value == 2);
+
+    g_assert(qdict_size(tests_dict) == 1);
+
+    QDECREF(tests_dict);
+}
+
+static void qdict_get_not_exists_test(void)
+{
+    QDict *tests_dict = qdict_new();
+    g_assert(qdict_get(tests_dict, "foo") == NULL);
+
+    QDECREF(tests_dict);
+}
+
+/*
+ * Stress test-case
+ *
+ * This is a lot big for a unit-test, but there is no other place
+ * to have it.
+ */
+
+static void remove_dots(char *string)
+{
+    char *p = strchr(string, ':');
+    if (p)
+        *p = '\0';
+}
+
+static QString *read_line(FILE *file, char *key)
+{
+    char value[128];
+
+    if (fscanf(file, "%127s%127s", key, value) == EOF) {
+        return NULL;
+    }
+    remove_dots(key);
+    return qstring_from_str(value);
+}
+
+#define reset_file(file)    fseek(file, 0L, SEEK_SET)
+
+static void qdict_stress_test(void)
+{
+    size_t lines;
+    char key[128];
+    FILE *test_file;
+    QDict *qdict;
+    QString *value;
+    const char *test_file_path = "qdict-test-data.txt";
+
+    test_file = fopen(test_file_path, "r");
+    g_assert(test_file != NULL);
+
+    // Create the dict
+    qdict = qdict_new();
+    g_assert(qdict != NULL);
+
+    // Add everything from the test file
+    for (lines = 0;; lines++) {
+        value = read_line(test_file, key);
+        if (!value)
+            break;
+
+        qdict_put(qdict, key, value);
+    }
+    g_assert(qdict_size(qdict) == lines);
+
+    // Check if everything is really in there
+    reset_file(test_file);
+    for (;;) {
+        const char *str1, *str2;
+
+        value = read_line(test_file, key);
+        if (!value)
+            break;
+
+        str1 = qstring_get_str(value);
+
+        str2 = qdict_get_str(qdict, key);
+        g_assert(str2 != NULL);
+
+        g_assert(strcmp(str1, str2) == 0);
+
+        QDECREF(value);
+    }
+
+    // Delete everything
+    reset_file(test_file);
+    for (;;) {
+        value = read_line(test_file, key);
+        if (!value)
+            break;
+
+        qdict_del(qdict, key);
+        QDECREF(value);
+
+        g_assert(qdict_haskey(qdict, key) == 0);
+    }
+    fclose(test_file);
+
+    g_assert(qdict_size(qdict) == 0);
+    QDECREF(qdict);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/new", qdict_new_test);
+    g_test_add_func("/public/put_obj", qdict_put_obj_test);
+    g_test_add_func("/public/destroy_simple", qdict_destroy_simple_test);
+
+    /* Continue, but now with fixtures */
+    g_test_add_func("/public/get", qdict_get_test);
+    g_test_add_func("/public/get_int", qdict_get_int_test);
+    g_test_add_func("/public/get_try_int", qdict_get_try_int_test);
+    g_test_add_func("/public/get_str", qdict_get_str_test);
+    g_test_add_func("/public/get_try_str", qdict_get_try_str_test);
+    g_test_add_func("/public/haskey_not", qdict_haskey_not_test);
+    g_test_add_func("/public/haskey", qdict_haskey_test);
+    g_test_add_func("/public/del", qdict_del_test);
+    g_test_add_func("/public/to_qdict", qobject_to_qdict_test);
+    g_test_add_func("/public/iterapi", qdict_iterapi_test);
+
+    g_test_add_func("/errors/put_exists", qdict_put_exists_test);
+    g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
+
+    /* The Big one */
+    if (g_test_slow()) {
+        g_test_add_func("/stress/test", qdict_stress_test);
+    }
+
+    return g_test_run();
+}
diff --git a/tests/check-qfloat.c b/tests/check-qfloat.c
new file mode 100644 (file)
index 0000000..cdc66ea
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * QFloat unit-tests.
+ *
+ * Copyright IBM, Corp. 2009
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#include <glib.h>
+
+#include "qfloat.h"
+#include "qemu-common.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qfloat_from_double_test(void)
+{
+    QFloat *qf;
+    const double value = -42.23423;
+
+    qf = qfloat_from_double(value);
+    g_assert(qf != NULL);
+    g_assert(qf->value == value);
+    g_assert(qf->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qf)) == QTYPE_QFLOAT);
+
+    // destroy doesn't exit yet
+    g_free(qf);
+}
+
+static void qfloat_destroy_test(void)
+{
+    QFloat *qf = qfloat_from_double(0.0);
+    QDECREF(qf);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/from_double", qfloat_from_double_test);
+    g_test_add_func("/public/destroy", qfloat_destroy_test);
+
+    return g_test_run();
+}
diff --git a/tests/check-qint.c b/tests/check-qint.c
new file mode 100644 (file)
index 0000000..5a27119
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * QInt unit-tests.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include <glib.h>
+
+#include "qint.h"
+#include "qemu-common.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qint_from_int_test(void)
+{
+    QInt *qi;
+    const int value = -42;
+
+    qi = qint_from_int(value);
+    g_assert(qi != NULL);
+    g_assert(qi->value == value);
+    g_assert(qi->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qi)) == QTYPE_QINT);
+
+    // destroy doesn't exit yet
+    g_free(qi);
+}
+
+static void qint_destroy_test(void)
+{
+    QInt *qi = qint_from_int(0);
+    QDECREF(qi);
+}
+
+static void qint_from_int64_test(void)
+{
+    QInt *qi;
+    const int64_t value = 0x1234567890abcdefLL;
+
+    qi = qint_from_int(value);
+    g_assert((int64_t) qi->value == value);
+
+    QDECREF(qi);
+}
+
+static void qint_get_int_test(void)
+{
+    QInt *qi;
+    const int value = 123456;
+
+    qi = qint_from_int(value);
+    g_assert(qint_get_int(qi) == value);
+
+    QDECREF(qi);
+}
+
+static void qobject_to_qint_test(void)
+{
+    QInt *qi;
+
+    qi = qint_from_int(0);
+    g_assert(qobject_to_qint(QOBJECT(qi)) == qi);
+
+    QDECREF(qi);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/from_int", qint_from_int_test);
+    g_test_add_func("/public/destroy", qint_destroy_test);
+    g_test_add_func("/public/from_int64", qint_from_int64_test);
+    g_test_add_func("/public/get_int", qint_get_int_test);
+    g_test_add_func("/public/to_qint", qobject_to_qint_test);
+
+    return g_test_run();
+}
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
new file mode 100644 (file)
index 0000000..526e25e
--- /dev/null
@@ -0,0 +1,728 @@
+/*
+ * Copyright IBM, Corp. 2009
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#include <glib.h>
+
+#include "qstring.h"
+#include "qint.h"
+#include "qdict.h"
+#include "qlist.h"
+#include "qfloat.h"
+#include "qbool.h"
+#include "qjson.h"
+
+#include "qemu-common.h"
+
+static void escaped_string(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        const char *decoded;
+        int skip;
+    } test_cases[] = {
+        { "\"\\b\"", "\b" },
+        { "\"\\f\"", "\f" },
+        { "\"\\n\"", "\n" },
+        { "\"\\r\"", "\r" },
+        { "\"\\t\"", "\t" },
+        { "\"/\"", "/" },
+        { "\"\\/\"", "/", .skip = 1 },
+        { "\"\\\\\"", "\\" },
+        { "\"\\\"\"", "\"" },
+        { "\"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  ", .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" },
+        {}
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        
+        str = qobject_to_qstring(obj);
+        g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].decoded);
+
+        if (test_cases[i].skip == 0) {
+            str = qobject_to_json(obj);
+            g_assert_cmpstr(qstring_get_str(str), ==, test_cases[i].encoded);
+            qobject_decref(obj);
+        }
+
+        QDECREF(str);
+    }
+}
+
+static void simple_string(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        const char *decoded;
+    } test_cases[] = {
+        { "\"hello world\"", "hello world" },
+        { "\"the quick brown fox jumped over the fence\"",
+          "the quick brown fox jumped over the fence" },
+        {}
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        
+        str = qobject_to_qstring(obj);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+
+        str = qobject_to_json(obj);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+
+        qobject_decref(obj);
+        
+        QDECREF(str);
+    }
+}
+
+static void single_quote_string(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        const char *decoded;
+    } test_cases[] = {
+        { "'hello world'", "hello world" },
+        { "'the quick brown fox \\' jumped over the fence'",
+          "the quick brown fox ' jumped over the fence" },
+        {}
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        
+        str = qobject_to_qstring(obj);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+
+        QDECREF(str);
+    }
+}
+
+static void vararg_string(void)
+{
+    int i;
+    struct {
+        const char *decoded;
+    } test_cases[] = {
+        { "hello world" },
+        { "the quick brown fox jumped over the fence" },
+        {}
+    };
+
+    for (i = 0; test_cases[i].decoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_jsonf("%s", test_cases[i].decoded);
+
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        
+        str = qobject_to_qstring(obj);
+        g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+
+        QDECREF(str);
+    }
+}
+
+static void simple_number(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        int64_t decoded;
+        int skip;
+    } test_cases[] = {
+        { "0", 0 },
+        { "1234", 1234 },
+        { "1", 1 },
+        { "-32", -32 },
+        { "-0", 0, .skip = 1 },
+        { },
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QInt *qint;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QINT);
+
+        qint = qobject_to_qint(obj);
+        g_assert(qint_get_int(qint) == test_cases[i].decoded);
+        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);
+            QDECREF(str);
+        }
+
+        QDECREF(qint);
+    }
+}
+
+static void float_number(void)
+{
+    int i;
+    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, .skip = 1 },
+        { },
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QFloat *qfloat;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QFLOAT);
+
+        qfloat = qobject_to_qfloat(obj);
+        g_assert(qfloat_get_double(qfloat) == test_cases[i].decoded);
+
+        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);
+            QDECREF(str);
+        }
+
+        QDECREF(qfloat);
+    }
+}
+
+static void vararg_number(void)
+{
+    QObject *obj;
+    QInt *qint;
+    QFloat *qfloat;
+    int value = 0x2342;
+    int64_t value64 = 0x2342342343LL;
+    double valuef = 2.323423423;
+
+    obj = qobject_from_jsonf("%d", value);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
+
+    qint = qobject_to_qint(obj);
+    g_assert(qint_get_int(qint) == value);
+
+    QDECREF(qint);
+
+    obj = qobject_from_jsonf("%" PRId64, value64);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
+
+    qint = qobject_to_qint(obj);
+    g_assert(qint_get_int(qint) == value64);
+
+    QDECREF(qint);
+
+    obj = qobject_from_jsonf("%f", valuef);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
+
+    qfloat = qobject_to_qfloat(obj);
+    g_assert(qfloat_get_double(qfloat) == valuef);
+
+    QDECREF(qfloat);
+}
+
+static void keyword_literal(void)
+{
+    QObject *obj;
+    QBool *qbool;
+    QString *str;
+
+    obj = qobject_from_json("true");
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+
+    qbool = qobject_to_qbool(obj);
+    g_assert(qbool_get_int(qbool) != 0);
+
+    str = qobject_to_json(obj);
+    g_assert(strcmp(qstring_get_str(str), "true") == 0);
+    QDECREF(str);
+
+    QDECREF(qbool);
+
+    obj = qobject_from_json("false");
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+
+    qbool = qobject_to_qbool(obj);
+    g_assert(qbool_get_int(qbool) == 0);
+
+    str = qobject_to_json(obj);
+    g_assert(strcmp(qstring_get_str(str), "false") == 0);
+    QDECREF(str);
+
+    QDECREF(qbool);
+
+    obj = qobject_from_jsonf("%i", false);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+
+    qbool = qobject_to_qbool(obj);
+    g_assert(qbool_get_int(qbool) == 0);
+
+    QDECREF(qbool);
+    
+    obj = qobject_from_jsonf("%i", true);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+
+    qbool = qobject_to_qbool(obj);
+    g_assert(qbool_get_int(qbool) != 0);
+
+    QDECREF(qbool);
+}
+
+typedef struct LiteralQDictEntry LiteralQDictEntry;
+typedef struct LiteralQObject LiteralQObject;
+
+struct LiteralQObject
+{
+    int type;
+    union {
+        int64_t qint;
+        const char *qstr;
+        LiteralQDictEntry *qdict;
+        LiteralQObject *qlist;
+    } value;
+};
+
+struct LiteralQDictEntry
+{
+    const char *key;
+    LiteralQObject value;
+};
+
+#define QLIT_QINT(val) (LiteralQObject){.type = QTYPE_QINT, .value.qint = (val)}
+#define QLIT_QSTR(val) (LiteralQObject){.type = QTYPE_QSTRING, .value.qstr = (val)}
+#define QLIT_QDICT(val) (LiteralQObject){.type = QTYPE_QDICT, .value.qdict = (val)}
+#define QLIT_QLIST(val) (LiteralQObject){.type = QTYPE_QLIST, .value.qlist = (val)}
+
+typedef struct QListCompareHelper
+{
+    int index;
+    LiteralQObject *objs;
+    int result;
+} QListCompareHelper;
+
+static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs);
+
+static void compare_helper(QObject *obj, void *opaque)
+{
+    QListCompareHelper *helper = opaque;
+
+    if (helper->result == 0) {
+        return;
+    }
+
+    if (helper->objs[helper->index].type == QTYPE_NONE) {
+        helper->result = 0;
+        return;
+    }
+
+    helper->result = compare_litqobj_to_qobj(&helper->objs[helper->index++], obj);
+}
+
+static int compare_litqobj_to_qobj(LiteralQObject *lhs, QObject *rhs)
+{
+    if (lhs->type != qobject_type(rhs)) {
+        return 0;
+    }
+
+    switch (lhs->type) {
+    case QTYPE_QINT:
+        return lhs->value.qint == qint_get_int(qobject_to_qint(rhs));
+    case QTYPE_QSTRING:
+        return (strcmp(lhs->value.qstr, qstring_get_str(qobject_to_qstring(rhs))) == 0);
+    case QTYPE_QDICT: {
+        int i;
+
+        for (i = 0; lhs->value.qdict[i].key; i++) {
+            QObject *obj = qdict_get(qobject_to_qdict(rhs), lhs->value.qdict[i].key);
+
+            if (!compare_litqobj_to_qobj(&lhs->value.qdict[i].value, obj)) {
+                return 0;
+            }
+        }
+
+        return 1;
+    }
+    case QTYPE_QLIST: {
+        QListCompareHelper helper;
+
+        helper.index = 0;
+        helper.objs = lhs->value.qlist;
+        helper.result = 1;
+        
+        qlist_iter(qobject_to_qlist(rhs), compare_helper, &helper);
+
+        return helper.result;
+    }
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+static void simple_dict(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        LiteralQObject decoded;
+    } test_cases[] = {
+        {
+            .encoded = "{\"foo\": 42, \"bar\": \"hello world\"}",
+            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+                        { "foo", QLIT_QINT(42) },
+                        { "bar", QLIT_QSTR("hello world") },
+                        { }
+                    })),
+        }, {
+            .encoded = "{}",
+            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+                        { }
+                    })),
+        }, {
+            .encoded = "{\"foo\": 43}",
+            .decoded = QLIT_QDICT(((LiteralQDictEntry[]){
+                        { "foo", QLIT_QINT(43) },
+                        { }
+                    })),
+        },
+        { }
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+        g_assert(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));
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        qobject_decref(obj);
+        QDECREF(str);
+    }
+}
+
+static void simple_list(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        LiteralQObject decoded;
+    } test_cases[] = {
+        {
+            .encoded = "[43,42]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        QLIT_QINT(42),
+                        { }
+                    })),
+        },
+        {
+            .encoded = "[43]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        { }
+                    })),
+        },
+        {
+            .encoded = "[]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        { }
+                    })),
+        },
+        {
+            .encoded = "[{}]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QDICT(((LiteralQDictEntry[]){
+                                    {},
+                                        })),
+                        {},
+                            })),
+        },
+        { }
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+        g_assert(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));
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+        qobject_decref(obj);
+        QDECREF(str);
+    }
+}
+
+static void simple_whitespace(void)
+{
+    int i;
+    struct {
+        const char *encoded;
+        LiteralQObject decoded;
+    } test_cases[] = {
+        {
+            .encoded = " [ 43 , 42 ]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        QLIT_QINT(42),
+                        { }
+                    })),
+        },
+        {
+            .encoded = " [ 43 , { 'h' : 'b' }, [ ], 42 ]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        QLIT_QDICT(((LiteralQDictEntry[]){
+                                    { "h", QLIT_QSTR("b") },
+                                    { }})),
+                        QLIT_QLIST(((LiteralQObject[]){
+                                    { }})),
+                        QLIT_QINT(42),
+                        { }
+                    })),
+        },
+        {
+            .encoded = " [ 43 , { 'h' : 'b' , 'a' : 32 }, [ ], 42 ]",
+            .decoded = QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(43),
+                        QLIT_QDICT(((LiteralQDictEntry[]){
+                                    { "h", QLIT_QSTR("b") },
+                                    { "a", QLIT_QINT(32) },
+                                    { }})),
+                        QLIT_QLIST(((LiteralQObject[]){
+                                    { }})),
+                        QLIT_QINT(42),
+                        { }
+                    })),
+        },
+        { }
+    };
+
+    for (i = 0; test_cases[i].encoded; i++) {
+        QObject *obj;
+        QString *str;
+
+        obj = qobject_from_json(test_cases[i].encoded);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+        g_assert(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));
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+        g_assert(compare_litqobj_to_qobj(&test_cases[i].decoded, obj) == 1);
+
+        qobject_decref(obj);
+        QDECREF(str);
+    }
+}
+
+static void simple_varargs(void)
+{
+    QObject *embedded_obj;
+    QObject *obj;
+    LiteralQObject decoded = QLIT_QLIST(((LiteralQObject[]){
+            QLIT_QINT(1),
+            QLIT_QINT(2),
+            QLIT_QLIST(((LiteralQObject[]){
+                        QLIT_QINT(32),
+                        QLIT_QINT(42),
+                        {}})),
+            {}}));
+
+    embedded_obj = qobject_from_json("[32, 42]");
+    g_assert(embedded_obj != NULL);
+
+    obj = qobject_from_jsonf("[%d, 2, %p]", 1, embedded_obj);
+    g_assert(obj != NULL);
+
+    g_assert(compare_litqobj_to_qobj(&decoded, obj) == 1);
+
+    qobject_decref(obj);
+}
+
+static void empty_input(void)
+{
+    const char *empty = "";
+
+    QObject *obj = qobject_from_json(empty);
+    g_assert(obj == NULL);
+}
+
+static void unterminated_string(void)
+{
+    QObject *obj = qobject_from_json("\"abc");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_sq_string(void)
+{
+    QObject *obj = qobject_from_json("'abc");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_escape(void)
+{
+    QObject *obj = qobject_from_json("\"abc\\\"");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_array(void)
+{
+    QObject *obj = qobject_from_json("[32");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_array_comma(void)
+{
+    QObject *obj = qobject_from_json("[32,");
+    g_assert(obj == NULL);
+}
+
+static void invalid_array_comma(void)
+{
+    QObject *obj = qobject_from_json("[32,}");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_dict(void)
+{
+    QObject *obj = qobject_from_json("{'abc':32");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_dict_comma(void)
+{
+    QObject *obj = qobject_from_json("{'abc':32,");
+    g_assert(obj == NULL);
+}
+
+static void invalid_dict_comma(void)
+{
+    QObject *obj = qobject_from_json("{'abc':32,}");
+    g_assert(obj == NULL);
+}
+
+static void unterminated_literal(void)
+{
+    QObject *obj = qobject_from_json("nul");
+    g_assert(obj == NULL);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/literals/string/simple", simple_string);
+    g_test_add_func("/literals/string/escaped", escaped_string);
+    g_test_add_func("/literals/string/single_quote", single_quote_string);
+    g_test_add_func("/literals/string/vararg", vararg_string);
+
+    g_test_add_func("/literals/number/simple", simple_number);
+    g_test_add_func("/literals/number/float", float_number);
+    g_test_add_func("/literals/number/vararg", vararg_number);
+
+    g_test_add_func("/literals/keyword", keyword_literal);
+
+    g_test_add_func("/dicts/simple_dict", simple_dict);
+    g_test_add_func("/lists/simple_list", simple_list);
+
+    g_test_add_func("/whitespace/simple_whitespace", simple_whitespace);
+
+    g_test_add_func("/varargs/simple_varargs", simple_varargs);
+
+    g_test_add_func("/errors/empty_input", empty_input);
+    g_test_add_func("/errors/unterminated/string", unterminated_string);
+    g_test_add_func("/errors/unterminated/escape", unterminated_escape);
+    g_test_add_func("/errors/unterminated/sq_string", unterminated_sq_string);
+    g_test_add_func("/errors/unterminated/array", unterminated_array);
+    g_test_add_func("/errors/unterminated/array_comma", unterminated_array_comma);
+    g_test_add_func("/errors/unterminated/dict", unterminated_dict);
+    g_test_add_func("/errors/unterminated/dict_comma", unterminated_dict_comma);
+    g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
+    g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
+    g_test_add_func("/errors/unterminated/literal", unterminated_literal);
+
+    return g_test_run();
+}
diff --git a/tests/check-qlist.c b/tests/check-qlist.c
new file mode 100644 (file)
index 0000000..501ba26
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * QList unit-tests.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include <glib.h>
+
+#include "qint.h"
+#include "qlist.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qlist_new_test(void)
+{
+    QList *qlist;
+
+    qlist = qlist_new();
+    g_assert(qlist != NULL);
+    g_assert(qlist->base.refcnt == 1);
+    g_assert(qobject_type(QOBJECT(qlist)) == QTYPE_QLIST);
+
+    // destroy doesn't exist yet
+    g_free(qlist);
+}
+
+static void qlist_append_test(void)
+{
+    QInt *qi;
+    QList *qlist;
+    QListEntry *entry;
+
+    qi = qint_from_int(42);
+
+    qlist = qlist_new();
+    qlist_append(qlist, qi);
+
+    entry = QTAILQ_FIRST(&qlist->head);
+    g_assert(entry != NULL);
+    g_assert(entry->value == QOBJECT(qi));
+
+    // destroy doesn't exist yet
+    QDECREF(qi);
+    g_free(entry);
+    g_free(qlist);
+}
+
+static void qobject_to_qlist_test(void)
+{
+    QList *qlist;
+
+    qlist = qlist_new();
+
+    g_assert(qobject_to_qlist(QOBJECT(qlist)) == qlist);
+
+    // destroy doesn't exist yet
+    g_free(qlist);
+}
+
+static void qlist_destroy_test(void)
+{
+    int i;
+    QList *qlist;
+
+    qlist = qlist_new();
+
+    for (i = 0; i < 42; i++)
+        qlist_append(qlist, qint_from_int(i));
+
+    QDECREF(qlist);
+}
+
+static int iter_called;
+static const int iter_max = 42;
+
+static void iter_func(QObject *obj, void *opaque)
+{
+    QInt *qi;
+
+    g_assert(opaque == NULL);
+
+    qi = qobject_to_qint(obj);
+    g_assert(qi != NULL);
+    g_assert((qint_get_int(qi) >= 0) && (qint_get_int(qi) <= iter_max));
+
+    iter_called++;
+}
+
+static void qlist_iter_test(void)
+{
+    int i;
+    QList *qlist;
+
+    qlist = qlist_new();
+
+    for (i = 0; i < iter_max; i++)
+        qlist_append(qlist, qint_from_int(i));
+
+    iter_called = 0;
+    qlist_iter(qlist, iter_func, NULL);
+
+    g_assert(iter_called == iter_max);
+
+    QDECREF(qlist);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/new", qlist_new_test);
+    g_test_add_func("/public/append", qlist_append_test);
+    g_test_add_func("/public/to_qlist", qobject_to_qlist_test);
+    g_test_add_func("/public/destroy", qlist_destroy_test);
+    g_test_add_func("/public/iter", qlist_iter_test);
+
+    return g_test_run();
+}
diff --git a/tests/check-qstring.c b/tests/check-qstring.c
new file mode 100644 (file)
index 0000000..addad6c
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * QString unit-tests.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+#include <glib.h>
+
+#include "qstring.h"
+#include "qemu-common.h"
+
+/*
+ * Public Interface test-cases
+ *
+ * (with some violations to access 'private' data)
+ */
+
+static void qstring_from_str_test(void)
+{
+    QString *qstring;
+    const char *str = "QEMU";
+
+    qstring = qstring_from_str(str);
+    g_assert(qstring != NULL);
+    g_assert(qstring->base.refcnt == 1);
+    g_assert(strcmp(str, qstring->string) == 0);
+    g_assert(qobject_type(QOBJECT(qstring)) == QTYPE_QSTRING);
+
+    // destroy doesn't exit yet
+    g_free(qstring->string);
+    g_free(qstring);
+}
+
+static void qstring_destroy_test(void)
+{
+    QString *qstring = qstring_from_str("destroy test");
+    QDECREF(qstring);
+}
+
+static void qstring_get_str_test(void)
+{
+    QString *qstring;
+    const char *ret_str;
+    const char *str = "QEMU/KVM";
+
+    qstring = qstring_from_str(str);
+    ret_str = qstring_get_str(qstring);
+    g_assert(strcmp(ret_str, str) == 0);
+
+    QDECREF(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);
+    QDECREF(qstring);
+}
+
+static void qstring_from_substr_test(void)
+{
+    QString *qs;
+
+    qs = qstring_from_substr("virtualization", 3, 9);
+    g_assert(qs != NULL);
+    g_assert(strcmp(qstring_get_str(qs), "tualiza") == 0);
+
+    QDECREF(qs);
+}
+
+
+static void qobject_to_qstring_test(void)
+{
+    QString *qstring;
+
+    qstring = qstring_from_str("foo");
+    g_assert(qobject_to_qstring(QOBJECT(qstring)) == qstring);
+
+    QDECREF(qstring);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/public/from_str", qstring_from_str_test);
+    g_test_add_func("/public/destroy", qstring_destroy_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);
+
+    return g_test_run();
+}
diff --git a/tests/test-coroutine.c b/tests/test-coroutine.c
new file mode 100644 (file)
index 0000000..e5d14eb
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Coroutine tests
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ *  Stefan Hajnoczi    <stefanha@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include <glib.h>
+#include "qemu-coroutine.h"
+
+/*
+ * Check that qemu_in_coroutine() works
+ */
+
+static void coroutine_fn verify_in_coroutine(void *opaque)
+{
+    g_assert(qemu_in_coroutine());
+}
+
+static void test_in_coroutine(void)
+{
+    Coroutine *coroutine;
+
+    g_assert(!qemu_in_coroutine());
+
+    coroutine = qemu_coroutine_create(verify_in_coroutine);
+    qemu_coroutine_enter(coroutine, NULL);
+}
+
+/*
+ * Check that qemu_coroutine_self() works
+ */
+
+static void coroutine_fn verify_self(void *opaque)
+{
+    g_assert(qemu_coroutine_self() == opaque);
+}
+
+static void test_self(void)
+{
+    Coroutine *coroutine;
+
+    coroutine = qemu_coroutine_create(verify_self);
+    qemu_coroutine_enter(coroutine, coroutine);
+}
+
+/*
+ * Check that coroutines may nest multiple levels
+ */
+
+typedef struct {
+    unsigned int n_enter;   /* num coroutines entered */
+    unsigned int n_return;  /* num coroutines returned */
+    unsigned int max;       /* maximum level of nesting */
+} NestData;
+
+static void coroutine_fn nest(void *opaque)
+{
+    NestData *nd = opaque;
+
+    nd->n_enter++;
+
+    if (nd->n_enter < nd->max) {
+        Coroutine *child;
+
+        child = qemu_coroutine_create(nest);
+        qemu_coroutine_enter(child, nd);
+    }
+
+    nd->n_return++;
+}
+
+static void test_nesting(void)
+{
+    Coroutine *root;
+    NestData nd = {
+        .n_enter  = 0,
+        .n_return = 0,
+        .max      = 128,
+    };
+
+    root = qemu_coroutine_create(nest);
+    qemu_coroutine_enter(root, &nd);
+
+    /* Must enter and return from max nesting level */
+    g_assert_cmpint(nd.n_enter, ==, nd.max);
+    g_assert_cmpint(nd.n_return, ==, nd.max);
+}
+
+/*
+ * Check that yield/enter transfer control correctly
+ */
+
+static void coroutine_fn yield_5_times(void *opaque)
+{
+    bool *done = opaque;
+    int i;
+
+    for (i = 0; i < 5; i++) {
+        qemu_coroutine_yield();
+    }
+    *done = true;
+}
+
+static void test_yield(void)
+{
+    Coroutine *coroutine;
+    bool done = false;
+    int i = -1; /* one extra time to return from coroutine */
+
+    coroutine = qemu_coroutine_create(yield_5_times);
+    while (!done) {
+        qemu_coroutine_enter(coroutine, &done);
+        i++;
+    }
+    g_assert_cmpint(i, ==, 5); /* coroutine must yield 5 times */
+}
+
+/*
+ * Check that creation, enter, and return work
+ */
+
+static void coroutine_fn set_and_exit(void *opaque)
+{
+    bool *done = opaque;
+
+    *done = true;
+}
+
+static void test_lifecycle(void)
+{
+    Coroutine *coroutine;
+    bool done = false;
+
+    /* Create, enter, and return from coroutine */
+    coroutine = qemu_coroutine_create(set_and_exit);
+    qemu_coroutine_enter(coroutine, &done);
+    g_assert(done); /* expect done to be true (first time) */
+
+    /* Repeat to check that no state affects this test */
+    done = false;
+    coroutine = qemu_coroutine_create(set_and_exit);
+    qemu_coroutine_enter(coroutine, &done);
+    g_assert(done); /* expect done to be true (second time) */
+}
+
+/*
+ * Lifecycle benchmark
+ */
+
+static void coroutine_fn empty_coroutine(void *opaque)
+{
+    /* Do nothing */
+}
+
+static void perf_lifecycle(void)
+{
+    Coroutine *coroutine;
+    unsigned int i, max;
+    double duration;
+
+    max = 1000000;
+
+    g_test_timer_start();
+    for (i = 0; i < max; i++) {
+        coroutine = qemu_coroutine_create(empty_coroutine);
+        qemu_coroutine_enter(coroutine, NULL);
+    }
+    duration = g_test_timer_elapsed();
+
+    g_test_message("Lifecycle %u iterations: %f s\n", max, duration);
+}
+
+static void perf_nesting(void)
+{
+    unsigned int i, maxcycles, maxnesting;
+    double duration;
+
+    maxcycles = 100000000;
+    maxnesting = 20000;
+    Coroutine *root;
+    NestData nd = {
+        .n_enter  = 0,
+        .n_return = 0,
+        .max      = maxnesting,
+    };
+
+    g_test_timer_start();
+    for (i = 0; i < maxcycles; i++) {
+        root = qemu_coroutine_create(nest);
+        qemu_coroutine_enter(root, &nd);
+    }
+    duration = g_test_timer_elapsed();
+
+    g_test_message("Nesting %u iterations of %u depth each: %f s\n",
+        maxcycles, maxnesting, duration);
+}
+
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+    g_test_add_func("/basic/lifecycle", test_lifecycle);
+    g_test_add_func("/basic/yield", test_yield);
+    g_test_add_func("/basic/nesting", test_nesting);
+    g_test_add_func("/basic/self", test_self);
+    g_test_add_func("/basic/in_coroutine", test_in_coroutine);
+    if (g_test_perf()) {
+        g_test_add_func("/perf/lifecycle", perf_lifecycle);
+        g_test_add_func("/perf/nesting", perf_nesting);
+    }
+    return g_test_run();
+}
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
new file mode 100644 (file)
index 0000000..60cbf01
--- /dev/null
@@ -0,0 +1,139 @@
+#include <glib.h>
+#include "qemu-objects.h"
+#include "test-qmp-commands.h"
+#include "qapi/qmp-core.h"
+#include "module.h"
+
+void qmp_user_def_cmd(Error **errp)
+{
+}
+
+void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
+{
+}
+
+UserDefTwo * qmp_user_def_cmd2(UserDefOne * ud1a, UserDefOne * ud1b, Error **errp)
+{
+    UserDefTwo *ret;
+    UserDefOne *ud1c = g_malloc0(sizeof(UserDefOne));
+    UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
+
+    ud1c->string = strdup(ud1a->string);
+    ud1c->integer = ud1a->integer;
+    ud1d->string = strdup(ud1b->string);
+    ud1d->integer = ud1b->integer;
+
+    ret = g_malloc0(sizeof(UserDefTwo));
+    ret->string = strdup("blah1");
+    ret->dict.string = strdup("blah2");
+    ret->dict.dict.userdef = ud1c;
+    ret->dict.dict.string = strdup("blah3");
+    ret->dict.has_dict2 = true;
+    ret->dict.dict2.userdef = ud1d;
+    ret->dict.dict2.string = strdup("blah4");
+
+    return ret;
+}
+
+/* test commands with no input and no return value */
+static void test_dispatch_cmd(void)
+{
+    QDict *req = qdict_new();
+    QObject *resp;
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd")));
+
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
+
+    qobject_decref(resp);
+    QDECREF(req);
+}
+
+/* test commands that return an error due to invalid parameters */
+static void test_dispatch_cmd_error(void)
+{
+    QDict *req = qdict_new();
+    QObject *resp;
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
+
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(qdict_haskey(qobject_to_qdict(resp), "error"));
+
+    qobject_decref(resp);
+    QDECREF(req);
+}
+
+/* test commands that involve both input parameters and return values */
+static void test_dispatch_cmd_io(void)
+{
+    QDict *req = qdict_new();
+    QDict *args = qdict_new();
+    QDict *ud1a = qdict_new();
+    QDict *ud1b = qdict_new();
+    QObject *resp;
+
+    qdict_put_obj(ud1a, "integer", QOBJECT(qint_from_int(42)));
+    qdict_put_obj(ud1a, "string", QOBJECT(qstring_from_str("hello")));
+    qdict_put_obj(ud1b, "integer", QOBJECT(qint_from_int(422)));
+    qdict_put_obj(ud1b, "string", QOBJECT(qstring_from_str("hello2")));
+    qdict_put_obj(args, "ud1a", QOBJECT(ud1a));
+    qdict_put_obj(args, "ud1b", QOBJECT(ud1b));
+    qdict_put_obj(req, "arguments", QOBJECT(args));
+
+    qdict_put_obj(req, "execute", QOBJECT(qstring_from_str("user_def_cmd2")));
+
+    /* TODO: put in full payload and check for errors */
+    resp = qmp_dispatch(QOBJECT(req));
+    assert(resp != NULL);
+    assert(!qdict_haskey(qobject_to_qdict(resp), "error"));
+
+    qobject_decref(resp);
+    QDECREF(req);
+}
+
+/* test generated dealloc functions for generated types */
+static void test_dealloc_types(void)
+{
+    UserDefOne *ud1test, *ud1a, *ud1b;
+    UserDefOneList *ud1list;
+
+    ud1test = g_malloc0(sizeof(UserDefOne));
+    ud1test->integer = 42;
+    ud1test->string = g_strdup("hi there 42");
+
+    qapi_free_UserDefOne(ud1test);
+
+    ud1a = g_malloc0(sizeof(UserDefOne));
+    ud1a->integer = 43;
+    ud1a->string = g_strdup("hi there 43");
+
+    ud1b = g_malloc0(sizeof(UserDefOne));
+    ud1b->integer = 44;
+    ud1b->string = g_strdup("hi there 44");
+
+    ud1list = g_malloc0(sizeof(UserDefOneList));
+    ud1list->value = ud1a;
+    ud1list->next = g_malloc0(sizeof(UserDefOneList));
+    ud1list->next->value = ud1b;
+
+    qapi_free_UserDefOneList(ud1list);
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd);
+    g_test_add_func("/0.15/dispatch_cmd_error", test_dispatch_cmd_error);
+    g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io);
+    g_test_add_func("/0.15/dealloc_types", test_dealloc_types);
+
+    module_call_init(MODULE_INIT_QAPI);
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c
new file mode 100644 (file)
index 0000000..f6df8cb
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * QMP Input Visitor unit-tests (strict mode).
+ *
+ * Copyright (C) 2011-2012 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *  Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/qmp-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    QObject *obj;
+    QmpInputVisitor *qiv;
+} TestInputVisitorData;
+
+static void validate_teardown(TestInputVisitorData *data,
+                               const void *unused)
+{
+    qobject_decref(data->obj);
+    data->obj = NULL;
+
+    if (data->qiv) {
+        qmp_input_visitor_cleanup(data->qiv);
+        data->qiv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static GCC_FMT_ATTR(2, 3)
+Visitor *validate_test_init(TestInputVisitorData *data,
+                             const char *json_string, ...)
+{
+    Visitor *v;
+    va_list ap;
+
+    va_start(ap, json_string);
+    data->obj = qobject_from_jsonv(json_string, &ap);
+    va_end(ap);
+
+    g_assert(data->obj != NULL);
+
+    data->qiv = qmp_input_visitor_new_strict(data->obj);
+    g_assert(data->qiv != NULL);
+
+    v = qmp_input_get_visitor(data->qiv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_validate_struct(TestInputVisitorData *data,
+                                  const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_free(p->string);
+    g_free(p);
+}
+
+static void test_validate_struct_nested(TestInputVisitorData *data,
+                                         const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefNested(udp);
+}
+
+static void test_validate_list(TestInputVisitorData *data,
+                                const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_validate_union(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    UserDefUnion *tmp = NULL;
+    Visitor *v;
+    Error *errp = NULL;
+
+    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void test_validate_fail_struct(TestInputVisitorData *data,
+                                       const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    if (p) {
+        g_free(p->string);
+    }
+    g_free(p);
+}
+
+static void test_validate_fail_struct_nested(TestInputVisitorData *data,
+                                              const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefNested(udp);
+}
+
+static void test_validate_fail_list(TestInputVisitorData *data,
+                                     const void *unused)
+{
+    UserDefOneList *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_validate_fail_union(TestInputVisitorData *data,
+                                      const void *unused)
+{
+    UserDefUnion *tmp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 }, 'extra': 'yyy' }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void validate_test_add(const char *testpath,
+                               TestInputVisitorData *data,
+                               void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               validate_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData testdata;
+
+    g_test_init(&argc, &argv, NULL);
+
+    validate_test_add("/visitor/input-strict/pass/struct",
+                       &testdata, test_validate_struct);
+    validate_test_add("/visitor/input-strict/pass/struct-nested",
+                       &testdata, test_validate_struct_nested);
+    validate_test_add("/visitor/input-strict/pass/list",
+                       &testdata, test_validate_list);
+    validate_test_add("/visitor/input-strict/pass/union",
+                       &testdata, test_validate_union);
+    validate_test_add("/visitor/input-strict/fail/struct",
+                       &testdata, test_validate_fail_struct);
+    validate_test_add("/visitor/input-strict/fail/struct-nested",
+                       &testdata, test_validate_fail_struct_nested);
+    validate_test_add("/visitor/input-strict/fail/list",
+                       &testdata, test_validate_fail_list);
+    validate_test_add("/visitor/input-strict/fail/union",
+                       &testdata, test_validate_fail_union);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
new file mode 100644 (file)
index 0000000..c30fdc4
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * QMP Input Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/qmp-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    QObject *obj;
+    QmpInputVisitor *qiv;
+} TestInputVisitorData;
+
+static void visitor_input_teardown(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    qobject_decref(data->obj);
+    data->obj = NULL;
+
+    if (data->qiv) {
+        qmp_input_visitor_cleanup(data->qiv);
+        data->qiv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static GCC_FMT_ATTR(2, 3)
+Visitor *visitor_input_test_init(TestInputVisitorData *data,
+                                 const char *json_string, ...)
+{
+    Visitor *v;
+    va_list ap;
+
+    va_start(ap, json_string);
+    data->obj = qobject_from_jsonv(json_string, &ap);
+    va_end(ap);
+
+    g_assert(data->obj != NULL);
+
+    data->qiv = qmp_input_visitor_new(data->obj);
+    g_assert(data->qiv != NULL);
+
+    v = qmp_input_get_visitor(data->qiv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+static void test_visitor_in_int(TestInputVisitorData *data,
+                                const void *unused)
+{
+    int64_t res = 0, value = -42;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%" PRId64, value);
+
+    visit_type_int(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, value);
+}
+
+static void test_visitor_in_bool(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    bool res = false;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "true");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+}
+
+static void test_visitor_in_number(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    double res = 0, value = 3.14;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%f", value);
+
+    visit_type_number(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpfloat(res, ==, value);
+}
+
+static void test_visitor_in_string(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    char *res = NULL, *value = (char *) "Q E M U";
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "%s", value);
+
+    visit_type_str(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpstr(res, ==, value);
+
+    g_free(res);
+}
+
+static void test_visitor_in_enum(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    Visitor *v;
+    EnumOne i;
+
+    for (i = 0; EnumOne_lookup[i]; i++) {
+        EnumOne res = -1;
+
+        v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
+
+        visit_type_EnumOne(v, &res, NULL, &errp);
+        g_assert(!error_is_set(&errp));
+        g_assert_cmpint(i, ==, res);
+
+        visitor_input_teardown(data, NULL);
+    }
+
+    data->obj = NULL;
+    data->qiv = NULL;
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_in_struct(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(p->integer, ==, -42);
+    g_assert(p->boolean == true);
+    g_assert_cmpstr(p->string, ==, "foo");
+
+    g_free(p->string);
+    g_free(p);
+}
+
+static void check_and_free_str(char *str, const char *cmp)
+{
+    g_assert_cmpstr(str, ==, cmp);
+    g_free(str);
+}
+
+static void test_visitor_in_struct_nested(TestInputVisitorData *data,
+                                          const void *unused)
+{
+    UserDefNested *udp = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
+
+    visit_type_UserDefNested(v, &udp, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    check_and_free_str(udp->string0, "string0");
+    check_and_free_str(udp->dict1.string1, "string1");
+    g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42);
+    check_and_free_str(udp->dict1.dict2.userdef1->string, "string");
+    check_and_free_str(udp->dict1.dict2.string2, "string2");
+    g_assert(udp->dict1.has_dict3 == false);
+
+    g_free(udp->dict1.dict2.userdef1);
+    g_free(udp);
+}
+
+static void test_visitor_in_list(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    UserDefOneList *item, *head = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+    int i;
+
+    v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
+
+    visit_type_UserDefOneList(v, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert(head != NULL);
+
+    for (i = 0, item = head; item; item = item->next, i++) {
+        char string[12];
+
+        snprintf(string, sizeof(string), "string%d", i);
+        g_assert_cmpstr(item->value->string, ==, string);
+        g_assert_cmpint(item->value->integer, ==, 42 + i);
+    }
+
+    qapi_free_UserDefOneList(head);
+}
+
+static void test_visitor_in_union(TestInputVisitorData *data,
+                                  const void *unused)
+{
+    Visitor *v;
+    Error *err = NULL;
+    UserDefUnion *tmp;
+
+    v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
+
+    visit_type_UserDefUnion(v, &tmp, NULL, &err);
+    g_assert(err == NULL);
+    g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B);
+    g_assert_cmpint(tmp->b->integer, ==, 42);
+    qapi_free_UserDefUnion(tmp);
+}
+
+static void input_visitor_test_add(const char *testpath,
+                                   TestInputVisitorData *data,
+                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               visitor_input_teardown);
+}
+
+static void test_visitor_in_errors(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    TestStruct *p = NULL;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
+
+    visit_type_TestStruct(v, &p, NULL, &errp);
+    g_assert(error_is_set(&errp));
+    g_assert(p->string == NULL);
+
+    g_free(p->string);
+    g_free(p);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData in_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    input_visitor_test_add("/visitor/input/int",
+                           &in_visitor_data, test_visitor_in_int);
+    input_visitor_test_add("/visitor/input/bool",
+                           &in_visitor_data, test_visitor_in_bool);
+    input_visitor_test_add("/visitor/input/number",
+                           &in_visitor_data, test_visitor_in_number);
+    input_visitor_test_add("/visitor/input/string",
+                            &in_visitor_data, test_visitor_in_string);
+    input_visitor_test_add("/visitor/input/enum",
+                            &in_visitor_data, test_visitor_in_enum);
+    input_visitor_test_add("/visitor/input/struct",
+                            &in_visitor_data, test_visitor_in_struct);
+    input_visitor_test_add("/visitor/input/struct-nested",
+                            &in_visitor_data, test_visitor_in_struct_nested);
+    input_visitor_test_add("/visitor/input/list",
+                            &in_visitor_data, test_visitor_in_list);
+    input_visitor_test_add("/visitor/input/union",
+                            &in_visitor_data, test_visitor_in_union);
+    input_visitor_test_add("/visitor/input/errors",
+                            &in_visitor_data, test_visitor_in_errors);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
new file mode 100644 (file)
index 0000000..24a6359
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+ * QMP Output Visitor unit-tests.
+ *
+ * Copyright (C) 2011 Red Hat Inc.
+ *
+ * Authors:
+ *  Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+
+#include "qapi/qmp-output-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestOutputVisitorData {
+    QmpOutputVisitor *qov;
+    Visitor *ov;
+} TestOutputVisitorData;
+
+static void visitor_output_setup(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    data->qov = qmp_output_visitor_new();
+    g_assert(data->qov != NULL);
+
+    data->ov = qmp_output_get_visitor(data->qov);
+    g_assert(data->ov != NULL);
+}
+
+static void visitor_output_teardown(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    qmp_output_visitor_cleanup(data->qov);
+    data->qov = NULL;
+    data->ov = NULL;
+}
+
+static void test_visitor_out_int(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    int64_t value = -42;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_int(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QINT);
+    g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_bool(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    bool value = true;
+    QObject *obj;
+
+    visit_type_bool(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QBOOL);
+    g_assert(qbool_get_int(qobject_to_qbool(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_number(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    double value = 3.14;
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_number(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QFLOAT);
+    g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_string(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    char *string = (char *) "Q E M U";
+    Error *errp = NULL;
+    QObject *obj;
+
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string);
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_no_string(TestOutputVisitorData *data,
+                                       const void *unused)
+{
+    char *string = NULL;
+    Error *errp = NULL;
+    QObject *obj;
+
+    /* A null string should return "" */
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QSTRING);
+    g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, "");
+
+    qobject_decref(obj);
+}
+
+static void test_visitor_out_enum(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    QObject *obj;
+    EnumOne i;
+
+    for (i = 0; i < ENUM_ONE_MAX; i++) {
+        visit_type_EnumOne(data->ov, &i, "unused", &errp);
+        g_assert(!error_is_set(&errp));
+
+        obj = qmp_output_get_qobject(data->qov);
+        g_assert(obj != NULL);
+        g_assert(qobject_type(obj) == QTYPE_QSTRING);
+        g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==,
+                        EnumOne_lookup[i]);
+        qobject_decref(obj);
+    }
+}
+
+static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
+                                         const void *unused)
+{
+    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+    Error *errp;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
+typedef struct TestStruct
+{
+    int64_t integer;
+    bool boolean;
+    char *string;
+} TestStruct;
+
+static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
+                                  const char *name, Error **errp)
+{
+    visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+                       errp);
+
+    visit_type_int(v, &(*obj)->integer, "integer", errp);
+    visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
+    visit_type_str(v, &(*obj)->string, "string", errp);
+
+    visit_end_struct(v, errp);
+}
+
+static void test_visitor_out_struct(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    TestStruct test_struct = { .integer = 42,
+                               .boolean = false,
+                               .string = (char *) "foo"};
+    TestStruct *p = &test_struct;
+    Error *errp = NULL;
+    QObject *obj;
+    QDict *qdict;
+
+    visit_type_TestStruct(data->ov, &p, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 3);
+    g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42);
+    g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0);
+    g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo");
+
+    QDECREF(qdict);
+}
+
+static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
+                                           const void *unused)
+{
+    int64_t value = 42;
+    Error *errp = NULL;
+    UserDefNested *ud2;
+    QObject *obj;
+    QDict *qdict, *dict1, *dict2, *dict3, *userdef;
+    const char *string = "user def string";
+    const char *strings[] = { "forty two", "forty three", "forty four",
+                              "forty five" };
+
+    ud2 = g_malloc0(sizeof(*ud2));
+    ud2->string0 = g_strdup(strings[0]);
+
+    ud2->dict1.string1 = g_strdup(strings[1]);
+    ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict2.userdef1->string = g_strdup(string);
+    ud2->dict1.dict2.userdef1->integer = value;
+    ud2->dict1.dict2.string2 = g_strdup(strings[2]);
+
+    ud2->dict1.has_dict3 = true;
+    ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne));
+    ud2->dict1.dict3.userdef2->string = g_strdup(string);
+    ud2->dict1.dict3.userdef2->integer = value;
+    ud2->dict1.dict3.string3 = g_strdup(strings[3]);
+
+    visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QDICT);
+
+    qdict = qobject_to_qdict(obj);
+    g_assert_cmpint(qdict_size(qdict), ==, 2);
+    g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]);
+
+    dict1 = qdict_get_qdict(qdict, "dict1");
+    g_assert_cmpint(qdict_size(dict1), ==, 3);
+    g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]);
+
+    dict2 = qdict_get_qdict(dict1, "dict2");
+    g_assert_cmpint(qdict_size(dict2), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]);
+    userdef = qdict_get_qdict(dict2, "userdef1");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    dict3 = qdict_get_qdict(dict1, "dict3");
+    g_assert_cmpint(qdict_size(dict3), ==, 2);
+    g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]);
+    userdef = qdict_get_qdict(dict3, "userdef2");
+    g_assert_cmpint(qdict_size(userdef), ==, 2);
+    g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value);
+    g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string);
+
+    QDECREF(qdict);
+    qapi_free_UserDefNested(ud2);
+}
+
+static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
+                                           const void *unused)
+{
+    EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
+    UserDefOne u = { 0 }, *pu = &u;
+    Error *errp;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        u.has_enum1 = true;
+        u.enum1 = bad_values[i];
+        visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
+typedef struct TestStructList
+{
+    TestStruct *value;
+    struct TestStructList *next;
+} TestStructList;
+
+static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
+                                      const char *name, Error **errp)
+{
+    GenericList *i, **head = (GenericList **)obj;
+
+    visit_start_list(v, name, errp);
+
+    for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
+        TestStructList *native_i = (TestStructList *)i;
+        visit_type_TestStruct(v, &native_i->value, NULL, errp);
+    }
+
+    visit_end_list(v, errp);
+}
+
+static void test_visitor_out_list(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    char *value_str = (char *) "list value";
+    TestStructList *p, *head = NULL;
+    const int max_items = 10;
+    bool value_bool = true;
+    int value_int = 10;
+    Error *errp = NULL;
+    QListEntry *entry;
+    QObject *obj;
+    QList *qlist;
+    int i;
+
+    for (i = 0; i < max_items; i++) {
+        p = g_malloc0(sizeof(*p));
+        p->value = g_malloc0(sizeof(*p->value));
+        p->value->integer = value_int;
+        p->value->boolean = value_bool;
+        p->value->string = value_str;
+
+        p->next = head;
+        head = p;
+    }
+
+    visit_type_TestStructList(data->ov, &head, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+
+    obj = qmp_output_get_qobject(data->qov);
+    g_assert(obj != NULL);
+    g_assert(qobject_type(obj) == QTYPE_QLIST);
+
+    qlist = qobject_to_qlist(obj);
+    g_assert(!qlist_empty(qlist));
+
+    i = 0;
+    QLIST_FOREACH_ENTRY(qlist, entry) {
+        QDict *qdict;
+
+        g_assert(qobject_type(entry->value) == QTYPE_QDICT);
+        qdict = qobject_to_qdict(entry->value);
+        g_assert_cmpint(qdict_size(qdict), ==, 3);
+        g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
+        g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
+        g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
+        i++;
+    }
+    g_assert_cmpint(i, ==, max_items);
+
+    QDECREF(qlist);
+
+    for (p = head; p;) {
+        TestStructList *tmp = p->next;
+        g_free(p->value);
+        g_free(p);
+        p = tmp;
+    }
+}
+
+static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
+                                            const void *unused)
+{
+    UserDefNestedList *p, *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.string1 = g_strdup(string);
+        p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne));
+        p->value->dict1.dict2.userdef1->string = g_strdup(string);
+        p->value->dict1.dict2.userdef1->integer = 42;
+        p->value->dict1.dict2.string2 = g_strdup(string);
+        p->value->dict1.has_dict3 = false;
+
+        p->next = head;
+        head = p;
+    }
+
+    qapi_free_UserDefNestedList(head);
+}
+
+static void test_visitor_out_union(TestOutputVisitorData *data,
+                                   const void *unused)
+{
+    QObject *arg, *qvalue;
+    QDict *qdict, *value;
+
+    Error *err = NULL;
+
+    UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion));
+    tmp->kind = USER_DEF_UNION_KIND_A;
+    tmp->a = g_malloc0(sizeof(UserDefA));
+    tmp->a->boolean = true;
+
+    visit_type_UserDefUnion(data->ov, &tmp, NULL, &err);
+    g_assert(err == NULL);
+    arg = qmp_output_get_qobject(data->qov);
+
+    g_assert(qobject_type(arg) == QTYPE_QDICT);
+    qdict = qobject_to_qdict(arg);
+
+    g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a");
+
+    qvalue = qdict_get(qdict, "data");
+    g_assert(data != NULL);
+    g_assert(qobject_type(qvalue) == QTYPE_QDICT);
+    value = qobject_to_qdict(qvalue);
+    g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true);
+
+    qapi_free_UserDefUnion(tmp);
+    QDECREF(qdict);
+}
+
+static void output_visitor_test_add(const char *testpath,
+                                    TestOutputVisitorData *data,
+                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
+               test_func, visitor_output_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestOutputVisitorData out_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    output_visitor_test_add("/visitor/output/int",
+                            &out_visitor_data, test_visitor_out_int);
+    output_visitor_test_add("/visitor/output/bool",
+                            &out_visitor_data, test_visitor_out_bool);
+    output_visitor_test_add("/visitor/output/number",
+                            &out_visitor_data, test_visitor_out_number);
+    output_visitor_test_add("/visitor/output/string",
+                            &out_visitor_data, test_visitor_out_string);
+    output_visitor_test_add("/visitor/output/no-string",
+                            &out_visitor_data, test_visitor_out_no_string);
+    output_visitor_test_add("/visitor/output/enum",
+                            &out_visitor_data, test_visitor_out_enum);
+    output_visitor_test_add("/visitor/output/enum-errors",
+                            &out_visitor_data, test_visitor_out_enum_errors);
+    output_visitor_test_add("/visitor/output/struct",
+                            &out_visitor_data, test_visitor_out_struct);
+    output_visitor_test_add("/visitor/output/struct-nested",
+                            &out_visitor_data, test_visitor_out_struct_nested);
+    output_visitor_test_add("/visitor/output/struct-errors",
+                            &out_visitor_data, test_visitor_out_struct_errors);
+    output_visitor_test_add("/visitor/output/list",
+                            &out_visitor_data, test_visitor_out_list);
+    output_visitor_test_add("/visitor/output/list-qapi-free",
+                            &out_visitor_data, test_visitor_out_list_qapi_free);
+    output_visitor_test_add("/visitor/output/union",
+                            &out_visitor_data, test_visitor_out_union);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
new file mode 100644 (file)
index 0000000..5370e32
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * String Input Visitor unit-tests.
+ *
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Authors:
+ *  Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-input-visitor)
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/string-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+    StringInputVisitor *siv;
+} TestInputVisitorData;
+
+static void visitor_input_teardown(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    if (data->siv) {
+        string_input_visitor_cleanup(data->siv);
+        data->siv = NULL;
+    }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+   string used by the tests are kept in the test functions (and not
+   int main()) */
+static
+Visitor *visitor_input_test_init(TestInputVisitorData *data,
+                                 const char *string)
+{
+    Visitor *v;
+
+    data->siv = string_input_visitor_new(string);
+    g_assert(data->siv != NULL);
+
+    v = string_input_get_visitor(data->siv);
+    g_assert(v != NULL);
+
+    return v;
+}
+
+static void test_visitor_in_int(TestInputVisitorData *data,
+                                const void *unused)
+{
+    int64_t res = 0, value = -42;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "-42");
+
+    visit_type_int(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, value);
+}
+
+static void test_visitor_in_bool(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    bool res = false;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "true");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "yes");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "on");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, true);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "false");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, false);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "no");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, false);
+    visitor_input_teardown(data, unused);
+
+    v = visitor_input_test_init(data, "off");
+
+    visit_type_bool(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpint(res, ==, false);
+}
+
+static void test_visitor_in_number(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    double res = 0, value = 3.14;
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, "3.14");
+
+    visit_type_number(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpfloat(res, ==, value);
+}
+
+static void test_visitor_in_string(TestInputVisitorData *data,
+                                   const void *unused)
+{
+    char *res = NULL, *value = (char *) "Q E M U";
+    Error *errp = NULL;
+    Visitor *v;
+
+    v = visitor_input_test_init(data, value);
+
+    visit_type_str(v, &res, NULL, &errp);
+    g_assert(!error_is_set(&errp));
+    g_assert_cmpstr(res, ==, value);
+
+    g_free(res);
+}
+
+static void test_visitor_in_enum(TestInputVisitorData *data,
+                                 const void *unused)
+{
+    Error *errp = NULL;
+    Visitor *v;
+    EnumOne i;
+
+    for (i = 0; EnumOne_lookup[i]; i++) {
+        EnumOne res = -1;
+
+        v = visitor_input_test_init(data, EnumOne_lookup[i]);
+
+        visit_type_EnumOne(v, &res, NULL, &errp);
+        g_assert(!error_is_set(&errp));
+        g_assert_cmpint(i, ==, res);
+
+        visitor_input_teardown(data, NULL);
+    }
+
+    data->siv = NULL;
+}
+
+static void input_visitor_test_add(const char *testpath,
+                                   TestInputVisitorData *data,
+                                   void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+               visitor_input_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestInputVisitorData in_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    input_visitor_test_add("/string-visitor/input/int",
+                           &in_visitor_data, test_visitor_in_int);
+    input_visitor_test_add("/string-visitor/input/bool",
+                           &in_visitor_data, test_visitor_in_bool);
+    input_visitor_test_add("/string-visitor/input/number",
+                           &in_visitor_data, test_visitor_in_number);
+    input_visitor_test_add("/string-visitor/input/string",
+                            &in_visitor_data, test_visitor_in_string);
+    input_visitor_test_add("/string-visitor/input/enum",
+                            &in_visitor_data, test_visitor_in_enum);
+
+    g_test_run();
+
+    return 0;
+}
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
new file mode 100644 (file)
index 0000000..22909b8
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * String Output Visitor unit-tests.
+ *
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Authors:
+ *  Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-output-visitor)
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+
+#include "qapi/string-output-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestOutputVisitorData {
+    StringOutputVisitor *sov;
+    Visitor *ov;
+} TestOutputVisitorData;
+
+static void visitor_output_setup(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    data->sov = string_output_visitor_new();
+    g_assert(data->sov != NULL);
+
+    data->ov = string_output_get_visitor(data->sov);
+    g_assert(data->ov != NULL);
+}
+
+static void visitor_output_teardown(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    string_output_visitor_cleanup(data->sov);
+    data->sov = NULL;
+    data->ov = NULL;
+}
+
+static void test_visitor_out_int(TestOutputVisitorData *data,
+                                 const void *unused)
+{
+    int64_t value = -42;
+    Error *errp = NULL;
+    char *str;
+
+    visit_type_int(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, "-42");
+    g_free(str);
+}
+
+static void test_visitor_out_bool(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    bool value = true;
+    char *str;
+
+    visit_type_bool(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, "true");
+    g_free(str);
+}
+
+static void test_visitor_out_number(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    double value = 3.14;
+    Error *errp = NULL;
+    char *str;
+
+    visit_type_number(data->ov, &value, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, "3.14");
+    g_free(str);
+}
+
+static void test_visitor_out_string(TestOutputVisitorData *data,
+                                    const void *unused)
+{
+    char *string = (char *) "Q E M U";
+    Error *errp = NULL;
+    char *str;
+
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, string);
+    g_free(str);
+}
+
+static void test_visitor_out_no_string(TestOutputVisitorData *data,
+                                       const void *unused)
+{
+    char *string = NULL;
+    Error *errp = NULL;
+    char *str;
+
+    /* A null string should return "" */
+    visit_type_str(data->ov, &string, NULL, &errp);
+    g_assert(error_is_set(&errp) == 0);
+
+    str = string_output_get_string(data->sov);
+    g_assert(str != NULL);
+    g_assert_cmpstr(str, ==, "");
+    g_free(str);
+}
+
+static void test_visitor_out_enum(TestOutputVisitorData *data,
+                                  const void *unused)
+{
+    Error *errp = NULL;
+    char *str;
+    EnumOne i;
+
+    for (i = 0; i < ENUM_ONE_MAX; i++) {
+        visit_type_EnumOne(data->ov, &i, "unused", &errp);
+        g_assert(!error_is_set(&errp));
+
+        str = string_output_get_string(data->sov);
+        g_assert(str != NULL);
+        g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
+       g_free(str);
+    }
+}
+
+static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
+                                         const void *unused)
+{
+    EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+    Error *errp;
+
+    for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+        errp = NULL;
+        visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
+        g_assert(error_is_set(&errp) == true);
+        error_free(errp);
+    }
+}
+
+static void output_visitor_test_add(const char *testpath,
+                                    TestOutputVisitorData *data,
+                                    void (*test_func)(TestOutputVisitorData *data, const void *user_data))
+{
+    g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
+               test_func, visitor_output_teardown);
+}
+
+int main(int argc, char **argv)
+{
+    TestOutputVisitorData out_visitor_data;
+
+    g_test_init(&argc, &argv, NULL);
+
+    output_visitor_test_add("/string-visitor/output/int",
+                            &out_visitor_data, test_visitor_out_int);
+    output_visitor_test_add("/string-visitor/output/bool",
+                            &out_visitor_data, test_visitor_out_bool);
+    output_visitor_test_add("/string-visitor/output/number",
+                            &out_visitor_data, test_visitor_out_number);
+    output_visitor_test_add("/string-visitor/output/string",
+                            &out_visitor_data, test_visitor_out_string);
+    output_visitor_test_add("/string-visitor/output/no-string",
+                            &out_visitor_data, test_visitor_out_no_string);
+    output_visitor_test_add("/string-visitor/output/enum",
+                            &out_visitor_data, test_visitor_out_enum);
+    output_visitor_test_add("/string-visitor/output/enum-errors",
+                            &out_visitor_data, test_visitor_out_enum_errors);
+
+    g_test_run();
+
+    return 0;
+}