diff mbox

[v5,19/28] qapi: Add some type check tests

Message ID 1427227433-5030-20-git-send-email-eblake@redhat.com
State New
Headers show

Commit Message

Eric Blake March 24, 2015, 8:03 p.m. UTC
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.

Signed-off-by: Eric Blake <eblake@redhat.com>
---
 tests/Makefile                               |  8 ++++++--
 tests/qapi-schema/data-array-empty.err       |  0
 tests/qapi-schema/data-array-empty.exit      |  1 +
 tests/qapi-schema/data-array-empty.json      |  2 ++
 tests/qapi-schema/data-array-empty.out       |  3 +++
 tests/qapi-schema/data-array-unknown.err     |  0
 tests/qapi-schema/data-array-unknown.exit    |  1 +
 tests/qapi-schema/data-array-unknown.json    |  2 ++
 tests/qapi-schema/data-array-unknown.out     |  3 +++
 tests/qapi-schema/data-int.err               |  0
 tests/qapi-schema/data-int.exit              |  1 +
 tests/qapi-schema/data-int.json              |  2 ++
 tests/qapi-schema/data-int.out               |  3 +++
 tests/qapi-schema/data-member-array-bad.err  |  0
 tests/qapi-schema/data-member-array-bad.exit |  1 +
 tests/qapi-schema/data-member-array-bad.json |  2 ++
 tests/qapi-schema/data-member-array-bad.out  |  3 +++
 tests/qapi-schema/data-member-array.err      |  0
 tests/qapi-schema/data-member-array.exit     |  1 +
 tests/qapi-schema/data-member-array.json     |  4 ++++
 tests/qapi-schema/data-member-array.out      |  5 +++++
 tests/qapi-schema/data-member-unknown.err    |  0
 tests/qapi-schema/data-member-unknown.exit   |  1 +
 tests/qapi-schema/data-member-unknown.json   |  2 ++
 tests/qapi-schema/data-member-unknown.out    |  3 +++
 tests/qapi-schema/data-unknown.err           |  0
 tests/qapi-schema/data-unknown.exit          |  1 +
 tests/qapi-schema/data-unknown.json          |  2 ++
 tests/qapi-schema/data-unknown.out           |  3 +++
 tests/qapi-schema/nested-struct-data.err     |  0
 tests/qapi-schema/nested-struct-data.exit    |  1 +
 tests/qapi-schema/nested-struct-data.json    |  4 ++++
 tests/qapi-schema/nested-struct-data.out     |  3 +++
 tests/qapi-schema/nested-struct-returns.err  |  0
 tests/qapi-schema/nested-struct-returns.exit |  1 +
 tests/qapi-schema/nested-struct-returns.json |  3 +++
 tests/qapi-schema/nested-struct-returns.out  |  3 +++
 tests/qapi-schema/returns-alternate.err      |  0
 tests/qapi-schema/returns-alternate.exit     |  1 +
 tests/qapi-schema/returns-alternate.json     |  3 +++
 tests/qapi-schema/returns-alternate.out      |  4 ++++
 tests/qapi-schema/returns-array-bad.err      |  0
 tests/qapi-schema/returns-array-bad.exit     |  1 +
 tests/qapi-schema/returns-array-bad.json     |  2 ++
 tests/qapi-schema/returns-array-bad.out      |  3 +++
 tests/qapi-schema/returns-int.err            |  0
 tests/qapi-schema/returns-int.exit           |  1 +
 tests/qapi-schema/returns-int.json           |  2 ++
 tests/qapi-schema/returns-int.out            |  3 +++
 tests/qapi-schema/returns-unknown.err        |  0
 tests/qapi-schema/returns-unknown.exit       |  1 +
 tests/qapi-schema/returns-unknown.json       |  2 ++
 tests/qapi-schema/returns-unknown.out        |  3 +++
 tests/qapi-schema/returns-whitelist.err      |  0
 tests/qapi-schema/returns-whitelist.exit     |  1 +
 tests/qapi-schema/returns-whitelist.json     | 11 +++++++++++
 tests/qapi-schema/returns-whitelist.out      |  7 +++++++
 57 files changed, 112 insertions(+), 2 deletions(-)
 create mode 100644 tests/qapi-schema/data-array-empty.err
 create mode 100644 tests/qapi-schema/data-array-empty.exit
 create mode 100644 tests/qapi-schema/data-array-empty.json
 create mode 100644 tests/qapi-schema/data-array-empty.out
 create mode 100644 tests/qapi-schema/data-array-unknown.err
 create mode 100644 tests/qapi-schema/data-array-unknown.exit
 create mode 100644 tests/qapi-schema/data-array-unknown.json
 create mode 100644 tests/qapi-schema/data-array-unknown.out
 create mode 100644 tests/qapi-schema/data-int.err
 create mode 100644 tests/qapi-schema/data-int.exit
 create mode 100644 tests/qapi-schema/data-int.json
 create mode 100644 tests/qapi-schema/data-int.out
 create mode 100644 tests/qapi-schema/data-member-array-bad.err
 create mode 100644 tests/qapi-schema/data-member-array-bad.exit
 create mode 100644 tests/qapi-schema/data-member-array-bad.json
 create mode 100644 tests/qapi-schema/data-member-array-bad.out
 create mode 100644 tests/qapi-schema/data-member-array.err
 create mode 100644 tests/qapi-schema/data-member-array.exit
 create mode 100644 tests/qapi-schema/data-member-array.json
 create mode 100644 tests/qapi-schema/data-member-array.out
 create mode 100644 tests/qapi-schema/data-member-unknown.err
 create mode 100644 tests/qapi-schema/data-member-unknown.exit
 create mode 100644 tests/qapi-schema/data-member-unknown.json
 create mode 100644 tests/qapi-schema/data-member-unknown.out
 create mode 100644 tests/qapi-schema/data-unknown.err
 create mode 100644 tests/qapi-schema/data-unknown.exit
 create mode 100644 tests/qapi-schema/data-unknown.json
 create mode 100644 tests/qapi-schema/data-unknown.out
 create mode 100644 tests/qapi-schema/nested-struct-data.err
 create mode 100644 tests/qapi-schema/nested-struct-data.exit
 create mode 100644 tests/qapi-schema/nested-struct-data.json
 create mode 100644 tests/qapi-schema/nested-struct-data.out
 create mode 100644 tests/qapi-schema/nested-struct-returns.err
 create mode 100644 tests/qapi-schema/nested-struct-returns.exit
 create mode 100644 tests/qapi-schema/nested-struct-returns.json
 create mode 100644 tests/qapi-schema/nested-struct-returns.out
 create mode 100644 tests/qapi-schema/returns-alternate.err
 create mode 100644 tests/qapi-schema/returns-alternate.exit
 create mode 100644 tests/qapi-schema/returns-alternate.json
 create mode 100644 tests/qapi-schema/returns-alternate.out
 create mode 100644 tests/qapi-schema/returns-array-bad.err
 create mode 100644 tests/qapi-schema/returns-array-bad.exit
 create mode 100644 tests/qapi-schema/returns-array-bad.json
 create mode 100644 tests/qapi-schema/returns-array-bad.out
 create mode 100644 tests/qapi-schema/returns-int.err
 create mode 100644 tests/qapi-schema/returns-int.exit
 create mode 100644 tests/qapi-schema/returns-int.json
 create mode 100644 tests/qapi-schema/returns-int.out
 create mode 100644 tests/qapi-schema/returns-unknown.err
 create mode 100644 tests/qapi-schema/returns-unknown.exit
 create mode 100644 tests/qapi-schema/returns-unknown.json
 create mode 100644 tests/qapi-schema/returns-unknown.out
 create mode 100644 tests/qapi-schema/returns-whitelist.err
 create mode 100644 tests/qapi-schema/returns-whitelist.exit
 create mode 100644 tests/qapi-schema/returns-whitelist.json
 create mode 100644 tests/qapi-schema/returns-whitelist.out

