From patchwork Wed Oct 31 22:36:12 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 196037 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id AC2632C0223 for ; Thu, 1 Nov 2012 09:55:36 +1100 (EST) Received: from localhost ([::1]:53118 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TTgwV-0004x1-HY for incoming@patchwork.ozlabs.org; Wed, 31 Oct 2012 18:39:23 -0400 Received: from eggs.gnu.org ([208.118.235.92]:35069) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TTguV-00029p-Jr for qemu-devel@nongnu.org; Wed, 31 Oct 2012 18:37:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TTguN-0005wF-QX for qemu-devel@nongnu.org; Wed, 31 Oct 2012 18:37:19 -0400 Received: from mail-ie0-f173.google.com ([209.85.223.173]:33189) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TTguN-0005k6-KO for qemu-devel@nongnu.org; Wed, 31 Oct 2012 18:37:11 -0400 Received: by mail-ie0-f173.google.com with SMTP id 17so2893446iea.4 for ; Wed, 31 Oct 2012 15:37:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=dmTLAuzbzJpumoncb567BrwsBhf1ezHxGM1oshVvGu8=; b=0JRqWMUf2JfAI60JMrZ85DhkO+MAPevOwJYRTFuhmdRThBL/lwlfquH9PEp4cSJrkD oK+JNHD+hNt93xsX5pt+U81dRP98sMAyQEjHdNzcge41pRveY4ugevRNFtFBtgswe8Eg no1+gN4GjB/YKf9o4v9x8I27PNSsKN5jhcLcXIDbaJAgjuX3mImjCHz1+j7LFBtKgUkE gdMqi90gvnfKJjanAvQ44wp5ymPEZNd9P2ugKX4h1bYCOXfMNJVOjoWS+MSPQodWxnOn PN4wZ+b0Tly6vaC2l8ClUqmE8nIOJ8ONNo5PIqq06+f285VZ8oUQjItkee4Qy+rkFYYj mBXw== Received: by 10.50.57.234 with SMTP id l10mr3182445igq.18.1351723031294; Wed, 31 Oct 2012 15:37:11 -0700 (PDT) Received: from loki.morrigu.org (cpe-72-179-62-111.austin.res.rr.com. [72.179.62.111]) by mx.google.com with ESMTPS id hg2sm11556858igc.3.2012.10.31.15.37.09 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 31 Oct 2012 15:37:10 -0700 (PDT) From: Michael Roth To: qemu-devel@nongnu.org Date: Wed, 31 Oct 2012 17:36:12 -0500 Message-Id: <1351722972-17801-29-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1351722972-17801-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1351722972-17801-1-git-send-email-mdroth@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.223.173 Cc: kwolf@redhat.com, peter.maydell@linaro.org, aliguori@us.ibm.com, blauwirbel@gmail.com, pbonzini@redhat.com Subject: [Qemu-devel] [PATCH 28/28] qidl: unit tests and build infrastructure 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 Signed-off-by: Michael Roth --- Makefile | 3 + configure | 1 + rules.mak | 42 ++++- tests/Makefile | 8 +- tests/test-qidl-included.h | 25 +++ tests/test-qidl-linked.c | 101 +++++++++++ tests/test-qidl-pub-linked.c | 18 ++ tests/test-qidl-pub-linked.h | 29 ++++ tests/test-qidl.c | 390 ++++++++++++++++++++++++++++++++++++++++++ tests/test-qidl.h | 36 ++++ 10 files changed, 650 insertions(+), 3 deletions(-) create mode 100644 tests/test-qidl-included.h create mode 100644 tests/test-qidl-linked.c create mode 100644 tests/test-qidl-pub-linked.c create mode 100644 tests/test-qidl-pub-linked.h create mode 100644 tests/test-qidl.c create mode 100644 tests/test-qidl.h diff --git a/Makefile b/Makefile index e543482..b575361 100644 --- a/Makefile +++ b/Makefile @@ -248,6 +248,8 @@ clean: if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ rm -f $$d/qemu-options.def; \ done + find -name '*.qidl.c' -exec rm -f {} \; + find -name '*.qidl.schema' -exec rm -f {} \; VERSION ?= $(shell cat VERSION) @@ -419,6 +421,7 @@ ifneq ($(filter-out %clean,$(MAKECMDGOALS)),$(if $(MAKECMDGOALS),,fail)) Makefile: $(GENERATED_HEADERS) endif + # Include automatically generated dependency files # Dependencies in Makefile.objs files come from our recursive subdir rules -include $(wildcard *.d tests/*.d) diff --git a/configure b/configure index 9c6ac87..bc675f8 100755 --- a/configure +++ b/configure @@ -3231,6 +3231,7 @@ if test "$debug_tcg" = "yes" ; then fi if test "$debug" = "yes" ; then echo "CONFIG_DEBUG_EXEC=y" >> $config_host_mak + echo "CONFIG_DEBUG_QIDL=y" >> $config_host_mak fi if test "$strip_opt" = "yes" ; then echo "STRIP=${strip}" >> $config_host_mak diff --git a/rules.mak b/rules.mak index 1b173aa..714f642 100644 --- a/rules.mak +++ b/rules.mak @@ -14,8 +14,23 @@ MAKEFLAGS += -rR # Flags for dependency generation QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d +# Debug options for QIDL +ifdef CONFIG_DEBUG_QIDL +QIDL_FLAGS = --schema-filepath=$(*D)/$(*F).qidl.schema +endif + +# QIDL dependencies +qidl-deps := $(SRC_PATH)/qidl.h $(addprefix $(SRC_PATH)/scripts/,lexer.py qidl.py qidl_parser.py qapi.py qapi_visit.py) + +.SECONDARY: + %.o: %.c - $(call quiet-command,$(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CC $(TARGET_DIR)$@") + +%.qidl.c: %.c $(qidl-deps) + $(call quiet-command,$(qidl-pp)) + +%.o: %.c %.qidl.c + $(call quiet-command,$(qidl-cc)) ifeq ($(LIBTOOL),) %.lo: %.c @@ -79,6 +94,31 @@ TRACETOOL=$(PYTHON) $(SRC_PATH)/scripts/tracetool.py obj := . old-nested-dirs := +qidl-pp-cmd = \ + $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(CFLAGS) -E -c -DQIDL_GEN $< | \ + $(PYTHON) $(SRC_PATH)/scripts/qidl.py $(QIDL_FLAGS) \ + --output-filepath=$(*D)/$(*F).qidl.c || [ "$$?" -eq 2 ] + +qidl-cc-cmd = \ + $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c \ + -DQIDL_ENABLED -include $< -o $@ $(*D)/$(*F).qidl.c + +default-cc-cmd = \ + $(CC) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $< + +qidl-pp = \ + rm -f $(*D)/$(*F).qidl.*; \ + if grep "QIDL_ENABLE()" $< 1>/dev/null; then \ + echo "qidl PP $(*D)/$(*F).c" && $(qidl-pp-cmd); \ + fi + +qidl-cc = \ + if test -f $(*D)/$(*F).qidl.c; then \ + echo "qidl CC $@" && $(qidl-cc-cmd); \ + else \ + echo " CC $@" && $(default-cc-cmd); \ + fi + define push-var $(eval save-$2-$1 = $(value $1)) $(eval $1 :=) diff --git a/tests/Makefile b/tests/Makefile index af06a9b..aab7ce2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -15,6 +15,7 @@ check-unit-y += tests/test-string-output-visitor$(EXESUF) check-unit-y += tests/test-coroutine$(EXESUF) check-unit-y += tests/test-visitor-serialization$(EXESUF) check-unit-y += tests/test-iov$(EXESUF) +check-unit-y += tests/test-qidl$(EXESUF) check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh @@ -34,11 +35,12 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.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 tests/test-visitor-serialization.o + tests/test-qmp-commands.o tests/test-visitor-serialization.o \ + tests/test-qidl.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-qapi-obj-y += module.o $(qom-obj-y) $(test-obj-y): QEMU_INCLUDES += -Itests @@ -84,6 +86,8 @@ check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET) qtest-obj-y = tests/libqtest.o $(oslib-obj-y) $(tools-obj-y) $(check-qtest-y): $(qtest-obj-y) +tests/test-qidl$(EXESUF): tests/test-qidl.o tests/test-qidl-linked.o tests/test-qidl-pub-linked.o $(test-qapi-obj-y) qapi/misc-qapi-visit.o + .PHONY: check-help check-help: @echo "Regression testing targets:" diff --git a/tests/test-qidl-included.h b/tests/test-qidl-included.h new file mode 100644 index 0000000..3ee8487 --- /dev/null +++ b/tests/test-qidl-included.h @@ -0,0 +1,25 @@ +/* + * Unit-tests for QIDL-generated visitors/code + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Michael Roth + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef TEST_QIDL_INCLUDED_H +#define TEST_QIDL_INCLUDED_H + +#include "qidl.h" +#include "test-qidl.h" + +typedef struct TestStructIncluded TestStructIncluded; + +QIDL_DECLARE(TestStructIncluded) { + TEST_QIDL_STRUCT_BODY +}; + +#endif diff --git a/tests/test-qidl-linked.c b/tests/test-qidl-linked.c new file mode 100644 index 0000000..0499bc1 --- /dev/null +++ b/tests/test-qidl-linked.c @@ -0,0 +1,101 @@ +/* + * Unit-tests for QIDL-generated visitors/code + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Michael Roth + * + * 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 "qidl.h" +#include "test-qidl.h" +#include "test-qidl-pub-linked.h" +#include "hw/qdev-properties.h" +#include "qapi/qmp-input-visitor.h" +#include "qapi/qmp-output-visitor.h" +#include "qapi/qapi-dealloc-visitor.h" + +QIDL_ENABLE() + +typedef struct TestStructLinked TestStructLinked; + +QIDL_DECLARE(TestStructLinked) { + TEST_QIDL_STRUCT_BODY +}; + +/* exercise generated code from annotations in objects we link against */ +void test_linked_object_annotations(gconstpointer opaque) +{ + TestStructLinked *s1, *s2 = NULL; + QmpInputVisitor *qiv; + QmpOutputVisitor *qov; + QObject *s1_obj; + Error *err = NULL; + + s1 = g_malloc0(sizeof(TestStructLinked)); + fill_test_struct(s1); + + qov = qmp_output_visitor_new(); + QIDL_VISIT_TYPE(TestStructLinked, qmp_output_get_visitor(qov), &s1, NULL, + &err); + g_assert(err == NULL); + + s1_obj = qmp_output_get_qobject(qov); + qiv = qmp_input_visitor_new(s1_obj); + + qobject_decref(s1_obj); + qmp_output_visitor_cleanup(qov); + free_test_struct(s1); + + s2 = g_malloc0(sizeof(TestStructLinked)); + QIDL_VISIT_TYPE(TestStructLinked, qmp_input_get_visitor(qiv), &s2, NULL, + &err); + g_assert(err == NULL); + check_test_struct(s2); + + qmp_input_visitor_cleanup(qiv); + free_test_struct(s2); + + check_test_struct_properties(QIDL_PROPERTIES(TestStructLinked)); +} + +/* exercise annotations in public header files who's generated code we + * link against (second user of generated code) + */ +void test_public_linked_object_annotations2(gconstpointer opaque) +{ + TestStructPublicLinked *s1, *s2 = NULL; + QmpInputVisitor *qiv; + QmpOutputVisitor *qov; + QObject *s1_obj; + Error *err = NULL; + + s1 = g_malloc0(sizeof(TestStructPublicLinked)); + fill_test_struct(s1); + + qov = qmp_output_visitor_new(); + QIDL_VISIT_TYPE(TestStructPublicLinked, qmp_output_get_visitor(qov), &s1, + NULL, &err); + g_assert(err == NULL); + + s1_obj = qmp_output_get_qobject(qov); + qiv = qmp_input_visitor_new(s1_obj); + + qobject_decref(s1_obj); + qmp_output_visitor_cleanup(qov); + free_test_struct(s1); + + s2 = g_malloc0(sizeof(TestStructPublicLinked)); + QIDL_VISIT_TYPE(TestStructPublicLinked, qmp_input_get_visitor(qiv), &s2, + NULL, &err); + g_assert(err == NULL); + check_test_struct(s2); + + qmp_input_visitor_cleanup(qiv); + free_test_struct(s2); + + check_test_struct_properties(QIDL_PROPERTIES(TestStructPublicLinked)); +} diff --git a/tests/test-qidl-pub-linked.c b/tests/test-qidl-pub-linked.c new file mode 100644 index 0000000..5b613e7 --- /dev/null +++ b/tests/test-qidl-pub-linked.c @@ -0,0 +1,18 @@ +/* + * Unit-tests for QIDL-generated visitors/code + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Michael Roth + * + * 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 "qidl.h" +#include "test-qidl-pub-linked.h" + +QIDL_ENABLE() + +QIDL_IMPLEMENT_PUBLIC(TestStructPublicLinked) diff --git a/tests/test-qidl-pub-linked.h b/tests/test-qidl-pub-linked.h new file mode 100644 index 0000000..362b57c --- /dev/null +++ b/tests/test-qidl-pub-linked.h @@ -0,0 +1,29 @@ +/* + * Unit-tests for QIDL-generated visitors/code + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Michael Roth + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef TEST_QIDL_PUB_LINKED_H +#define TEST_QIDL_PUB_LINKED_H + +typedef struct TestStructPublicLinked TestStructPublicLinked; + +QIDL_DECLARE_PUBLIC(TestStructPublicLinked) { + int32_t q_immutable a; + int32_t b; + uint32_t q_immutable c; + uint32_t d; + uint64_t q_immutable e; + uint64_t q_property("f", 42) f; + char *g; + char q_property("h") *h; +}; + +#endif diff --git a/tests/test-qidl.c b/tests/test-qidl.c new file mode 100644 index 0000000..06cf27e --- /dev/null +++ b/tests/test-qidl.c @@ -0,0 +1,390 @@ +/* + * Unit-tests for QIDL-generated visitors/code + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Michael Roth + * + * 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 +#include "qidl.h" +#include "test-qidl.h" +#include "test-qidl-included.h" +#include "test-qidl-pub-linked.h" +#include "hw/qdev-properties.h" +#include "qapi/qmp-input-visitor.h" +#include "qapi/qmp-output-visitor.h" +#include "qapi/qapi-dealloc-visitor.h" + +QIDL_ENABLE() + +PropertyInfo qdev_prop_uint64; +PropertyInfo qdev_prop_string; + +typedef struct TestStructMain TestStructMain; + +QIDL_DECLARE(TestStructMain) { + TEST_QIDL_STRUCT_BODY +}; + +void fill_test_struct(void *opaque) +{ + TestStructMain *s = opaque; + s->a = 42; + s->b = INT32_MAX; + s->c = 43; + s->d = UINT32_MAX; + s->e = 44; + s->f = UINT64_MAX; + s->g = g_strdup("test string g"); + s->h = g_strdup("test string h"); +} + +void check_test_struct(void *opaque) +{ + TestStructMain *s = opaque; + g_assert_cmpint(s->a, ==, 0); + g_assert_cmpint(s->b, ==, INT32_MAX); + g_assert_cmpint(s->c, ==, 0); + g_assert_cmpint(s->d, ==, UINT32_MAX); + g_assert_cmpint(s->e, ==, 0); + g_assert_cmpstr(s->g, ==, "test string g"); + g_assert(s->h == NULL); +} + +void free_test_struct(void *opaque) +{ + TestStructMain *s = opaque; + g_free(s->g); + g_free(s->h); + g_free(s); +} + +void check_test_struct_properties(const Property *props) +{ + g_assert_cmpstr(props[0].name, ==, "f"); + g_assert_cmpint(props[0].defval, ==, 42); + g_assert_cmpstr(props[1].name, ==, "h"); + g_assert_cmpint(props[1].defval, ==, 0); + g_assert(props[2].name == NULL); +} + +/* exercise generated code from annotations in main() object file */ +static void test_main_object_annotations(gconstpointer opaque) +{ + TestStructMain *s1, *s2 = NULL; + QmpInputVisitor *qiv; + QmpOutputVisitor *qov; + QObject *s1_obj; + Error *err = NULL; + + s1 = g_malloc0(sizeof(TestStructMain)); + fill_test_struct(s1); + + qov = qmp_output_visitor_new(); + QIDL_VISIT_TYPE(TestStructMain, qmp_output_get_visitor(qov), &s1, NULL, + &err); + g_assert(err == NULL); + + s1_obj = qmp_output_get_qobject(qov); + qiv = qmp_input_visitor_new(s1_obj); + + qobject_decref(s1_obj); + qmp_output_visitor_cleanup(qov); + free_test_struct(s1); + + s2 = g_malloc0(sizeof(TestStructMain)); + QIDL_VISIT_TYPE(TestStructMain, qmp_input_get_visitor(qiv), &s2, NULL, + &err); + g_assert(err == NULL); + check_test_struct(s2); + + qmp_input_visitor_cleanup(qiv); + free_test_struct(s2); + + check_test_struct_properties(QIDL_PROPERTIES(TestStructMain)); +} + +/* exercise generated code from annotations in included header files */ +static void test_header_file_annotations(gconstpointer opaque) +{ + TestStructIncluded *s1, *s2 = NULL; + QmpInputVisitor *qiv; + QmpOutputVisitor *qov; + QObject *s1_obj; + Error *err = NULL; + + s1 = g_malloc0(sizeof(TestStructIncluded)); + fill_test_struct(s1); + + qov = qmp_output_visitor_new(); + QIDL_VISIT_TYPE(TestStructIncluded, qmp_output_get_visitor(qov), &s1, NULL, + &err); + g_assert(err == NULL); + + s1_obj = qmp_output_get_qobject(qov); + qiv = qmp_input_visitor_new(s1_obj); + + qobject_decref(s1_obj); + qmp_output_visitor_cleanup(qov); + free_test_struct(s1); + + s2 = g_malloc0(sizeof(TestStructIncluded)); + QIDL_VISIT_TYPE(TestStructIncluded, qmp_input_get_visitor(qiv), &s2, NULL, + &err); + g_assert(err == NULL); + check_test_struct(s2); + + qmp_input_visitor_cleanup(qiv); + free_test_struct(s2); + + check_test_struct_properties(QIDL_PROPERTIES(TestStructIncluded)); +} + +/* exercise annotations in public header files who's generated code we + * link against + */ +static void test_public_linked_object_annotations(gconstpointer opaque) +{ + TestStructPublicLinked *s1, *s2 = NULL; + QmpInputVisitor *qiv; + QmpOutputVisitor *qov; + QObject *s1_obj; + Error *err = NULL; + + s1 = g_malloc0(sizeof(TestStructPublicLinked)); + fill_test_struct(s1); + + qov = qmp_output_visitor_new(); + QIDL_VISIT_TYPE(TestStructPublicLinked, qmp_output_get_visitor(qov), &s1, + NULL, &err); + g_assert(err == NULL); + + s1_obj = qmp_output_get_qobject(qov); + qiv = qmp_input_visitor_new(s1_obj); + + qobject_decref(s1_obj); + qmp_output_visitor_cleanup(qov); + free_test_struct(s1); + + s2 = g_malloc0(sizeof(TestStructPublicLinked)); + QIDL_VISIT_TYPE(TestStructPublicLinked, qmp_input_get_visitor(qiv), &s2, + NULL, &err); + g_assert(err == NULL); + check_test_struct(s2); + + qmp_input_visitor_cleanup(qiv); + free_test_struct(s2); + + check_test_struct_properties(QIDL_PROPERTIES(TestStructPublicLinked)); +} + +typedef struct TestStructComplex TestStructComplex; + +QIDL_DECLARE(TestStructComplex) { + int8_t q_size(2) array1[4]; + size_t array2_count; + int32_t q_size(array2_count) array2[8]; + int16_t q_size((2*3)) array3[16]; + bool has_optional_array; + int32_t optional_array_count; + int8_t q_optional q_size(optional_array_count) optional_array[16]; + TestStructMain struct_array[32]; + int64_t struct_array2_count; + TestStructMain q_size(struct_array2_count) struct_array2[32]; +}; + +static void fill_test_struct_complex(TestStructComplex *s) +{ + int i; + + for (i = 0; i < 4; i++) { + s->array1[i] = i*2; + } + + s->array2_count = 6; + for (i = 0; i < s->array2_count; i++) { + s->array2[i] = i*2; + } + + for (i = 0; i < 6; i++) { + s->array3[i] = i*2; + } + + s->has_optional_array = true; + s->optional_array_count = 15; + for (i = 0; i < s->optional_array_count; i++) { + s->optional_array[i] = i*2; + } + + for (i = 0; i < 32; i++) { + fill_test_struct(&s->struct_array[i]); + } + + s->struct_array2_count = 31; + for (i = 0; i < s->struct_array2_count; i++) { + fill_test_struct(&s->struct_array2[i]); + } +} + +static void check_test_struct_complex(TestStructComplex *s) +{ + int i; + + for (i = 0; i < 4; i++) { + if (i < 2) { + g_assert_cmpint(s->array1[i], ==, i*2); + } else { + g_assert_cmpint(s->array1[i], ==, 0); + } + } + + g_assert_cmpint(s->array2_count, ==, 6); + for (i = 0; i < sizeof(s->array2)/sizeof(int32_t); i++) { + if (i < s->array2_count) { + g_assert_cmpint(s->array2[i], ==, i*2); + } else { + g_assert_cmpint(s->array2[i], ==, 0); + } + } + + g_assert(s->has_optional_array); + g_assert_cmpint(s->optional_array_count, ==, 15); + for (i = 0; i < sizeof(s->optional_array)/sizeof(int16_t); i++) { + if (i < s->optional_array_count) { + g_assert_cmpint(s->optional_array[i], ==, i*2); + } else { + g_assert_cmpint(s->optional_array[i], ==, 0); + } + } + + for (i = 0; i < 32; i++) { + check_test_struct(&s->struct_array[i]); + } + + g_assert_cmpint(s->struct_array2_count, ==, 31); + for (i = 0; i < sizeof(s->struct_array2)/sizeof(TestStructMain); i++) { + if (i < s->struct_array2_count) { + check_test_struct(&s->struct_array2[i]); + } else { + int j; + uint8_t *ptr = (uint8_t *)&s->struct_array2[i]; + for (j = 0; j < sizeof(TestStructMain); j++) { + g_assert_cmpint(ptr[0], ==, 0); + } + } + } +} + +static void test_array_annotations(gconstpointer opaque) +{ + TestStructComplex *s1, *s2 = NULL; + QmpInputVisitor *qiv; + QmpOutputVisitor *qov; + QObject *s1_obj; + Error *err = NULL; + + s1 = g_malloc0(sizeof(TestStructComplex)); + fill_test_struct_complex(s1); + + qov = qmp_output_visitor_new(); + QIDL_VISIT_TYPE(TestStructComplex, qmp_output_get_visitor(qov), &s1, NULL, + &err); + g_assert(err == NULL); + + s1_obj = qmp_output_get_qobject(qov); + qiv = qmp_input_visitor_new(s1_obj); + + qobject_decref(s1_obj); + qmp_output_visitor_cleanup(qov); + g_free(s1); + + s2 = g_malloc0(sizeof(TestStructComplex)); + QIDL_VISIT_TYPE(TestStructComplex, qmp_input_get_visitor(qiv), &s2, NULL, + &err); + g_assert(err == NULL); + check_test_struct_complex(s2); + + qmp_input_visitor_cleanup(qiv); + g_free(s2); +} + +typedef struct TestStructComplex2 TestStructComplex2; + +QIDL_DECLARE(TestStructComplex2) { + bool has_struct1; + TestStructMain q_optional *struct1; + TestStructMain embedded_struct1; +}; + +static void test_complex_annotations(gconstpointer opaque) +{ + TestStructComplex2 *s1, *s2 = NULL; + QmpInputVisitor *qiv; + QmpOutputVisitor *qov; + QObject *s1_obj; + Error *err = NULL; + + s1 = g_malloc0(sizeof(TestStructComplex)); + s1->has_struct1 = true; + s1->struct1 = g_malloc0(sizeof(TestStructMain)); + fill_test_struct(s1->struct1); + fill_test_struct(&s1->embedded_struct1); + + qov = qmp_output_visitor_new(); + QIDL_VISIT_TYPE(TestStructComplex2, qmp_output_get_visitor(qov), &s1, NULL, + &err); + g_assert(err == NULL); + + s1_obj = qmp_output_get_qobject(qov); + qiv = qmp_input_visitor_new(s1_obj); + + qobject_decref(s1_obj); + qmp_output_visitor_cleanup(qov); + free_test_struct(s1->struct1); + g_free(s1); + + s2 = g_malloc0(sizeof(TestStructComplex2)); + QIDL_VISIT_TYPE(TestStructComplex2, qmp_input_get_visitor(qiv), &s2, NULL, + &err); + g_assert(err == NULL); + check_test_struct(s2->struct1); + check_test_struct(&s2->embedded_struct1); + + qmp_input_visitor_cleanup(qiv); + free_test_struct(s2->struct1); + g_free(s2); +} + +int main(int argc, char **argv) +{ + module_call_init(MODULE_INIT_QOM); + module_call_init(MODULE_INIT_QIDL); + + g_test_init(&argc, &argv, NULL); + + g_test_add_data_func("/qidl/build_test/main_object_annotations", NULL, + test_main_object_annotations); + g_test_add_data_func("/qidl/build_test/linked_object_annotations", NULL, + test_linked_object_annotations); + g_test_add_data_func("/qidl/build_test/public_linked_object_annotations", + NULL, test_public_linked_object_annotations); + g_test_add_data_func("/qidl/build_test/public_linked_object_annotations2", + NULL, test_public_linked_object_annotations2); + g_test_add_data_func("/qidl/build_test/header_file_annotations", NULL, + test_header_file_annotations); + g_test_add_data_func("/qidl/build_test/array_annotations", NULL, + test_array_annotations); + g_test_add_data_func("/qidl/build_test/complex_annotations", NULL, + test_complex_annotations); + + g_test_run(); + + return 0; +} diff --git a/tests/test-qidl.h b/tests/test-qidl.h new file mode 100644 index 0000000..ddb03ad --- /dev/null +++ b/tests/test-qidl.h @@ -0,0 +1,36 @@ +/* + * Unit-tests for QIDL-generated visitors/code + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Michael Roth + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef TEST_QIDL_H +#define TEST_QIDL_H + +#include "qidl.h" + +#define TEST_QIDL_STRUCT_BODY \ + int32_t q_immutable a; \ + int32_t b; \ + uint32_t q_immutable c; \ + uint32_t d; \ + uint64_t q_immutable e; \ + uint64_t q_property("f", 42) f; \ + char *g; \ + char q_property("h") *h; + +void fill_test_struct(void *opaque); +void check_test_struct(void *opaque); +void free_test_struct(void *opaque); +void check_test_struct_properties(const Property *props); + +void test_linked_object_annotations(gconstpointer opaque); +void test_public_linked_object_annotations2(gconstpointer opaque); + +#endif