From patchwork Mon Dec 5 14:45:48 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Capitulino X-Patchwork-Id: 129306 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B4FF11007D6 for ; Tue, 6 Dec 2011 01:47:02 +1100 (EST) Received: from localhost ([::1]:38629 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RXZoo-0008H5-1z for incoming@patchwork.ozlabs.org; Mon, 05 Dec 2011 09:46:58 -0500 Received: from eggs.gnu.org ([140.186.70.92]:49968) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RXZnx-0005ca-V4 for qemu-devel@nongnu.org; Mon, 05 Dec 2011 09:46:16 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RXZnv-0005yL-4j for qemu-devel@nongnu.org; Mon, 05 Dec 2011 09:46:05 -0500 Received: from mx1.redhat.com ([209.132.183.28]:2458) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RXZnu-0005yC-Q2 for qemu-devel@nongnu.org; Mon, 05 Dec 2011 09:46:03 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id pB5EjxNB005637 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 5 Dec 2011 09:45:59 -0500 Received: from localhost (ovpn-113-50.phx2.redhat.com [10.3.113.50]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id pB5Ejw95020659; Mon, 5 Dec 2011 09:45:58 -0500 From: Luiz Capitulino To: qemu-devel@nongnu.org Date: Mon, 5 Dec 2011 12:45:48 -0200 Message-Id: <1323096349-2246-4-git-send-email-lcapitulino@redhat.com> In-Reply-To: <1323096349-2246-1-git-send-email-lcapitulino@redhat.com> References: <1323096349-2246-1-git-send-email-lcapitulino@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 209.132.183.28 Cc: aliguori@us.ibm.com, mdroth@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 3/4] Introduce test-qmp-input-visitor X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Contains unit-tests for the QMP input visitor implementation. Signed-off-by: Luiz Capitulino --- Makefile | 5 +- configure | 2 +- test-qmp-input-visitor.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 275 insertions(+), 2 deletions(-) create mode 100644 test-qmp-input-visitor.c diff --git a/Makefile b/Makefile index 206854a..c4884fc 100644 --- a/Makefile +++ b/Makefile @@ -169,7 +169,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(qapi-obj-y): $(GENERATED_HEADERS) qapi-dir := $(BUILD_DIR)/qapi-generated -test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir) +test-qmp-input-visitor.o test-qmp-output-visitor.o test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir) qemu-ga$(EXESUF): LIBS = $(LIBS_QGA) $(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\ @@ -208,6 +208,9 @@ test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qap 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 +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 + 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 diff --git a/configure b/configure index ad403f7..4a958e2 100755 --- a/configure +++ b/configure @@ -2744,7 +2744,7 @@ if test "$softmmu" = yes ; then checks="check-qint check-qstring check-qdict check-qlist" checks="check-qfloat check-qjson $checks" fi - test_progs="$checks test-coroutine test-qmp-output-visitor" + test_progs="$checks test-coroutine test-qmp-output-visitor test-qmp-input-visitor" fi fi diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c new file mode 100644 index 0000000..1f3ab03 --- /dev/null +++ b/test-qmp-input-visitor.c @@ -0,0 +1,270 @@ +/* + * 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 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, "%d", 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 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("/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); + + g_test_run(); + + return 0; +}