Comments

Markus Armbruster March 26, 2015, 5:58 p.m. UTC | #1
Eric Blake <eblake@redhat.com> writes:

> 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.
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
[...]
> diff --git a/tests/qapi-schema/data-array-empty.err b/tests/qapi-schema/data-array-empty.err
> new file mode 100644
> index 0000000..e69de29
> diff --git a/tests/qapi-schema/data-array-empty.exit b/tests/qapi-schema/data-array-empty.exit
> new file mode 100644
> index 0000000..573541a
> --- /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 0000000..edb543a
> --- /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': [ ] } }

v4 tested

    { 'command': 'oops', 'data': [ ] }

Is that still covered somewhere else?

> diff --git a/tests/qapi-schema/data-array-empty.out b/tests/qapi-schema/data-array-empty.out
> new file mode 100644
> index 0000000..6f25c9e
> --- /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/returns-whitelist.err b/tests/qapi-schema/returns-whitelist.err
> new file mode 100644
> index 0000000..e69de29
> diff --git a/tests/qapi-schema/returns-whitelist.exit b/tests/qapi-schema/returns-whitelist.exit
> new file mode 100644
> index 0000000..573541a
> --- /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 0000000..8328563
> --- /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' ] }

I like the pattern "add tests to demonstrate issues, then code to
address the issues".  But this test appears too much out of the blue for
my taste.

