diff options
author | Eric Blake <eblake@redhat.com> | 2015-05-04 09:05:20 -0600 |
---|---|---|
committer | Markus Armbruster <armbru@redhat.com> | 2015-05-05 18:39:01 +0200 |
commit | 0d8b9fb5f296a96723d98a45a6a00bfd4e45e1b9 (patch) | |
tree | 23069277c1b7f5b14582eda0417632d8b15b21d8 | |
parent | d708cdbe8792a55f53e90c1c787e871d527e8d4b (diff) |
qapi: Add some type check tests
Demonstrate that the qapi generator silently parses confusing
types, which may cause other errors later on. Later patches
will update the expected results as the generator is made stricter.
Most of the new tests focus on blatant errors. But
returns-whitelist is a case where we have historically allowed
returning something other than a JSON object from particular
commands; we have to keep that behavior to avoid breaking clients,
but it would be nicer to avoid adding such commands in the future,
because any return that is not an (array of) object cannot be
easily extended if future qemu wants to return additional
information. The QMP protocol already documents that clients
should ignore unknown dictionary keys, but does not require
clients to have to handle more than one type of JSON object.
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
61 files changed, 119 insertions, 3 deletions
diff --git a/tests/Makefile b/tests/Makefile index 64e678502c..e2a3bd349e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -215,10 +215,14 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \ double-type.json bad-base.json bad-type-bool.json bad-type-int.json \ 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 event-max.json \ + redefined-event.json command-int.json bad-data.json event-max.json \ type-bypass.json type-bypass-no-gen.json type-bypass-bad-gen.json \ - missing-colon.json missing-comma-list.json \ - missing-comma-object.json non-objects.json \ + data-array-empty.json data-array-unknown.json data-int.json \ + data-unknown.json data-member-unknown.json data-member-array.json \ + data-member-array-bad.json returns-array-bad.json returns-int.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 \ 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 \ diff --git a/tests/qapi-schema/bad-data.err b/tests/qapi-schema/bad-data.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/bad-data.err diff --git a/tests/qapi-schema/bad-data.exit b/tests/qapi-schema/bad-data.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/bad-data.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/bad-data.json b/tests/qapi-schema/bad-data.json new file mode 100644 index 0000000000..ff1616dd96 --- /dev/null +++ b/tests/qapi-schema/bad-data.json @@ -0,0 +1,2 @@ +# FIXME: we should ensure 'data' is a dictionary for all but enums +{ 'command': 'oops', 'data': [ ] } diff --git a/tests/qapi-schema/bad-data.out b/tests/qapi-schema/bad-data.out new file mode 100644 index 0000000000..67802be93c --- /dev/null +++ b/tests/qapi-schema/bad-data.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'oops'), ('data', [])])] +[] +[] diff --git a/tests/qapi-schema/data-array-empty.err b/tests/qapi-schema/data-array-empty.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/data-array-empty.err diff --git a/tests/qapi-schema/data-array-empty.exit b/tests/qapi-schema/data-array-empty.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/data-array-empty.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/data-array-empty.json b/tests/qapi-schema/data-array-empty.json new file mode 100644 index 0000000000..edb543a75d --- /dev/null +++ b/tests/qapi-schema/data-array-empty.json @@ -0,0 +1,2 @@ +# FIXME: we should reject an array for data if it does not contain a known type +{ 'command': 'oops', 'data': { 'empty': [ ] } } diff --git a/tests/qapi-schema/data-array-empty.out b/tests/qapi-schema/data-array-empty.out new file mode 100644 index 0000000000..6f25c9e18a --- /dev/null +++ b/tests/qapi-schema/data-array-empty.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'oops'), ('data', OrderedDict([('empty', [])]))])] +[] +[] diff --git a/tests/qapi-schema/data-array-unknown.err b/tests/qapi-schema/data-array-unknown.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/data-array-unknown.err diff --git a/tests/qapi-schema/data-array-unknown.exit b/tests/qapi-schema/data-array-unknown.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/data-array-unknown.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/data-array-unknown.json b/tests/qapi-schema/data-array-unknown.json new file mode 100644 index 0000000000..20cd3c0c30 --- /dev/null +++ b/tests/qapi-schema/data-array-unknown.json @@ -0,0 +1,2 @@ +# FIXME: we should reject an array for data if it does not contain a known type +{ 'command': 'oops', 'data': { 'array': [ 'NoSuchType' ] } } diff --git a/tests/qapi-schema/data-array-unknown.out b/tests/qapi-schema/data-array-unknown.out new file mode 100644 index 0000000000..4314ab5dfa --- /dev/null +++ b/tests/qapi-schema/data-array-unknown.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'oops'), ('data', OrderedDict([('array', ['NoSuchType'])]))])] +[] +[] diff --git a/tests/qapi-schema/data-int.err b/tests/qapi-schema/data-int.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/data-int.err diff --git a/tests/qapi-schema/data-int.exit b/tests/qapi-schema/data-int.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/data-int.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/data-int.json b/tests/qapi-schema/data-int.json new file mode 100644 index 0000000000..37916e09a9 --- /dev/null +++ b/tests/qapi-schema/data-int.json @@ -0,0 +1,2 @@ +# FIXME: we should reject commands where data is not an array or complex type +{ 'command': 'oops', 'data': 'int' } diff --git a/tests/qapi-schema/data-int.out b/tests/qapi-schema/data-int.out new file mode 100644 index 0000000000..e589a4ff92 --- /dev/null +++ b/tests/qapi-schema/data-int.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'oops'), ('data', 'int')])] +[] +[] diff --git a/tests/qapi-schema/data-member-array-bad.err b/tests/qapi-schema/data-member-array-bad.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/data-member-array-bad.err diff --git a/tests/qapi-schema/data-member-array-bad.exit b/tests/qapi-schema/data-member-array-bad.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/data-member-array-bad.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/data-member-array-bad.json b/tests/qapi-schema/data-member-array-bad.json new file mode 100644 index 0000000000..c954af13ee --- /dev/null +++ b/tests/qapi-schema/data-member-array-bad.json @@ -0,0 +1,2 @@ +# FIXME: we should reject data if it does not contain a valid array type +{ 'command': 'oops', 'data': { 'member': [ { 'nested': 'str' } ] } } diff --git a/tests/qapi-schema/data-member-array-bad.out b/tests/qapi-schema/data-member-array-bad.out new file mode 100644 index 0000000000..0e00c4171c --- /dev/null +++ b/tests/qapi-schema/data-member-array-bad.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'oops'), ('data', OrderedDict([('member', [OrderedDict([('nested', 'str')])])]))])] +[] +[] diff --git a/tests/qapi-schema/data-member-array.err b/tests/qapi-schema/data-member-array.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/data-member-array.err diff --git a/tests/qapi-schema/data-member-array.exit b/tests/qapi-schema/data-member-array.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/data-member-array.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/data-member-array.json b/tests/qapi-schema/data-member-array.json new file mode 100644 index 0000000000..7cce276979 --- /dev/null +++ b/tests/qapi-schema/data-member-array.json @@ -0,0 +1,4 @@ +# valid array members +{ 'enum': 'abc', 'data': [ 'a', 'b', 'c' ] } +{ 'type': 'def', 'data': { 'array': [ 'abc' ] } } +{ 'command': 'okay', 'data': { 'member1': [ 'int' ], 'member2': [ 'def' ] } } diff --git a/tests/qapi-schema/data-member-array.out b/tests/qapi-schema/data-member-array.out new file mode 100644 index 0000000000..82871204ed --- /dev/null +++ b/tests/qapi-schema/data-member-array.out @@ -0,0 +1,5 @@ +[OrderedDict([('enum', 'abc'), ('data', ['a', 'b', 'c'])]), + OrderedDict([('type', 'def'), ('data', OrderedDict([('array', ['abc'])]))]), + OrderedDict([('command', 'okay'), ('data', OrderedDict([('member1', ['int']), ('member2', ['def'])]))])] +[{'enum_name': 'abc', 'enum_values': ['a', 'b', 'c']}] +[OrderedDict([('type', 'def'), ('data', OrderedDict([('array', ['abc'])]))])] diff --git a/tests/qapi-schema/data-member-unknown.err b/tests/qapi-schema/data-member-unknown.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/data-member-unknown.err diff --git a/tests/qapi-schema/data-member-unknown.exit b/tests/qapi-schema/data-member-unknown.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/data-member-unknown.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/data-member-unknown.json b/tests/qapi-schema/data-member-unknown.json new file mode 100644 index 0000000000..40e6252c1d --- /dev/null +++ b/tests/qapi-schema/data-member-unknown.json @@ -0,0 +1,2 @@ +# FIXME: we should reject data if it does not contain a known type +{ 'command': 'oops', 'data': { 'member': 'NoSuchType' } } diff --git a/tests/qapi-schema/data-member-unknown.out b/tests/qapi-schema/data-member-unknown.out new file mode 100644 index 0000000000..36252a5f73 --- /dev/null +++ b/tests/qapi-schema/data-member-unknown.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'oops'), ('data', OrderedDict([('member', 'NoSuchType')]))])] +[] +[] diff --git a/tests/qapi-schema/data-unknown.err b/tests/qapi-schema/data-unknown.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/data-unknown.err diff --git a/tests/qapi-schema/data-unknown.exit b/tests/qapi-schema/data-unknown.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/data-unknown.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/data-unknown.json b/tests/qapi-schema/data-unknown.json new file mode 100644 index 0000000000..776bd342e5 --- /dev/null +++ b/tests/qapi-schema/data-unknown.json @@ -0,0 +1,2 @@ +# FIXME: we should reject data if it does not contain a known type +{ 'command': 'oops', 'data': 'NoSuchType' } diff --git a/tests/qapi-schema/data-unknown.out b/tests/qapi-schema/data-unknown.out new file mode 100644 index 0000000000..2c60726881 --- /dev/null +++ b/tests/qapi-schema/data-unknown.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'oops'), ('data', 'NoSuchType')])] +[] +[] diff --git a/tests/qapi-schema/nested-struct-data.err b/tests/qapi-schema/nested-struct-data.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/nested-struct-data.err diff --git a/tests/qapi-schema/nested-struct-data.exit b/tests/qapi-schema/nested-struct-data.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/nested-struct-data.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/nested-struct-data.json b/tests/qapi-schema/nested-struct-data.json new file mode 100644 index 0000000000..0247c8c82c --- /dev/null +++ b/tests/qapi-schema/nested-struct-data.json @@ -0,0 +1,4 @@ +# FIXME: inline subtypes collide with our desired future use of defaults +{ 'command': 'foo', + 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' }, + 'returns': {} } diff --git a/tests/qapi-schema/nested-struct-data.out b/tests/qapi-schema/nested-struct-data.out new file mode 100644 index 0000000000..999cbb8eef --- /dev/null +++ b/tests/qapi-schema/nested-struct-data.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'foo'), ('data', OrderedDict([('a', OrderedDict([('string', 'str'), ('integer', 'int')])), ('b', 'str')])), ('returns', OrderedDict())])] +[] +[] diff --git a/tests/qapi-schema/nested-struct-returns.err b/tests/qapi-schema/nested-struct-returns.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/nested-struct-returns.err diff --git a/tests/qapi-schema/nested-struct-returns.exit b/tests/qapi-schema/nested-struct-returns.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/nested-struct-returns.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/nested-struct-returns.json b/tests/qapi-schema/nested-struct-returns.json new file mode 100644 index 0000000000..5a46840b71 --- /dev/null +++ b/tests/qapi-schema/nested-struct-returns.json @@ -0,0 +1,3 @@ +# FIXME: inline subtypes collide with our desired future use of defaults +{ 'command': 'foo', + 'returns': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } } diff --git a/tests/qapi-schema/nested-struct-returns.out b/tests/qapi-schema/nested-struct-returns.out new file mode 100644 index 0000000000..c53d23b3a8 --- /dev/null +++ b/tests/qapi-schema/nested-struct-returns.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'foo'), ('returns', OrderedDict([('a', OrderedDict([('string', 'str'), ('integer', 'int')])), ('b', 'str')]))])] +[] +[] diff --git a/tests/qapi-schema/returns-alternate.err b/tests/qapi-schema/returns-alternate.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/returns-alternate.err diff --git a/tests/qapi-schema/returns-alternate.exit b/tests/qapi-schema/returns-alternate.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/returns-alternate.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/returns-alternate.json b/tests/qapi-schema/returns-alternate.json new file mode 100644 index 0000000000..b3b91fd3d4 --- /dev/null +++ b/tests/qapi-schema/returns-alternate.json @@ -0,0 +1,3 @@ +# FIXME: we should reject returns if it is an alternate type +{ 'alternate': 'Alt', 'data': { 'a': 'int', 'b': 'str' } } +{ 'command': 'oops', 'returns': 'Alt' } diff --git a/tests/qapi-schema/returns-alternate.out b/tests/qapi-schema/returns-alternate.out new file mode 100644 index 0000000000..8a03ed3adf --- /dev/null +++ b/tests/qapi-schema/returns-alternate.out @@ -0,0 +1,4 @@ +[OrderedDict([('alternate', 'Alt'), ('data', OrderedDict([('a', 'int'), ('b', 'str')]))]), + OrderedDict([('command', 'oops'), ('returns', 'Alt')])] +[{'enum_name': 'AltKind', 'enum_values': None}] +[] diff --git a/tests/qapi-schema/returns-array-bad.err b/tests/qapi-schema/returns-array-bad.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/returns-array-bad.err diff --git a/tests/qapi-schema/returns-array-bad.exit b/tests/qapi-schema/returns-array-bad.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/returns-array-bad.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/returns-array-bad.json b/tests/qapi-schema/returns-array-bad.json new file mode 100644 index 0000000000..14882c1e45 --- /dev/null +++ b/tests/qapi-schema/returns-array-bad.json @@ -0,0 +1,2 @@ +# FIXME: we should reject an array return that is not a single type +{ 'command': 'oops', 'returns': [ 'str', 'str' ] } diff --git a/tests/qapi-schema/returns-array-bad.out b/tests/qapi-schema/returns-array-bad.out new file mode 100644 index 0000000000..eccad55219 --- /dev/null +++ b/tests/qapi-schema/returns-array-bad.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'oops'), ('returns', ['str', 'str'])])] +[] +[] diff --git a/tests/qapi-schema/returns-int.err b/tests/qapi-schema/returns-int.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/returns-int.err diff --git a/tests/qapi-schema/returns-int.exit b/tests/qapi-schema/returns-int.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/returns-int.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/returns-int.json b/tests/qapi-schema/returns-int.json new file mode 100644 index 0000000000..7888fb1b08 --- /dev/null +++ b/tests/qapi-schema/returns-int.json @@ -0,0 +1,2 @@ +# It is okay (although not extensible) to return a non-dictionary +{ 'command': 'okay', 'returns': 'int' } diff --git a/tests/qapi-schema/returns-int.out b/tests/qapi-schema/returns-int.out new file mode 100644 index 0000000000..36b00a9f3b --- /dev/null +++ b/tests/qapi-schema/returns-int.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'okay'), ('returns', 'int')])] +[] +[] diff --git a/tests/qapi-schema/returns-unknown.err b/tests/qapi-schema/returns-unknown.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/returns-unknown.err diff --git a/tests/qapi-schema/returns-unknown.exit b/tests/qapi-schema/returns-unknown.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/returns-unknown.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/returns-unknown.json b/tests/qapi-schema/returns-unknown.json new file mode 100644 index 0000000000..61f20ebb02 --- /dev/null +++ b/tests/qapi-schema/returns-unknown.json @@ -0,0 +1,2 @@ +# FIXME: we should reject returns if it does not contain a known type +{ 'command': 'oops', 'returns': 'NoSuchType' } diff --git a/tests/qapi-schema/returns-unknown.out b/tests/qapi-schema/returns-unknown.out new file mode 100644 index 0000000000..a482c837ce --- /dev/null +++ b/tests/qapi-schema/returns-unknown.out @@ -0,0 +1,3 @@ +[OrderedDict([('command', 'oops'), ('returns', 'NoSuchType')])] +[] +[] diff --git a/tests/qapi-schema/returns-whitelist.err b/tests/qapi-schema/returns-whitelist.err new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/qapi-schema/returns-whitelist.err diff --git a/tests/qapi-schema/returns-whitelist.exit b/tests/qapi-schema/returns-whitelist.exit new file mode 100644 index 0000000000..573541ac97 --- /dev/null +++ b/tests/qapi-schema/returns-whitelist.exit @@ -0,0 +1 @@ +0 diff --git a/tests/qapi-schema/returns-whitelist.json b/tests/qapi-schema/returns-whitelist.json new file mode 100644 index 0000000000..8328563b4e --- /dev/null +++ b/tests/qapi-schema/returns-whitelist.json @@ -0,0 +1,11 @@ +# FIXME: we should enforce that 'returns' be a dict or array of dict unless whitelisted +{ 'command': 'human-monitor-command', + 'data': {'command-line': 'str', '*cpu-index': 'int'}, + 'returns': 'str' } +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] } +{ 'command': 'query-tpm-models', 'returns': ['TpmModel'] } +{ 'command': 'guest-get-time', + 'returns': 'int' } + +{ 'command': 'no-way-this-will-get-whitelisted', + 'returns': [ 'int' ] } diff --git a/tests/qapi-schema/returns-whitelist.out b/tests/qapi-schema/returns-whitelist.out new file mode 100644 index 0000000000..2adcd8ba10 --- /dev/null +++ b/tests/qapi-schema/returns-whitelist.out @@ -0,0 +1,7 @@ +[OrderedDict([('command', 'human-monitor-command'), ('data', OrderedDict([('command-line', 'str'), ('*cpu-index', 'int')])), ('returns', 'str')]), + OrderedDict([('enum', 'TpmModel'), ('data', ['tpm-tis'])]), + OrderedDict([('command', 'query-tpm-models'), ('returns', ['TpmModel'])]), + OrderedDict([('command', 'guest-get-time'), ('returns', 'int')]), + OrderedDict([('command', 'no-way-this-will-get-whitelisted'), ('returns', ['int'])])] +[{'enum_name': 'TpmModel', 'enum_values': ['tpm-tis']}] +[] |