Commit 9b090d42 authored by Markus Armbruster's avatar Markus Armbruster
Browse files

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: default avatarMarkus Armbruster <armbru@redhat.com>
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
parent 315932b5
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -394,7 +394,7 @@ following example objects:
=== Commands ===

Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
         '*returns': TYPE-NAME-OR-DICT,
         '*returns': TYPE-NAME,
         '*gen': false, '*success-response': false }

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,
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,
or a dictionary that declares an anonymous type with the same
semantics as a 'struct' expression, with one exception noted below
when 'gen' is used.  Although it is permitted to have the 'returns'
member name a built-in type or an array of built-in types, any command
that does this cannot be extended to return additional information in
the future; thus, new commands should strongly consider returning a
dictionary-based type or an array of dictionaries, even if the
dictionary only contains one field at the present.
with one exception noted below when 'gen' is used.  Although it is
permitted to have the 'returns' member name a built-in type or an
array of built-in types, any command that does this cannot be extended
to return additional information in the future; thus, new commands
should strongly consider returning a dictionary-based type or an array
of dictionaries, even if the dictionary only contains one field at the
present.

All commands in Client JSON Protocol use a dictionary to report
failure, with no way to specify that in QAPI.  Where the error return
+1 −1
Original line number Diff line number Diff line
@@ -504,7 +504,7 @@ def check_command(expr, expr_info):
    if name in returns_whitelist:
        returns_meta += ['built-in', 'alternate', 'enum']
    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_star=allow_star)

+2 −2
Original line number Diff line number Diff line
@@ -232,10 +232,10 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
	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 \
	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 \
	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 \
	trailing-comma-list.json trailing-comma-object.json \
	unclosed-list.json unclosed-object.json unclosed-string.json \
+1 −2
Original line number Diff line number Diff line
# we reject collisions between commands and types
{ 'command': 'int', 'data': { 'character': 'str' },
  'returns': { 'value': 'int' } }
{ 'command': 'int', 'data': { 'character': 'str' } }
+1 −2
Original line number Diff line number Diff line
# inline subtypes collide with our desired future use of defaults
{ 'command': 'foo',
  'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' },
  'returns': {} }
  'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
Loading