From patchwork Tue Aug 18 16:05:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 508378 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 1D39914012C for ; Wed, 19 Aug 2015 02:06:28 +1000 (AEST) Received: from localhost ([::1]:58245 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZRjP8-0008KA-5y for incoming@patchwork.ozlabs.org; Tue, 18 Aug 2015 12:06:26 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52661) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZRjOC-0006ZE-7G for qemu-devel@nongnu.org; Tue, 18 Aug 2015 12:05:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZRjOA-0000Lk-52 for qemu-devel@nongnu.org; Tue, 18 Aug 2015 12:05:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40636) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZRjO9-0000LW-RD for qemu-devel@nongnu.org; Tue, 18 Aug 2015 12:05:26 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id 7D70E91D09; Tue, 18 Aug 2015 16:05:25 +0000 (UTC) Received: from red.redhat.com (ovpn-113-20.phx2.redhat.com [10.3.113.20]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t7IG5KQG028378; Tue, 18 Aug 2015 12:05:25 -0400 From: Eric Blake To: qemu-devel@nongnu.org Date: Tue, 18 Aug 2015 09:05:18 -0700 Message-Id: <1439913918-12866-9-git-send-email-eblake@redhat.com> In-Reply-To: <1439907602-11414-1-git-send-email-eblake@redhat.com> References: <1439907602-11414-1-git-send-email-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: armbru@redhat.com, Michael Roth Subject: [Qemu-devel] [PATCH RFC v3 20/20] qapi: Support boxed unions 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 This patch completes support for boxed types, by allowing union types to be used when 'box':true is specified. It also avoids a python crash when attempting to use boxing on an anonymous type. While it was possible to support 'box':true on an empty event, it was easier to just reject missing 'data' for commands. Add some tests to cover new error messages, as well as enhancing qapi-schema-test to cover situations that are now valid. Signed-off-by: Eric Blake --- scripts/qapi.py | 20 ++++++++++++++++---- tests/Makefile | 4 ++-- tests/qapi-schema/args-bad-box.err | 1 + tests/qapi-schema/args-bad-box.exit | 1 + tests/qapi-schema/args-bad-box.json | 2 ++ tests/qapi-schema/args-bad-box.out | 0 tests/qapi-schema/args-box-anon.err | 1 + tests/qapi-schema/args-box-anon.exit | 1 + tests/qapi-schema/args-box-anon.json | 2 ++ tests/qapi-schema/args-box-anon.out | 0 tests/qapi-schema/args-box-empty.err | 1 + tests/qapi-schema/args-box-empty.exit | 1 + tests/qapi-schema/args-box-empty.json | 2 ++ tests/qapi-schema/args-box-empty.out | 0 tests/qapi-schema/args-union.err | 2 +- tests/qapi-schema/args-union.json | 3 +-- tests/qapi-schema/qapi-schema-test.json | 3 ++- tests/qapi-schema/qapi-schema-test.out | 4 +++- tests/test-qmp-commands.c | 4 ++++ 19 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 tests/qapi-schema/args-bad-box.err create mode 100644 tests/qapi-schema/args-bad-box.exit create mode 100644 tests/qapi-schema/args-bad-box.json create mode 100644 tests/qapi-schema/args-bad-box.out create mode 100644 tests/qapi-schema/args-box-anon.err create mode 100644 tests/qapi-schema/args-box-anon.exit create mode 100644 tests/qapi-schema/args-box-anon.json create mode 100644 tests/qapi-schema/args-box-anon.out create mode 100644 tests/qapi-schema/args-box-empty.err create mode 100644 tests/qapi-schema/args-box-empty.exit create mode 100644 tests/qapi-schema/args-box-empty.json create mode 100644 tests/qapi-schema/args-box-empty.out diff --git a/scripts/qapi.py b/scripts/qapi.py index b907878..1e73500 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -491,10 +491,18 @@ def check_member_clash(expr_info, base_name, data, source = ""): def check_command(expr, expr_info): name = expr['command'] + box = expr.get('box', False) + args_meta = ['struct'] + if box: + args_meta += ['union'] + if not expr.get('data'): + raise QAPIExprError(expr_info, + "Use of 'box' requires 'data' for command '%s'" + % name) check_type(expr_info, "'data' for command '%s'" % name, - expr.get('data'), allow_dict=True, allow_optional=True, - allow_metas=['struct']) + expr.get('data'), allow_dict=not box, allow_optional=True, + allow_metas=args_meta) returns_meta = ['union', 'struct'] if name in returns_whitelist: returns_meta += ['built-in', 'alternate', 'enum'] @@ -505,13 +513,17 @@ def check_command(expr, expr_info): def check_event(expr, expr_info): global events name = expr['event'] + box = expr.get('box', False) + meta = ['struct'] + if box: + meta += ['union'] if name.upper() == 'MAX': raise QAPIExprError(expr_info, "Event name 'MAX' cannot be created") events.append(name) check_type(expr_info, "'data' for event '%s'" % name, - expr.get('data'), allow_dict=True, allow_optional=True, - allow_metas=['struct']) + expr.get('data'), allow_dict=not box, allow_optional=True, + allow_metas=meta) def check_union(expr, expr_info): name = expr['union'] diff --git a/tests/Makefile b/tests/Makefile index 8838f11..33578ea 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -228,11 +228,11 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \ bad-type-dict.json double-data.json unknown-expr-key.json \ redefined-type.json redefined-command.json redefined-builtin.json \ redefined-event.json command-int.json bad-data.json event-max.json \ - type-bypass-bad-gen.json \ + type-bypass-bad-gen.json args-bad-box.json \ args-array-empty.json args-array-unknown.json args-int.json \ args-unknown.json args-member-unknown.json args-member-array.json \ args-member-array-bad.json args-alternate.json args-union.json \ - args-any.json \ + args-any.json args-box-anon.json args-box-empty.json \ returns-array-bad.json returns-int.json returns-dict.json \ returns-unknown.json returns-alternate.json returns-whitelist.json \ missing-colon.json missing-comma-list.json missing-comma-object.json \ diff --git a/tests/qapi-schema/args-bad-box.err b/tests/qapi-schema/args-bad-box.err new file mode 100644 index 0000000..16afe3c --- /dev/null +++ b/tests/qapi-schema/args-bad-box.err @@ -0,0 +1 @@ +tests/qapi-schema/args-bad-box.json:2: 'box' of command 'foo' should only use true value diff --git a/tests/qapi-schema/args-bad-box.exit b/tests/qapi-schema/args-bad-box.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/args-bad-box.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/args-bad-box.json b/tests/qapi-schema/args-bad-box.json new file mode 100644 index 0000000..8d5737a --- /dev/null +++ b/tests/qapi-schema/args-bad-box.json @@ -0,0 +1,2 @@ +# 'box' should only appear with value true +{ 'command': 'foo', 'box': false } diff --git a/tests/qapi-schema/args-bad-box.out b/tests/qapi-schema/args-bad-box.out new file mode 100644 index 0000000..e69de29 diff --git a/tests/qapi-schema/args-box-anon.err b/tests/qapi-schema/args-box-anon.err new file mode 100644 index 0000000..11eaefc --- /dev/null +++ b/tests/qapi-schema/args-box-anon.err @@ -0,0 +1 @@ +tests/qapi-schema/args-box-anon.json:2: 'data' for command 'foo' should be a type name diff --git a/tests/qapi-schema/args-box-anon.exit b/tests/qapi-schema/args-box-anon.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/args-box-anon.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/args-box-anon.json b/tests/qapi-schema/args-box-anon.json new file mode 100644 index 0000000..947e3c6 --- /dev/null +++ b/tests/qapi-schema/args-box-anon.json @@ -0,0 +1,2 @@ +# 'box' can only be used with named types +{ 'command': 'foo', 'box': true, 'data': { 'string': 'str' } } diff --git a/tests/qapi-schema/args-box-anon.out b/tests/qapi-schema/args-box-anon.out new file mode 100644 index 0000000..e69de29 diff --git a/tests/qapi-schema/args-box-empty.err b/tests/qapi-schema/args-box-empty.err new file mode 100644 index 0000000..574c8b5 --- /dev/null +++ b/tests/qapi-schema/args-box-empty.err @@ -0,0 +1 @@ +tests/qapi-schema/args-box-empty.json:2: Use of 'box' requires 'data' for command 'foo' diff --git a/tests/qapi-schema/args-box-empty.exit b/tests/qapi-schema/args-box-empty.exit new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/qapi-schema/args-box-empty.exit @@ -0,0 +1 @@ +1 diff --git a/tests/qapi-schema/args-box-empty.json b/tests/qapi-schema/args-box-empty.json new file mode 100644 index 0000000..31dca5e --- /dev/null +++ b/tests/qapi-schema/args-box-empty.json @@ -0,0 +1,2 @@ +# 'box' can only be used with named types +{ 'command': 'foo', 'box': true } diff --git a/tests/qapi-schema/args-box-empty.out b/tests/qapi-schema/args-box-empty.out new file mode 100644 index 0000000..e69de29 diff --git a/tests/qapi-schema/args-union.err b/tests/qapi-schema/args-union.err index 1d693d7..f8ad223 100644 --- a/tests/qapi-schema/args-union.err +++ b/tests/qapi-schema/args-union.err @@ -1 +1 @@ -tests/qapi-schema/args-union.json:4: 'data' for command 'oops' cannot use union type 'Uni' +tests/qapi-schema/args-union.json:3: 'data' for command 'oops' cannot use union type 'Uni' diff --git a/tests/qapi-schema/args-union.json b/tests/qapi-schema/args-union.json index 7bdcbb7..c0ce091 100644 --- a/tests/qapi-schema/args-union.json +++ b/tests/qapi-schema/args-union.json @@ -1,4 +1,3 @@ -# we do not allow union arguments -# TODO should we support this? +# use of union arguments requires 'box':true { 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } } { 'command': 'oops', 'data': 'Uni' } diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 4acb57a..b4893ce 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -94,6 +94,7 @@ # note: command name 'guest-sync' chosen to avoid "cannot use built-in" error { 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' } { 'command': 'boxed', 'box': true, 'data': 'UserDefZero' } +{ 'command': 'boxed2', 'data': 'UserDefNativeListUnion', 'box': true } # For testing integer range flattening in opts-visitor. The following schema # corresponds to the option format: @@ -114,7 +115,7 @@ { 'struct': 'EventStructOne', 'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } } -{ 'event': 'EVENT_A' } +{ 'event': 'EVENT_A', 'box': true } { 'event': 'EVENT_B', 'data': { } } { 'event': 'EVENT_C', diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out index 8b120ee..89f50b8 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -70,7 +70,7 @@ alternate AltTwo case s: str case n: number event EVENT_A None - box=False + box=True event EVENT_B None box=False event EVENT_C :obj-EVENT_C-arg @@ -177,6 +177,8 @@ command __org.qemu_x-command :obj-__org.qemu_x-command-arg -> __org.qemu_x-Union gen=True success_response=True box=False command boxed UserDefZero -> None gen=True success_response=True box=True +command boxed2 UserDefNativeListUnion -> None + gen=True success_response=True box=True command guest-sync :obj-guest-sync-arg -> any gen=True success_response=True box=False command user_def_cmd None -> None diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c index a190f31..886de98 100644 --- a/tests/test-qmp-commands.c +++ b/tests/test-qmp-commands.c @@ -58,6 +58,10 @@ void qmp_boxed(UserDefZero *arg, Error **errp) { } +void qmp_boxed2(UserDefNativeListUnion *arg, Error **errp) +{ +} + __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a, __org_qemu_x_StructList *b, __org_qemu_x_Union2 *c,