You could use the commit message to prepare the reader.

Or you could deviate from the pattern and add this test together with
the actual whitelist.  That's what I'd try.

> diff --git a/tests/qapi-schema/returns-whitelist.out b/tests/qapi-schema/returns-whitelist.out
> new file mode 100644
> index 0000000..2adcd8b
> --- /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']}]
> +[]

Since I found nothing that's actually wrong:

Reviewed-by: Markus Armbruster <armbru@redhat.com>
Eric Blake March 26, 2015, 7:07 p.m. UTC | #2
On 03/26/2015 11:58 AM, Markus Armbruster wrote:
> Eric Blake <eblake@redhat.com> writes:
> 
>> 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.
>>
>> Signed-off-by: Eric Blake <eblake@redhat.com>
>> ---
> [...]
>> diff --git a/tests/qapi-schema/data-array-empty.err b/tests/qapi-schema/data-array-empty.err
>> new file mode 100644
>> index 0000000..e69de29
>> diff --git a/tests/qapi-schema/data-array-empty.exit b/tests/qapi-schema/data-array-empty.exit
>> new file mode 100644
>> index 0000000..573541a
>> --- /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 0000000..edb543a
>> --- /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': [ ] } }
> 
> v4 tested
> 
>     { 'command': 'oops', 'data': [ ] }
> 
> Is that still covered somewhere else?

Probably not.  Sounds like a good test case to add, presumably on top if
I don't have to respin.


>> +
>> +{ 'command': 'no-way-this-will-get-whitelisted',
>> +  'returns': [ 'int' ] }
> 
> I like the pattern "add tests to demonstrate issues, then code to
> address the issues".  But this test appears too much out of the blue for
> my taste.
> 
> You could use the commit message to prepare the reader.
> 
> Or you could deviate from the pattern and add this test together with
> the actual whitelist.  That's what I'd try.

Of course, if I do need to respin, I can shuffle and split patches as
needed to make the resubmission prettier.

> 
>> diff --git a/tests/qapi-schema/returns-whitelist.out b/tests/qapi-schema/returns-whitelist.out
>> new file mode 100644
>> index 0000000..2adcd8b
>> --- /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']}]
>> +[]
> 
> Since I found nothing that's actually wrong:
> 
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
> 
>
diff mbox

Patch

diff --git a/tests/Makefile b/tests/Makefile
index 941e839..9877a5b 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -216,8 +216,12 @@  check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
 	redefined-type.json redefined-command.json redefined-builtin.json \
 	redefined-event.json command-int.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/data-array-empty.err b/tests/qapi-schema/data-array-empty.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/data-array-empty.exit b/tests/qapi-schema/data-array-empty.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..edb543a
--- /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 0000000..6f25c9e
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/data-array-unknown.exit b/tests/qapi-schema/data-array-unknown.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..20cd3c0
--- /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 0000000..4314ab5
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/data-int.exit b/tests/qapi-schema/data-int.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..37916e0
--- /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 0000000..e589a4f
--- /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 0000000..e69de29
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 0000000..573541a
--- /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 0000000..c954af1
--- /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 0000000..0e00c41
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/data-member-array.exit b/tests/qapi-schema/data-member-array.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..7cce276
--- /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 0000000..8287120
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/data-member-unknown.exit b/tests/qapi-schema/data-member-unknown.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..40e6252
--- /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 0000000..36252a5
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/data-unknown.exit b/tests/qapi-schema/data-unknown.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..776bd34
--- /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 0000000..2c60726
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/nested-struct-data.exit b/tests/qapi-schema/nested-struct-data.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..0247c8c
--- /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 0000000..999cbb8
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/nested-struct-returns.exit b/tests/qapi-schema/nested-struct-returns.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..5a46840
--- /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 0000000..c53d23b
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/returns-alternate.exit b/tests/qapi-schema/returns-alternate.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..b3b91fd
--- /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 0000000..8a03ed3
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/returns-array-bad.exit b/tests/qapi-schema/returns-array-bad.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..14882c1
--- /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 0000000..eccad55
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/returns-int.exit b/tests/qapi-schema/returns-int.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..7888fb1
--- /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 0000000..36b00a9
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/returns-unknown.exit b/tests/qapi-schema/returns-unknown.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..61f20eb
--- /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 0000000..a482c83
--- /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 0000000..e69de29
diff --git a/tests/qapi-schema/returns-whitelist.exit b/tests/qapi-schema/returns-whitelist.exit
new file mode 100644
index 0000000..573541a
--- /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 0000000..8328563
--- /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 0000000..2adcd8b
--- /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']}]
+[]