From: Paolo Bonzini Date: Wed, 28 Mar 2012 13:42:01 +0000 (+0200) Subject: test makefile overhaul X-Git-Tag: qemu-xen-4.3.0-rc1~1313 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=b93b63f574ccb451e82f81c6da7c39b3ecb4f24c;p=qemu-upstream-4.3-testing.git test makefile overhaul 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 Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- diff --git a/check-qdict.c b/check-qdict.c deleted file mode 100644 index fc0d27653..000000000 --- a/check-qdict.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * QDict unit-tests. - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * - * 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 - -#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 index cdc66ea10..000000000 --- a/check-qfloat.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * QFloat unit-tests. - * - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori - * - * 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 - -#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 index 5a27119ae..000000000 --- a/check-qint.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * QInt unit-tests. - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * - * 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 - -#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 index 526e25ef6..000000000 --- a/check-qjson.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * Copyright IBM, Corp. 2009 - * - * Authors: - * Anthony Liguori - * - * 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 - -#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 index 501ba262d..000000000 --- a/check-qlist.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * QList unit-tests. - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * - * 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 - -#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 index addad6c67..000000000 --- a/check-qstring.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * QString unit-tests. - * - * Copyright (C) 2009 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * - * 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 - -#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/rules.mak b/rules.mak index 04a91983e..c30093c11 100644 --- 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 index 000000000..061a952ca --- /dev/null +++ b/scripts/gtester-cat @@ -0,0 +1,26 @@ +#!/bin/sh +# +# Copyright IBM, Corp. 2012 +# +# Authors: +# Anthony Liguori +# +# This work is licensed under the terms of the GNU GPLv2 or later. +# See the COPYING file in the top-level directory. + +cat < + + + qemu + 0.0 + rev + +EOF + +sed \ + -e '/$/d' \ + -e '//,/<\/info>/d' \ + -e '$b' \ + -e '/^<\/gtester>$/d' "$@" diff --git a/test-coroutine.c b/test-coroutine.c deleted file mode 100644 index e5d14eb69..000000000 --- a/test-coroutine.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Coroutine tests - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Stefan Hajnoczi - * - * 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 -#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 index 60cbf019b..000000000 --- a/test-qmp-commands.c +++ /dev/null @@ -1,139 +0,0 @@ -#include -#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 index f6df8cbe1..000000000 --- a/test-qmp-input-strict.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * QMP Input Visitor unit-tests (strict mode). - * - * Copyright (C) 2011-2012 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * Paolo Bonzini - * - * 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 -#include - -#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 index c30fdc4e5..000000000 --- a/test-qmp-input-visitor.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * QMP Input Visitor unit-tests. - * - * Copyright (C) 2011 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * - * 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 -#include - -#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 index 24a635950..000000000 --- a/test-qmp-output-visitor.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * QMP Output Visitor unit-tests. - * - * Copyright (C) 2011 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * - * 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 - -#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 index 5370e3204..000000000 --- a/test-string-input-visitor.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * String Input Visitor unit-tests. - * - * Copyright (C) 2012 Red Hat Inc. - * - * Authors: - * Paolo Bonzini (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 -#include - -#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 index 22909b84e..000000000 --- a/test-string-output-visitor.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * String Output Visitor unit-tests. - * - * Copyright (C) 2012 Red Hat Inc. - * - * Authors: - * Paolo Bonzini (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 - -#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; -} diff --git a/tests/Makefile b/tests/Makefile index 2a2fff7c6..17f6eced0 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,61 +1,113 @@ 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 index 000000000..fc0d27653 --- /dev/null +++ b/tests/check-qdict.c @@ -0,0 +1,378 @@ +/* + * QDict unit-tests. + * + * Copyright (C) 2009 Red Hat Inc. + * + * Authors: + * Luiz Capitulino + * + * 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 + +#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 index 000000000..cdc66ea10 --- /dev/null +++ b/tests/check-qfloat.c @@ -0,0 +1,53 @@ +/* + * QFloat unit-tests. + * + * Copyright IBM, Corp. 2009 + * + * Authors: + * Anthony Liguori + * + * 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 + +#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 index 000000000..5a27119ae --- /dev/null +++ b/tests/check-qint.c @@ -0,0 +1,87 @@ +/* + * QInt unit-tests. + * + * Copyright (C) 2009 Red Hat Inc. + * + * Authors: + * Luiz Capitulino + * + * 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 + +#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 index 000000000..526e25ef6 --- /dev/null +++ b/tests/check-qjson.c @@ -0,0 +1,728 @@ +/* + * Copyright IBM, Corp. 2009 + * + * Authors: + * Anthony Liguori + * + * 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 + +#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 index 000000000..501ba262d --- /dev/null +++ b/tests/check-qlist.c @@ -0,0 +1,127 @@ +/* + * QList unit-tests. + * + * Copyright (C) 2009 Red Hat Inc. + * + * Authors: + * Luiz Capitulino + * + * 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 + +#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 index 000000000..addad6c67 --- /dev/null +++ b/tests/check-qstring.c @@ -0,0 +1,107 @@ +/* + * QString unit-tests. + * + * Copyright (C) 2009 Red Hat Inc. + * + * Authors: + * Luiz Capitulino + * + * 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 + +#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 index 000000000..e5d14eb69 --- /dev/null +++ b/tests/test-coroutine.c @@ -0,0 +1,219 @@ +/* + * Coroutine tests + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczi + * + * 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 +#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 index 000000000..60cbf019b --- /dev/null +++ b/tests/test-qmp-commands.c @@ -0,0 +1,139 @@ +#include +#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 index 000000000..f6df8cbe1 --- /dev/null +++ b/tests/test-qmp-input-strict.c @@ -0,0 +1,234 @@ +/* + * QMP Input Visitor unit-tests (strict mode). + * + * Copyright (C) 2011-2012 Red Hat Inc. + * + * Authors: + * Luiz Capitulino + * Paolo Bonzini + * + * 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 +#include + +#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 index 000000000..c30fdc4e5 --- /dev/null +++ b/tests/test-qmp-input-visitor.c @@ -0,0 +1,308 @@ +/* + * QMP Input Visitor unit-tests. + * + * Copyright (C) 2011 Red Hat Inc. + * + * Authors: + * Luiz Capitulino + * + * 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 +#include + +#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 index 000000000..24a635950 --- /dev/null +++ b/tests/test-qmp-output-visitor.c @@ -0,0 +1,477 @@ +/* + * QMP Output Visitor unit-tests. + * + * Copyright (C) 2011 Red Hat Inc. + * + * Authors: + * Luiz Capitulino + * + * 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 + +#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 index 000000000..5370e3204 --- /dev/null +++ b/tests/test-string-input-visitor.c @@ -0,0 +1,195 @@ +/* + * String Input Visitor unit-tests. + * + * Copyright (C) 2012 Red Hat Inc. + * + * Authors: + * Paolo Bonzini (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 +#include + +#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 index 000000000..22909b84e --- /dev/null +++ b/tests/test-string-output-visitor.c @@ -0,0 +1,188 @@ +/* + * String Output Visitor unit-tests. + * + * Copyright (C) 2012 Red Hat Inc. + * + * Authors: + * Paolo Bonzini (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 + +#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; +}