qapi: Command returning anonymous type doesn't work, outlaw

Reproducer: with

    { 'command': 'user_def_cmd4', 'returns': { 'a': 'int' } }

added to qapi-schema-test.json, qapi-commands.py dies when it tries to
generate the command handler function

    Traceback (most recent call last):
      File "/work/armbru/qemu/scripts/qapi-commands.py", line 359, in <module>
        ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
      File "/work/armbru/qemu/scripts/qapi-commands.py", line 29, in generate_command_decl
        ret_type=c_type(ret_type), name=c_name(name),
      File "/work/armbru/qemu/scripts/qapi.py", line 927, in c_type
        assert isinstance(value, str) and value != ""
    AssertionError

because the return type doesn't exist.

Simply outlaw this usage, and drop or dumb down test cases accordingly.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Markus Armbruster 2015-07-31 17:59:38 +02:00
parent 315932b5ed
commit 9b090d42ae
11 changed files with 16 additions and 20 deletions

View File

@ -394,7 +394,7 @@ following example objects:
=== Commands === === Commands ===
Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT, Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
'*returns': TYPE-NAME-OR-DICT, '*returns': TYPE-NAME,
'*gen': false, '*success-response': false } '*gen': false, '*success-response': false }
Commands are defined by using a dictionary containing several members, Commands are defined by using a dictionary containing several members,
@ -415,14 +415,13 @@ The member is optional from the command declaration; if absent, the
"return" field will be an empty dictionary. If 'returns' is present, "return" field will be an empty dictionary. If 'returns' is present,
it must be the string name of a complex or built-in type, a it must be the string name of a complex or built-in type, a
one-element array containing the name of a complex or built-in type, one-element array containing the name of a complex or built-in type,
or a dictionary that declares an anonymous type with the same with one exception noted below when 'gen' is used. Although it is
semantics as a 'struct' expression, with one exception noted below permitted to have the 'returns' member name a built-in type or an
when 'gen' is used. Although it is permitted to have the 'returns' array of built-in types, any command that does this cannot be extended
member name a built-in type or an array of built-in types, any command to return additional information in the future; thus, new commands
that does this cannot be extended to return additional information in should strongly consider returning a dictionary-based type or an array
the future; thus, new commands should strongly consider returning a of dictionaries, even if the dictionary only contains one field at the
dictionary-based type or an array of dictionaries, even if the present.
dictionary only contains one field at the present.
All commands in Client JSON Protocol use a dictionary to report All commands in Client JSON Protocol use a dictionary to report
failure, with no way to specify that in QAPI. Where the error return failure, with no way to specify that in QAPI. Where the error return

View File

@ -504,7 +504,7 @@ def check_command(expr, expr_info):
if name in returns_whitelist: if name in returns_whitelist:
returns_meta += ['built-in', 'alternate', 'enum'] returns_meta += ['built-in', 'alternate', 'enum']
check_type(expr_info, "'returns' for command '%s'" % name, check_type(expr_info, "'returns' for command '%s'" % name,
expr.get('returns'), allow_array=True, allow_dict=True, expr.get('returns'), allow_array=True,
allow_optional=True, allow_metas=returns_meta, allow_optional=True, allow_metas=returns_meta,
allow_star=allow_star) allow_star=allow_star)

View File

@ -232,10 +232,10 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
args-array-empty.json args-array-unknown.json args-int.json \ args-array-empty.json args-array-unknown.json args-int.json \
args-unknown.json args-member-unknown.json args-member-array.json \ args-unknown.json args-member-unknown.json args-member-array.json \
args-member-array-bad.json args-alternate.json args-union.json \ args-member-array-bad.json args-alternate.json args-union.json \
returns-array-bad.json returns-int.json \ returns-array-bad.json returns-int.json returns-dict.json \
returns-unknown.json returns-alternate.json returns-whitelist.json \ returns-unknown.json returns-alternate.json returns-whitelist.json \
missing-colon.json missing-comma-list.json missing-comma-object.json \ missing-colon.json missing-comma-list.json missing-comma-object.json \
nested-struct-data.json nested-struct-returns.json non-objects.json \ nested-struct-data.json non-objects.json \
qapi-schema-test.json quoted-structural-chars.json \ qapi-schema-test.json quoted-structural-chars.json \
trailing-comma-list.json trailing-comma-object.json \ trailing-comma-list.json trailing-comma-object.json \
unclosed-list.json unclosed-object.json unclosed-string.json \ unclosed-list.json unclosed-object.json unclosed-string.json \

View File

@ -1,3 +1,2 @@
# we reject collisions between commands and types # we reject collisions between commands and types
{ 'command': 'int', 'data': { 'character': 'str' }, { 'command': 'int', 'data': { 'character': 'str' } }
'returns': { 'value': 'int' } }

View File

@ -1,4 +1,3 @@
# inline subtypes collide with our desired future use of defaults # inline subtypes collide with our desired future use of defaults
{ 'command': 'foo', { 'command': 'foo',
'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' }, 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
'returns': {} }

View File

@ -1 +0,0 @@
tests/qapi-schema/nested-struct-returns.json:2: Member 'a' of 'returns' for command 'foo' should be a type name

View File

@ -1,3 +0,0 @@
# inline subtypes collide with our desired future use of defaults
{ 'command': 'foo',
'returns': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }

View File

@ -0,0 +1 @@
tests/qapi-schema/returns-dict.json:2: 'returns' for command 'oops' should be a type name

View File

@ -0,0 +1,2 @@
# we reject inline struct return type
{ 'command': 'oops', 'returns': { 'a': 'str' } }