From patchwork Tue May 5 16:47:19 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Markus Armbruster X-Patchwork-Id: 468237 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 1C6661402AB for ; Wed, 6 May 2015 03:10:19 +1000 (AEST) Received: from localhost ([::1]:40882 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YpgML-0005zY-0r for incoming@patchwork.ozlabs.org; Tue, 05 May 2015 13:10:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52708) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ypg0g-0001n1-G8 for qemu-devel@nongnu.org; Tue, 05 May 2015 12:47:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Ypg0Z-0006GP-SQ for qemu-devel@nongnu.org; Tue, 05 May 2015 12:47:54 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49018) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Ypg0Z-0006GE-HV for qemu-devel@nongnu.org; Tue, 05 May 2015 12:47:47 -0400 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t45Glkbt030148 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Tue, 5 May 2015 12:47:47 -0400 Received: from blackfin.pond.sub.org (ovpn-116-60.ams2.redhat.com [10.36.116.60]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t45GlbsE017924 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 5 May 2015 12:47:44 -0400 Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 905313043908; Tue, 5 May 2015 18:47:28 +0200 (CEST) From: Markus Armbruster To: qemu-devel@nongnu.org Date: Tue, 5 May 2015 18:47:19 +0200 Message-Id: <1430844446-12491-34-git-send-email-armbru@redhat.com> In-Reply-To: <1430844446-12491-1-git-send-email-armbru@redhat.com> References: <1430844446-12491-1-git-send-email-armbru@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 33/40] qapi: Drop tests for inline nested structs 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 From: Eric Blake A future patch will be using a 'name':{dictionary} entry in the QAPI schema to specify a default value for an optional argument; but existing use of inline nested structs conflicts with that goal. More precisely, a definition in the QAPI schema associates a name with a set of properties: Example 1: { 'struct': 'Foo', 'data': { MEMBERS... } } associates the global name 'Foo' with properties (meta-type struct) and MEMBERS... Example 2: 'mumble': TYPE within MEMBERS... above associates 'mumble' with properties (type TYPE) and (optional false) within type Foo The syntax of example 1 is extensible; if we need another property, we add another name/value pair to the dictionary (such as 'base':TYPE). The syntax of example 2 is not extensible, because the right hand side can only be a type. We have used name encoding to add a property: "'*mumble': 'int'" associates 'mumble' with (type int) and (optional true). Nice, but doesn't scale. So the solution is to change our existing uses to be syntactic sugar to an extensible form: NAME: TYPE --> NAME: { 'type': TYPE, 'optional': false } *ONAME: TYPE --> ONAME: { 'type': TYPE, 'optional': true } This patch fixes the testsuite to avoid inline nested types, by breaking the nesting into explicit types; it means that the type is now boxed instead of unboxed in C code, but makes no difference on the wire (and if desired, a later patch could change the generator to not do so much boxing in C). When touching code to add new allocations, also convert existing allocations to consistently prefer typesafe g_new0 over g_malloc0 when a type name is involved. Signed-off-by: Eric Blake Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- tests/qapi-schema/qapi-schema-test.json | 12 ++++++-- tests/qapi-schema/qapi-schema-test.out | 8 +++-- tests/test-qmp-commands.c | 17 ++++++----- tests/test-qmp-input-visitor.c | 14 +++++---- tests/test-qmp-output-visitor.c | 44 +++++++++++++++------------ tests/test-visitor-serialization.c | 54 ++++++++++++++++++--------------- 6 files changed, 88 insertions(+), 61 deletions(-) diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index a6be983..8193dc1 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -14,11 +14,17 @@ 'base': 'UserDefZero', 'data': { 'string': 'str', '*enum1': 'EnumOne' } } +{ 'struct': 'UserDefTwoDictDict', + 'data': { 'userdef': 'UserDefOne', 'string': 'str' } } + +{ 'struct': 'UserDefTwoDict', + 'data': { 'string1': 'str', + 'dict2': 'UserDefTwoDictDict', + '*dict3': 'UserDefTwoDictDict' } } + { 'struct': 'UserDefTwo', 'data': { 'string0': 'str', - 'dict1': { 'string1': 'str', - 'dict2': { 'userdef': 'UserDefOne', 'string': 'str' }, - '*dict3': { 'userdef': 'UserDefOne', 'string': 'str' } } } } + 'dict1': 'UserDefTwoDict' } } # for testing unions { 'struct': 'UserDefA', diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 48f8f0e..93c4963 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -2,7 +2,9 @@ OrderedDict([('struct', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]), OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('struct', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]), - OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')])), ('*dict3', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]))]))]), + OrderedDict([('struct', 'UserDefTwoDictDict'), ('data', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]), + OrderedDict([('struct', 'UserDefTwoDict'), ('data', OrderedDict([('string1', 'str'), ('dict2', 'UserDefTwoDictDict'), ('*dict3', 'UserDefTwoDictDict')]))]), + OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', 'UserDefTwoDict')]))]), OrderedDict([('struct', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]), OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]), @@ -27,7 +29,9 @@ [OrderedDict([('struct', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]), OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('struct', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]), - OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', OrderedDict([('string1', 'str'), ('dict2', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')])), ('*dict3', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]))]))]), + OrderedDict([('struct', 'UserDefTwoDictDict'), ('data', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]), + OrderedDict([('struct', 'UserDefTwoDict'), ('data', OrderedDict([('string1', 'str'), ('dict2', 'UserDefTwoDictDict'), ('*dict3', 'UserDefTwoDictDict')]))]), + OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', 'UserDefTwoDict')]))]), OrderedDict([('struct', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]), OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]), OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]), diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index 8b50eac..ad2e403 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -33,12 +33,15 @@ UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a, ret = g_new0(UserDefTwo, 1); ret->string0 = strdup("blah1"); - ret->dict1.string1 = strdup("blah2"); - ret->dict1.dict2.userdef = ud1c; - ret->dict1.dict2.string = strdup("blah3"); - ret->dict1.has_dict3 = true; - ret->dict1.dict3.userdef = ud1d; - ret->dict1.dict3.string = strdup("blah4"); + ret->dict1 = g_new0(UserDefTwoDict, 1); + ret->dict1->string1 = strdup("blah2"); + ret->dict1->dict2 = g_new0(UserDefTwoDictDict, 1); + ret->dict1->dict2->userdef = ud1c; + ret->dict1->dict2->string = strdup("blah3"); + ret->dict1->dict3 = g_new0(UserDefTwoDictDict, 1); + ret->dict1->has_dict3 = true; + ret->dict1->dict3->userdef = ud1d; + ret->dict1->dict3->string = strdup("blah4"); return ret; } @@ -204,7 +207,7 @@ static void test_dealloc_partial(void) assert(ud2 != NULL); assert(ud2->string0 != NULL); assert(strcmp(ud2->string0, text) == 0); - assert(ud2->dict1.dict2.userdef == NULL); + assert(ud2->dict1 == NULL); /* confirm & release construction error */ assert(err != NULL); diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c index 115fb22..b961953 100644 --- a/tests/test-qmp-input-visitor.c +++ b/tests/test-qmp-input-visitor.c @@ -261,13 +261,15 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data, g_assert(!err); check_and_free_str(udp->string0, "string0"); - check_and_free_str(udp->dict1.string1, "string1"); - g_assert_cmpint(udp->dict1.dict2.userdef->base->integer, ==, 42); - check_and_free_str(udp->dict1.dict2.userdef->string, "string"); - check_and_free_str(udp->dict1.dict2.string, "string2"); - g_assert(udp->dict1.has_dict3 == false); + check_and_free_str(udp->dict1->string1, "string1"); + g_assert_cmpint(udp->dict1->dict2->userdef->base->integer, ==, 42); + check_and_free_str(udp->dict1->dict2->userdef->string, "string"); + check_and_free_str(udp->dict1->dict2->string, "string2"); + g_assert(udp->dict1->has_dict3 == false); - g_free(udp->dict1.dict2.userdef); + g_free(udp->dict1->dict2->userdef); + g_free(udp->dict1->dict2); + g_free(udp->dict1); g_free(udp); } diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c index 0584b4d..f8c9367 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -244,19 +244,23 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data, ud2 = g_malloc0(sizeof(*ud2)); ud2->string0 = g_strdup(strings[0]); - ud2->dict1.string1 = g_strdup(strings[1]); - ud2->dict1.dict2.userdef = g_new0(UserDefOne, 1); - ud2->dict1.dict2.userdef->string = g_strdup(string); - ud2->dict1.dict2.userdef->base = g_new0(UserDefZero, 1); - ud2->dict1.dict2.userdef->base->integer = value; - ud2->dict1.dict2.string = g_strdup(strings[2]); + ud2->dict1 = g_malloc0(sizeof(*ud2->dict1)); + ud2->dict1->string1 = g_strdup(strings[1]); - ud2->dict1.has_dict3 = true; - ud2->dict1.dict3.userdef = g_new0(UserDefOne, 1); - ud2->dict1.dict3.userdef->string = g_strdup(string); - ud2->dict1.dict3.userdef->base = g_new0(UserDefZero, 1); - ud2->dict1.dict3.userdef->base->integer = value; - ud2->dict1.dict3.string = g_strdup(strings[3]); + ud2->dict1->dict2 = g_malloc0(sizeof(*ud2->dict1->dict2)); + ud2->dict1->dict2->userdef = g_new0(UserDefOne, 1); + ud2->dict1->dict2->userdef->string = g_strdup(string); + ud2->dict1->dict2->userdef->base = g_new0(UserDefZero, 1); + ud2->dict1->dict2->userdef->base->integer = value; + ud2->dict1->dict2->string = g_strdup(strings[2]); + + ud2->dict1->dict3 = g_malloc0(sizeof(*ud2->dict1->dict3)); + ud2->dict1->has_dict3 = true; + ud2->dict1->dict3->userdef = g_new0(UserDefOne, 1); + ud2->dict1->dict3->userdef->string = g_strdup(string); + ud2->dict1->dict3->userdef->base = g_new0(UserDefZero, 1); + ud2->dict1->dict3->userdef->base->integer = value; + ud2->dict1->dict3->string = g_strdup(strings[3]); visit_type_UserDefTwo(data->ov, &ud2, "unused", &err); g_assert(!err); @@ -407,13 +411,15 @@ static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data, p->value = g_malloc0(sizeof(*p->value)); p->value->string0 = g_strdup(string); - p->value->dict1.string1 = g_strdup(string); - p->value->dict1.dict2.userdef = g_new0(UserDefOne, 1); - p->value->dict1.dict2.userdef->string = g_strdup(string); - p->value->dict1.dict2.userdef->base = g_new0(UserDefZero, 1); - p->value->dict1.dict2.userdef->base->integer = 42; - p->value->dict1.dict2.string = g_strdup(string); - p->value->dict1.has_dict3 = false; + p->value->dict1 = g_new0(UserDefTwoDict, 1); + p->value->dict1->string1 = g_strdup(string); + p->value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1); + p->value->dict1->dict2->userdef = g_new0(UserDefOne, 1); + p->value->dict1->dict2->userdef->string = g_strdup(string); + p->value->dict1->dict2->userdef->base = g_new0(UserDefZero, 1); + p->value->dict1->dict2->userdef->base->integer = 42; + p->value->dict1->dict2->string = g_strdup(string); + p->value->dict1->has_dict3 = false; p->next = head; head = p; diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c index 1ccaaa9..fa86cae 100644 --- a/tests/test-visitor-serialization.c +++ b/tests/test-visitor-serialization.c @@ -1,6 +1,7 @@ /* * Unit-tests for visitor-based serialization * + * Copyright (C) 2014-2015 Red Hat, Inc. * Copyright IBM, Corp. 2012 * * Authors: @@ -253,18 +254,21 @@ static UserDefTwo *nested_struct_create(void) { UserDefTwo *udnp = g_malloc0(sizeof(*udnp)); udnp->string0 = strdup("test_string0"); - udnp->dict1.string1 = strdup("test_string1"); - udnp->dict1.dict2.userdef = g_new0(UserDefOne, 1); - udnp->dict1.dict2.userdef->base = g_new0(UserDefZero, 1); - udnp->dict1.dict2.userdef->base->integer = 42; - udnp->dict1.dict2.userdef->string = strdup("test_string"); - udnp->dict1.dict2.string = strdup("test_string2"); - udnp->dict1.has_dict3 = true; - udnp->dict1.dict3.userdef = g_new0(UserDefOne, 1); - udnp->dict1.dict3.userdef->base = g_new0(UserDefZero, 1); - udnp->dict1.dict3.userdef->base->integer = 43; - udnp->dict1.dict3.userdef->string = strdup("test_string"); - udnp->dict1.dict3.string = strdup("test_string3"); + udnp->dict1 = g_malloc0(sizeof(*udnp->dict1)); + udnp->dict1->string1 = strdup("test_string1"); + udnp->dict1->dict2 = g_malloc0(sizeof(*udnp->dict1->dict2)); + udnp->dict1->dict2->userdef = g_new0(UserDefOne, 1); + udnp->dict1->dict2->userdef->base = g_new0(UserDefZero, 1); + udnp->dict1->dict2->userdef->base->integer = 42; + udnp->dict1->dict2->userdef->string = strdup("test_string"); + udnp->dict1->dict2->string = strdup("test_string2"); + udnp->dict1->dict3 = g_malloc0(sizeof(*udnp->dict1->dict3)); + udnp->dict1->has_dict3 = true; + udnp->dict1->dict3->userdef = g_new0(UserDefOne, 1); + udnp->dict1->dict3->userdef->base = g_new0(UserDefZero, 1); + udnp->dict1->dict3->userdef->base->integer = 43; + udnp->dict1->dict3->userdef->string = strdup("test_string"); + udnp->dict1->dict3->string = strdup("test_string3"); return udnp; } @@ -273,18 +277,20 @@ static void nested_struct_compare(UserDefTwo *udnp1, UserDefTwo *udnp2) g_assert(udnp1); g_assert(udnp2); g_assert_cmpstr(udnp1->string0, ==, udnp2->string0); - g_assert_cmpstr(udnp1->dict1.string1, ==, udnp2->dict1.string1); - g_assert_cmpint(udnp1->dict1.dict2.userdef->base->integer, ==, - udnp2->dict1.dict2.userdef->base->integer); - g_assert_cmpstr(udnp1->dict1.dict2.userdef->string, ==, - udnp2->dict1.dict2.userdef->string); - g_assert_cmpstr(udnp1->dict1.dict2.string, ==, udnp2->dict1.dict2.string); - g_assert(udnp1->dict1.has_dict3 == udnp2->dict1.has_dict3); - g_assert_cmpint(udnp1->dict1.dict3.userdef->base->integer, ==, - udnp2->dict1.dict3.userdef->base->integer); - g_assert_cmpstr(udnp1->dict1.dict3.userdef->string, ==, - udnp2->dict1.dict3.userdef->string); - g_assert_cmpstr(udnp1->dict1.dict3.string, ==, udnp2->dict1.dict3.string); + g_assert_cmpstr(udnp1->dict1->string1, ==, udnp2->dict1->string1); + g_assert_cmpint(udnp1->dict1->dict2->userdef->base->integer, ==, + udnp2->dict1->dict2->userdef->base->integer); + g_assert_cmpstr(udnp1->dict1->dict2->userdef->string, ==, + udnp2->dict1->dict2->userdef->string); + g_assert_cmpstr(udnp1->dict1->dict2->string, ==, + udnp2->dict1->dict2->string); + g_assert(udnp1->dict1->has_dict3 == udnp2->dict1->has_dict3); + g_assert_cmpint(udnp1->dict1->dict3->userdef->base->integer, ==, + udnp2->dict1->dict3->userdef->base->integer); + g_assert_cmpstr(udnp1->dict1->dict3->userdef->string, ==, + udnp2->dict1->dict3->userdef->string); + g_assert_cmpstr(udnp1->dict1->dict3->string, ==, + udnp2->dict1->dict3->string); } static void nested_struct_cleanup(UserDefTwo *udnp)