From: Markus Armbruster <armbru@redhat.com>
To: Eric Blake <eblake@redhat.com>
Cc: Fam Zheng <famz@redhat.com>,
qemu-devel@nongnu.org, wenchaoqemu@gmail.com,
Luiz Capitulino <lcapitulino@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v4 06/19] qapi: Better error messages for bad enums
Date: Tue, 23 Sep 2014 16:23:29 +0200 [thread overview]
Message-ID: <874mvyiffi.fsf@blackfin.pond.sub.org> (raw)
In-Reply-To: <1411165504-18198-7-git-send-email-eblake@redhat.com> (Eric Blake's message of "Fri, 19 Sep 2014 16:24:51 -0600")
Eric Blake <eblake@redhat.com> writes:
> The previous commit demonstrated that the generator had several
> flaws with less-than-perfect enums:
> - an enum that listed the same string twice (or two variant
> strings that map to the same C enum) ended up generating an
> invalid C enum
> - because the generator adds a _MAX terminator to each enum,
> the use of an enum member 'max' can also cause this clash
> - if an enum omits 'data', the generator left a python stack
> trace rather than a graceful message
> - an enum used a non-array 'data' was silently accepted by
> the parser
> - an enum that used non-string members in the 'data' member
> was silently accepted by the parser
>
> Add check_enum to cover these situations, and update testcases
> to match. While valid .json files won't trigger any of these
> cases, we might as well be nicer to developers that make a typo
> while trying to add new QAPI code.
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
> scripts/qapi.py | 32 ++++++++++++++++++++++++++++----
> tests/qapi-schema/enum-clash-member.err | 1 +
> tests/qapi-schema/enum-clash-member.exit | 2 +-
> tests/qapi-schema/enum-clash-member.json | 2 +-
> tests/qapi-schema/enum-clash-member.out | 3 ---
> tests/qapi-schema/enum-dict-member.err | 1 +
> tests/qapi-schema/enum-dict-member.exit | 2 +-
> tests/qapi-schema/enum-dict-member.json | 2 +-
> tests/qapi-schema/enum-dict-member.out | 3 ---
> tests/qapi-schema/enum-max-member.err | 1 +
> tests/qapi-schema/enum-max-member.exit | 2 +-
> tests/qapi-schema/enum-max-member.json | 4 ++--
> tests/qapi-schema/enum-max-member.out | 3 ---
> tests/qapi-schema/enum-missing-data.err | 7 +------
> tests/qapi-schema/enum-missing-data.json | 2 +-
> tests/qapi-schema/enum-wrong-data.err | 1 +
> tests/qapi-schema/enum-wrong-data.exit | 2 +-
> tests/qapi-schema/enum-wrong-data.json | 2 +-
> tests/qapi-schema/enum-wrong-data.out | 3 ---
> 19 files changed, 43 insertions(+), 32 deletions(-)
>
> diff --git a/scripts/qapi.py b/scripts/qapi.py
> index 77d46aa..85aa8bf 100644
> --- a/scripts/qapi.py
> +++ b/scripts/qapi.py
> @@ -2,7 +2,7 @@
> # QAPI helper library
> #
> # Copyright IBM, Corp. 2011
> -# Copyright (c) 2013 Red Hat Inc.
> +# Copyright (c) 2013-2014 Red Hat Inc.
> #
> # Authors:
> # Anthony Liguori <aliguori@us.ibm.com>
> @@ -316,13 +316,37 @@ def check_union(expr, expr_info):
> # Todo: add checking for values. Key is checked as above, value can be
> # also checked here, but we need more functions to handle array case.
>
> +def check_enum(expr, expr_info):
> + name = expr['enum']
> + members = expr.get('data')
> + values = { 'MAX': '(automatic)' }
> +
> + if not isinstance(members, list):
> + raise QAPIExprError(expr_info,
> + "enum '%s' requires an array for 'data'" % name)
> + for member in members:
> + if not isinstance(member, basestring):
> + raise QAPIExprError(expr_info,
> + "enum '%s' member '%s' is not a string"
> + % (name, member))
> + key = _generate_enum_string(member)
> + if key in values:
> + raise QAPIExprError(expr_info,
> + "enum '%s' member '%s' clashes with '%s'"
> + % (name, member, values[key]))
> + values[key] = member
> +
> def check_exprs(schema):
> for expr_elem in schema.exprs:
> expr = expr_elem['expr']
> + info = expr_elem['info']
> +
> if expr.has_key('union'):
> - check_union(expr, expr_elem['info'])
> + check_union(expr, info)
> if expr.has_key('event'):
> - check_event(expr, expr_elem['info'])
> + check_event(expr, info)
> + if expr.has_key('enum'):
> + check_enum(expr, info)
>
> def parse_schema(input_file):
> try:
> @@ -336,7 +360,7 @@ def parse_schema(input_file):
> for expr_elem in schema.exprs:
> expr = expr_elem['expr']
> if expr.has_key('enum'):
> - add_enum(expr['enum'], expr['data'])
> + add_enum(expr['enum'], expr.get('data'))
> elif expr.has_key('union'):
> add_union(expr)
> elif expr.has_key('type'):
> diff --git a/tests/qapi-schema/enum-clash-member.err b/tests/qapi-schema/enum-clash-member.err
> index e69de29..3731fc2 100644
> --- a/tests/qapi-schema/enum-clash-member.err
> +++ b/tests/qapi-schema/enum-clash-member.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/enum-clash-member.json:2: enum 'MyEnum' member 'ONE' clashes with 'one'
> diff --git a/tests/qapi-schema/enum-clash-member.exit b/tests/qapi-schema/enum-clash-member.exit
> index 573541a..d00491f 100644
> --- a/tests/qapi-schema/enum-clash-member.exit
> +++ b/tests/qapi-schema/enum-clash-member.exit
> @@ -1 +1 @@
> -0
> +1
> diff --git a/tests/qapi-schema/enum-clash-member.json b/tests/qapi-schema/enum-clash-member.json
> index cb4b428..c668ff5 100644
> --- a/tests/qapi-schema/enum-clash-member.json
> +++ b/tests/qapi-schema/enum-clash-member.json
> @@ -1,2 +1,2 @@
> -# FIXME: we should reject enums where members will clash in C switch
> +# we reject enums where members will clash in C switch
> { 'enum': 'MyEnum', 'data': [ 'one', 'ONE' ] }
Actually in PATCH 05 already: "clash in C switch". I guess you mean we
generate an enum with clashing enumeration constants. In the test case,
we'd generate MY_ENUM_ONE (I think) both for 'one' and 'ONE'. Correct?
> diff --git a/tests/qapi-schema/enum-clash-member.out b/tests/qapi-schema/enum-clash-member.out
> index 0814459..e69de29 100644
> --- a/tests/qapi-schema/enum-clash-member.out
> +++ b/tests/qapi-schema/enum-clash-member.out
> @@ -1,3 +0,0 @@
> -[OrderedDict([('enum', 'MyEnum'), ('data', ['one', 'ONE'])])]
> -[{'enum_name': 'MyEnum', 'enum_values': ['one', 'ONE']}]
> -[]
> diff --git a/tests/qapi-schema/enum-dict-member.err b/tests/qapi-schema/enum-dict-member.err
> index e69de29..f5a8ffe 100644
> --- a/tests/qapi-schema/enum-dict-member.err
> +++ b/tests/qapi-schema/enum-dict-member.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/enum-dict-member.json:2: enum 'MyEnum' member 'OrderedDict([('value', 'str')])' is not a string
Error message is in terms of implementation instead of source. Since
this is merely a development tool, it'll do. Same elsewhere, and I'm
not going to flag it. Precedents in master quite possible.
> diff --git a/tests/qapi-schema/enum-dict-member.exit b/tests/qapi-schema/enum-dict-member.exit
> index 573541a..d00491f 100644
> --- a/tests/qapi-schema/enum-dict-member.exit
> +++ b/tests/qapi-schema/enum-dict-member.exit
> @@ -1 +1 @@
> -0
> +1
> diff --git a/tests/qapi-schema/enum-dict-member.json b/tests/qapi-schema/enum-dict-member.json
> index de4d6bf..79672e0 100644
> --- a/tests/qapi-schema/enum-dict-member.json
> +++ b/tests/qapi-schema/enum-dict-member.json
> @@ -1,2 +1,2 @@
> -# FIXME: we should reject any enum member that is not a string
> +# we reject any enum member that is not a string
> { 'enum': 'MyEnum', 'data': [ { 'value': 'str' } ] }
> diff --git a/tests/qapi-schema/enum-dict-member.out b/tests/qapi-schema/enum-dict-member.out
> index 8b293f8..e69de29 100644
> --- a/tests/qapi-schema/enum-dict-member.out
> +++ b/tests/qapi-schema/enum-dict-member.out
> @@ -1,3 +0,0 @@
> -[OrderedDict([('enum', 'MyEnum'), ('data', [OrderedDict([('value', 'str')])])])]
> -[{'enum_name': 'MyEnum', 'enum_values': [OrderedDict([('value', 'str')])]}]
> -[]
> diff --git a/tests/qapi-schema/enum-max-member.err b/tests/qapi-schema/enum-max-member.err
> index e69de29..a6c5db1 100644
> --- a/tests/qapi-schema/enum-max-member.err
> +++ b/tests/qapi-schema/enum-max-member.err
> @@ -0,0 +1 @@
> +tests/qapi-schema/enum-max-member.json:3: enum 'MyEnum' member 'max' clashes with '(automatic)'
> diff --git a/tests/qapi-schema/enum-max-member.exit b/tests/qapi-schema/enum-max-member.exit
> index 573541a..d00491f 100644
> --- a/tests/qapi-schema/enum-max-member.exit
> +++ b/tests/qapi-schema/enum-max-member.exit
> @@ -1 +1 @@
> -0
> +1
> diff --git a/tests/qapi-schema/enum-max-member.json b/tests/qapi-schema/enum-max-member.json
> index ea854c4..6af4662 100644
> --- a/tests/qapi-schema/enum-max-member.json
> +++ b/tests/qapi-schema/enum-max-member.json
> @@ -1,3 +1,3 @@
> -# FIXME: we should either reject user-supplied 'max', or munge the implicit
> -# max value we generate at the end of an array
> +# we reject user-supplied 'max' for clashing with implicit enum end
> +# FIXME: should we instead munge the the implicit value to avoid the clash?
Or pick an identifier for the max member so that it cannot clash with
the ones we generate for the user's members.
The generator picks identifiers pretty much thoughtlessly in general.
If something clashes, the C compiler spits it out, and you get to fiddle
with the .json.
[...]
Reviewed-by: Markus Armbruster <armbru@redhat.com>
next prev parent reply other threads:[~2014-09-23 14:23 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-19 22:24 [Qemu-devel] [PATCH v4 00/19] drop qapi nested structs Eric Blake
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 01/19] qapi: Consistent whitespace in tests/Makefile Eric Blake
2014-09-22 12:40 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 02/19] qapi: Ignore files created during make check Eric Blake
2014-09-23 8:07 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 03/19] qapi: Update docs given recent event, spacing fixes Eric Blake
2014-09-22 12:40 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 04/19] qapi: Document type-safety considerations Eric Blake
2014-09-22 12:37 ` Markus Armbruster
2014-09-22 16:53 ` Eric Blake
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 05/19] qapi: Add some enum tests Eric Blake
2014-09-22 12:43 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 06/19] qapi: Better error messages for bad enums Eric Blake
2014-09-23 14:23 ` Markus Armbruster [this message]
2014-09-23 15:59 ` Eric Blake
2014-09-24 7:46 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 07/19] qapi: Add some expr tests Eric Blake
2014-09-23 14:26 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 08/19] qapi: Better error messages for bad expressions Eric Blake
2014-09-23 14:56 ` Markus Armbruster
2014-09-23 16:11 ` Eric Blake
2014-09-24 7:34 ` Markus Armbruster
2014-09-24 9:25 ` Kevin Wolf
2014-09-24 11:14 ` Markus Armbruster
2014-09-26 9:15 ` Markus Armbruster
2014-09-26 9:25 ` Kevin Wolf
2014-09-26 11:40 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 09/19] qapi: Add tests of redefined expressions Eric Blake
2014-09-24 11:24 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 10/19] qapi: Better error messages for duplicated expressions Eric Blake
2014-09-24 11:58 ` Markus Armbruster
2014-09-24 14:10 ` Eric Blake
2014-09-24 15:29 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 11/19] qapi: Add tests of type bypass Eric Blake
2014-09-24 16:10 ` Markus Armbruster
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 12/19] qapi: Add some type check tests Eric Blake
2014-09-25 7:34 ` Markus Armbruster
2014-09-25 8:06 ` Markus Armbruster
2014-09-25 14:00 ` Eric Blake
2014-09-25 16:19 ` Markus Armbruster
2015-03-23 15:33 ` [Qemu-devel] RFC: 'alternate' qapi top-level expression [was: [PATCH v4 12/19] qapi: Add some type check tests] Eric Blake
2015-03-23 19:28 ` Markus Armbruster
2014-09-25 13:54 ` [Qemu-devel] [PATCH v4 12/19] qapi: Add some type check tests Eric Blake
2014-09-25 16:12 ` Markus Armbruster
2014-09-25 16:32 ` Eric Blake
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 13/19] qapi: More rigourous checking of types Eric Blake
2014-09-26 9:26 ` Markus Armbruster
2014-09-29 8:27 ` Markus Armbruster
2014-09-29 14:26 ` Eric Blake
2014-09-29 14:35 ` Eric Blake
2014-09-19 22:24 ` [Qemu-devel] [PATCH v4 14/19] qapi: More rigorous checking for type safety bypass Eric Blake
2014-09-29 8:38 ` Markus Armbruster
2014-09-29 14:33 ` Eric Blake
2014-09-29 16:35 ` Markus Armbruster
2014-09-19 22:25 ` [Qemu-devel] [PATCH v4 15/19] qapi: Merge UserDefTwo and UserDefNested in tests Eric Blake
2014-09-19 22:25 ` [Qemu-devel] [PATCH v4 16/19] qapi: Drop tests for inline subtypes Eric Blake
2014-09-19 22:25 ` [Qemu-devel] [PATCH v4 17/19] qapi: Drop inline subtype in query-version Eric Blake
2014-09-30 17:40 ` Markus Armbruster
2014-09-19 22:25 ` [Qemu-devel] [PATCH v4 18/19] qapi: Drop inline subtype in query-pci Eric Blake
2014-09-19 22:25 ` [Qemu-devel] [PATCH v4 19/19] qapi: Drop support for inline subtypes Eric Blake
2014-09-30 17:47 ` Markus Armbruster
2014-09-26 15:42 ` [Qemu-devel] [PATCH v4 00/19] drop qapi nested structs Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=874mvyiffi.fsf@blackfin.pond.sub.org \
--to=armbru@redhat.com \
--cc=eblake@redhat.com \
--cc=famz@redhat.com \
--cc=lcapitulino@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=wenchaoqemu@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.