diff mbox

[v2,1/9] tests: QAPI schema parser tests

Message ID 1374939721-7876-2-git-send-email-armbru@redhat.com
State New
Headers show

Commit Message

Markus Armbruster July 27, 2013, 3:41 p.m. UTC
The parser handles erroneous input badly.  To be improved shortly.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 configure                                      |  2 +-
 tests/Makefile                                 | 24 ++++++++++++++++++++++--
 tests/qapi-schema/comments.exit                |  1 +
 tests/qapi-schema/comments.json                |  4 ++++
 tests/qapi-schema/comments.out                 |  3 +++
 tests/qapi-schema/empty.exit                   |  1 +
 tests/qapi-schema/empty.out                    |  3 +++
 tests/qapi-schema/funny-char.exit              |  1 +
 tests/qapi-schema/funny-char.json              |  2 ++
 tests/qapi-schema/funny-char.out               |  3 +++
 tests/qapi-schema/indented-expr.exit           |  1 +
 tests/qapi-schema/indented-expr.json           |  2 ++
 tests/qapi-schema/indented-expr.out            |  3 +++
 tests/qapi-schema/missing-colon.exit           |  1 +
 tests/qapi-schema/missing-colon.json           |  2 ++
 tests/qapi-schema/missing-colon.out            |  3 +++
 tests/qapi-schema/missing-comma-list.exit      |  1 +
 tests/qapi-schema/missing-comma-list.json      |  2 ++
 tests/qapi-schema/missing-comma-list.out       |  3 +++
 tests/qapi-schema/missing-comma-object.exit    |  1 +
 tests/qapi-schema/missing-comma-object.json    |  2 ++
 tests/qapi-schema/missing-comma-object.out     |  3 +++
 tests/qapi-schema/non-objects.err              |  1 +
 tests/qapi-schema/non-objects.exit             |  1 +
 tests/qapi-schema/non-objects.json             |  2 ++
 tests/qapi-schema/quoted-structural-chars.exit |  1 +
 tests/qapi-schema/quoted-structural-chars.json |  1 +
 tests/qapi-schema/quoted-structural-chars.out  |  3 +++
 tests/qapi-schema/test-qapi.py                 | 25 +++++++++++++++++++++++++
 tests/qapi-schema/trailing-comma-list.exit     |  1 +
 tests/qapi-schema/trailing-comma-list.json     |  2 ++
 tests/qapi-schema/trailing-comma-list.out      |  3 +++
 tests/qapi-schema/trailing-comma-object.exit   |  1 +
 tests/qapi-schema/trailing-comma-object.json   |  2 ++
 tests/qapi-schema/trailing-comma-object.out    |  3 +++
 tests/qapi-schema/unclosed-list.err            |  1 +
 tests/qapi-schema/unclosed-list.exit           |  1 +
 tests/qapi-schema/unclosed-list.json           |  1 +
 tests/qapi-schema/unclosed-object.err          |  1 +
 tests/qapi-schema/unclosed-object.exit         |  1 +
 tests/qapi-schema/unclosed-object.json         |  1 +
 tests/qapi-schema/unclosed-string.err          |  1 +
 tests/qapi-schema/unclosed-string.exit         |  1 +
 tests/qapi-schema/unclosed-string.json         |  2 ++
 44 files changed, 121 insertions(+), 3 deletions(-)
 create mode 100644 tests/qapi-schema/comments.err
 create mode 100644 tests/qapi-schema/comments.exit
 create mode 100644 tests/qapi-schema/comments.json
 create mode 100644 tests/qapi-schema/comments.out
 create mode 100644 tests/qapi-schema/empty.err
 create mode 100644 tests/qapi-schema/empty.exit
 create mode 100644 tests/qapi-schema/empty.json
 create mode 100644 tests/qapi-schema/empty.out
 create mode 100644 tests/qapi-schema/funny-char.err
 create mode 100644 tests/qapi-schema/funny-char.exit
 create mode 100644 tests/qapi-schema/funny-char.json
 create mode 100644 tests/qapi-schema/funny-char.out
 create mode 100644 tests/qapi-schema/indented-expr.err
 create mode 100644 tests/qapi-schema/indented-expr.exit
 create mode 100644 tests/qapi-schema/indented-expr.json
 create mode 100644 tests/qapi-schema/indented-expr.out
 create mode 100644 tests/qapi-schema/missing-colon.err
 create mode 100644 tests/qapi-schema/missing-colon.exit
 create mode 100644 tests/qapi-schema/missing-colon.json
 create mode 100644 tests/qapi-schema/missing-colon.out
 create mode 100644 tests/qapi-schema/missing-comma-list.err
 create mode 100644 tests/qapi-schema/missing-comma-list.exit
 create mode 100644 tests/qapi-schema/missing-comma-list.json
 create mode 100644 tests/qapi-schema/missing-comma-list.out
 create mode 100644 tests/qapi-schema/missing-comma-object.err
 create mode 100644 tests/qapi-schema/missing-comma-object.exit
 create mode 100644 tests/qapi-schema/missing-comma-object.json
 create mode 100644 tests/qapi-schema/missing-comma-object.out
 create mode 100644 tests/qapi-schema/non-objects.err
 create mode 100644 tests/qapi-schema/non-objects.exit
 create mode 100644 tests/qapi-schema/non-objects.json
 create mode 100644 tests/qapi-schema/non-objects.out
 create mode 100644 tests/qapi-schema/quoted-structural-chars.err
 create mode 100644 tests/qapi-schema/quoted-structural-chars.exit
 create mode 100644 tests/qapi-schema/quoted-structural-chars.json
 create mode 100644 tests/qapi-schema/quoted-structural-chars.out
 create mode 100644 tests/qapi-schema/test-qapi.py
 create mode 100644 tests/qapi-schema/trailing-comma-list.err
 create mode 100644 tests/qapi-schema/trailing-comma-list.exit
 create mode 100644 tests/qapi-schema/trailing-comma-list.json
 create mode 100644 tests/qapi-schema/trailing-comma-list.out
 create mode 100644 tests/qapi-schema/trailing-comma-object.err
 create mode 100644 tests/qapi-schema/trailing-comma-object.exit
 create mode 100644 tests/qapi-schema/trailing-comma-object.json
 create mode 100644 tests/qapi-schema/trailing-comma-object.out
 create mode 100644 tests/qapi-schema/unclosed-list.err
 create mode 100644 tests/qapi-schema/unclosed-list.exit
 create mode 100644 tests/qapi-schema/unclosed-list.json
 create mode 100644 tests/qapi-schema/unclosed-list.out
 create mode 100644 tests/qapi-schema/unclosed-object.err
 create mode 100644 tests/qapi-schema/unclosed-object.exit
 create mode 100644 tests/qapi-schema/unclosed-object.json
 create mode 100644 tests/qapi-schema/unclosed-object.out
 create mode 100644 tests/qapi-schema/unclosed-string.err
 create mode 100644 tests/qapi-schema/unclosed-string.exit
 create mode 100644 tests/qapi-schema/unclosed-string.json
 create mode 100644 tests/qapi-schema/unclosed-string.out

diff --git a/tests/qapi-schema/unclosed-string.out b/tests/qapi-schema/unclosed-string.out
new file mode 100644
index 0000000..e69de29

Comments

Laszlo Ersek Aug. 19, 2013, 10:02 p.m. UTC | #1
On 07/27/13 17:41, Markus Armbruster wrote:
> The parser handles erroneous input badly.  To be improved shortly.
> 
> Signed-off-by: Markus Armbruster <armbru@redhat.com>

> diff --git a/tests/Makefile b/tests/Makefile
> index cdbb79e..ddb957c 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile

> @@ -233,13 +242,24 @@ check-report.html: check-report.xml
>  check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF)
>  	$<
>  
> +.PHONY: check-tests/test-qapi.py
> +check-tests/test-qapi.py: tests/test-qapi.py
> +
> +.PHONY: $(patsubst %, check-%, $(check-qapi-schema-y))
> +$(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
> +	$(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py <$^ >$*.out 2>$*.err; echo $$? >$*.exit, "  TEST  $*.out")
> +	@diff -q $(SRC_PATH)/$*.out $*.out
> +	@diff -q $(SRC_PATH)/$*.err $*.err
> +	@diff -q $(SRC_PATH)/$*.exit $*.exit
> +

Unfortunately, this doesn't catch errors/differences when someone builds
qemu in the source tree, and runs "make check" there. In that case,
whatever output "test-qapi.py" produces, overwrites the in-tree file,
and the diff commands compare files with themselves.

Also, why is 2/9 a good idea, namely, using "qapi-schema-test.json" as a
test file itself? Whoever adds a new test, for anything that uses the
schema, now has to update the .out file as well. (And, due to the above,
only realizes this burden when someone else tries to make-check his/her
code outside of the tree...)

Thanks,
Laszlo
Markus Armbruster Aug. 20, 2013, 6:58 a.m. UTC | #2
Laszlo Ersek <lersek@redhat.com> writes:

> On 07/27/13 17:41, Markus Armbruster wrote:
>> The parser handles erroneous input badly.  To be improved shortly.
>> 
>> Signed-off-by: Markus Armbruster <armbru@redhat.com>
>
>> diff --git a/tests/Makefile b/tests/Makefile
>> index cdbb79e..ddb957c 100644
>> --- a/tests/Makefile
>> +++ b/tests/Makefile
>
>> @@ -233,13 +242,24 @@ check-report.html: check-report.xml
>>  check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF)
>>  	$<
>>  
>> +.PHONY: check-tests/test-qapi.py
>> +check-tests/test-qapi.py: tests/test-qapi.py
>> +
>> +.PHONY: $(patsubst %, check-%, $(check-qapi-schema-y))
>> +$(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
>> +	$(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py <$^ >$*.out 2>$*.err; echo $$? >$*.exit, "  TEST  $*.out")
>> +	@diff -q $(SRC_PATH)/$*.out $*.out
>> +	@diff -q $(SRC_PATH)/$*.err $*.err
>> +	@diff -q $(SRC_PATH)/$*.exit $*.exit
>> +
>
> Unfortunately, this doesn't catch errors/differences when someone builds
> qemu in the source tree, and runs "make check" there. In that case,
> whatever output "test-qapi.py" produces, overwrites the in-tree file,
> and the diff commands compare files with themselves.

D'uh!  Will fix.  Thanks!

> Also, why is 2/9 a good idea, namely, using "qapi-schema-test.json" as a
> test file itself? Whoever adds a new test, for anything that uses the
> schema, now has to update the .out file as well.

The parser needs to be tested with input that exercises all schema
features.  Since such a test already existed, I extended it to
additionally test the parser.

If this coupling turns out to be inconvenient, we can split the test in
two: qapi-schema-test.json goes back to just its original purpose, and a
(possibly simplified) copy is used for testing the parser.

Drawback: when you add schema features, you have to update both tests to
cover them.  Neglecting to add any tests is obvious in review.
Forgetting one of two not so much.

>                                                  (And, due to the above,
> only realizes this burden when someone else tries to make-check his/her
> code outside of the tree...)

Anyone posting patches without running "make check" gets exactly what he
asked for: embarrassment :)
diff mbox

Patch

diff --git a/configure b/configure
index 1c0cc81..f0761ea 100755
--- a/configure
+++ b/configure
@@ -4502,7 +4502,7 @@  if [ "$dtc_internal" = "yes" ]; then
 fi
 
 # build tree in object directory in case the source is not in the current directory
-DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos"
+DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema"
 DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
 DIRS="$DIRS roms/seabios roms/vgabios"
 DIRS="$DIRS qapi-generated"
diff --git a/tests/Makefile b/tests/Makefile
index cdbb79e..ddb957c 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -83,6 +83,14 @@  gcov-files-arm-y += hw/tmp105.c
 check-qtest-ppc-y += tests/boot-order-test$(EXESUF)
 check-qtest-ppc64-y += tests/boot-order-test$(EXESUF)
 
+check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
+        comments.json empty.json funny-char.json indented-expr.json \
+        missing-colon.json missing-comma-list.json \
+        missing-comma-object.json non-objects.json \
+        quoted-structural-chars.json \
+        trailing-comma-list.json trailing-comma-object.json \
+        unclosed-list.json unclosed-object.json unclosed-string.json)
+
 GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
 
 test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
@@ -171,6 +179,7 @@  check-help:
 	@echo " make check-qtest-TARGET   Run qtest tests for given target"
 	@echo " make check-qtest          Run qtest tests"
 	@echo " make check-unit           Run qobject tests"
+	@echo " make check-qapi-schema    Run QAPI schema tests"
 	@echo " make check-block          Run block tests"
 	@echo " make check-report.html    Generates an HTML test report"
 	@echo
@@ -233,13 +242,24 @@  check-report.html: check-report.xml
 check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) qemu-io$(EXESUF)
 	$<
 
+.PHONY: check-tests/test-qapi.py
+check-tests/test-qapi.py: tests/test-qapi.py
+
+.PHONY: $(patsubst %, check-%, $(check-qapi-schema-y))
+$(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
+	$(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py <$^ >$*.out 2>$*.err; echo $$? >$*.exit, "  TEST  $*.out")
+	@diff -q $(SRC_PATH)/$*.out $*.out
+	@diff -q $(SRC_PATH)/$*.err $*.err
+	@diff -q $(SRC_PATH)/$*.exit $*.exit
+
 # Consolidated targets
 
-.PHONY: check-qtest check-unit check
+.PHONY: check-qapi-schema check-qtest check-unit check
+check-qapi-schema: $(patsubst %,check-%, $(check-qapi-schema-y))
 check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
 check-unit: $(patsubst %,check-%, $(check-unit-y))
 check-block: $(patsubst %,check-%, $(check-block-y))
-check: check-unit check-qtest
+check: check-qapi-schema check-unit check-qtest
 
 -include $(wildcard tests/*.d)
 -include $(wildcard tests/libqos/*.d)
diff --git a/tests/qapi-schema/comments.err b/tests/qapi-schema/comments.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/comments.exit b/tests/qapi-schema/comments.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/comments.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/comments.json b/tests/qapi-schema/comments.json
new file mode 100644
index 0000000..e643f3a
--- /dev/null
+++ b/tests/qapi-schema/comments.json
@@ -0,0 +1,4 @@ 
+# Unindented comment
+{ 'enum': 'Status',             # Comment to the right of code
+  # Indented comment
+  'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/comments.out b/tests/qapi-schema/comments.out
new file mode 100644
index 0000000..e3bd904
--- /dev/null
+++ b/tests/qapi-schema/comments.out
@@ -0,0 +1,3 @@ 
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+['Status']
+[]
diff --git a/tests/qapi-schema/empty.err b/tests/qapi-schema/empty.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/empty.exit b/tests/qapi-schema/empty.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/empty.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/empty.json b/tests/qapi-schema/empty.json
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/empty.out b/tests/qapi-schema/empty.out
new file mode 100644
index 0000000..b7f89a4
--- /dev/null
+++ b/tests/qapi-schema/empty.out
@@ -0,0 +1,3 @@ 
+[]
+[]
+[]
diff --git a/tests/qapi-schema/funny-char.err b/tests/qapi-schema/funny-char.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/funny-char.exit b/tests/qapi-schema/funny-char.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/funny-char.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/funny-char.json b/tests/qapi-schema/funny-char.json
new file mode 100644
index 0000000..d4973a2
--- /dev/null
+++ b/tests/qapi-schema/funny-char.json
@@ -0,0 +1,2 @@ 
+{ 'enum': 'Status',
+  'data': [ 'good', 'bad', 'ugly' ]; }
diff --git a/tests/qapi-schema/funny-char.out b/tests/qapi-schema/funny-char.out
new file mode 100644
index 0000000..e3bd904
--- /dev/null
+++ b/tests/qapi-schema/funny-char.out
@@ -0,0 +1,3 @@ 
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+['Status']
+[]
diff --git a/tests/qapi-schema/indented-expr.err b/tests/qapi-schema/indented-expr.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/indented-expr.exit b/tests/qapi-schema/indented-expr.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/indented-expr.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/indented-expr.json b/tests/qapi-schema/indented-expr.json
new file mode 100644
index 0000000..d80af60
--- /dev/null
+++ b/tests/qapi-schema/indented-expr.json
@@ -0,0 +1,2 @@ 
+{ 'id' : 'eins' }
+ { 'id' : 'zwei' }
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
new file mode 100644
index 0000000..98ae692
--- /dev/null
+++ b/tests/qapi-schema/indented-expr.out
@@ -0,0 +1,3 @@ 
+[OrderedDict([('id', 'eins')])]
+[]
+[]
diff --git a/tests/qapi-schema/missing-colon.err b/tests/qapi-schema/missing-colon.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/missing-colon.exit b/tests/qapi-schema/missing-colon.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/missing-colon.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/missing-colon.json b/tests/qapi-schema/missing-colon.json
new file mode 100644
index 0000000..6fc27ce
--- /dev/null
+++ b/tests/qapi-schema/missing-colon.json
@@ -0,0 +1,2 @@ 
+{ 'enum' 'Status',
+  'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/missing-colon.out b/tests/qapi-schema/missing-colon.out
new file mode 100644
index 0000000..50f827e
--- /dev/null
+++ b/tests/qapi-schema/missing-colon.out
@@ -0,0 +1,3 @@ 
+[OrderedDict([('enum', ','), ('data', ['good', 'bad', 'ugly'])])]
+[',']
+[]
diff --git a/tests/qapi-schema/missing-comma-list.err b/tests/qapi-schema/missing-comma-list.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/missing-comma-list.exit b/tests/qapi-schema/missing-comma-list.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-list.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/missing-comma-list.json b/tests/qapi-schema/missing-comma-list.json
new file mode 100644
index 0000000..1af39b2
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-list.json
@@ -0,0 +1,2 @@ 
+{ 'enum': 'Status',
+  'data': [ 'good' 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/missing-comma-list.out b/tests/qapi-schema/missing-comma-list.out
new file mode 100644
index 0000000..e3bd904
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-list.out
@@ -0,0 +1,3 @@ 
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+['Status']
+[]
diff --git a/tests/qapi-schema/missing-comma-object.err b/tests/qapi-schema/missing-comma-object.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/missing-comma-object.exit b/tests/qapi-schema/missing-comma-object.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-object.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/missing-comma-object.json b/tests/qapi-schema/missing-comma-object.json
new file mode 100644
index 0000000..50f5178
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-object.json
@@ -0,0 +1,2 @@ 
+{ 'enum': 'Status'
+  'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/missing-comma-object.out b/tests/qapi-schema/missing-comma-object.out
new file mode 100644
index 0000000..e3bd904
--- /dev/null
+++ b/tests/qapi-schema/missing-comma-object.out
@@ -0,0 +1,3 @@ 
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+['Status']
+[]
diff --git a/tests/qapi-schema/non-objects.err b/tests/qapi-schema/non-objects.err
new file mode 100644
index 0000000..48c849d
--- /dev/null
+++ b/tests/qapi-schema/non-objects.err
@@ -0,0 +1 @@ 
+Crashed: <type 'exceptions.AttributeError'>
diff --git a/tests/qapi-schema/non-objects.exit b/tests/qapi-schema/non-objects.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/non-objects.exit
@@ -0,0 +1 @@ 
+1
diff --git a/tests/qapi-schema/non-objects.json b/tests/qapi-schema/non-objects.json
new file mode 100644
index 0000000..f3fa851
--- /dev/null
+++ b/tests/qapi-schema/non-objects.json
@@ -0,0 +1,2 @@ 
+'string'
+[ ]
diff --git a/tests/qapi-schema/non-objects.out b/tests/qapi-schema/non-objects.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/quoted-structural-chars.err b/tests/qapi-schema/quoted-structural-chars.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/quoted-structural-chars.exit b/tests/qapi-schema/quoted-structural-chars.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/quoted-structural-chars.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/quoted-structural-chars.json b/tests/qapi-schema/quoted-structural-chars.json
new file mode 100644
index 0000000..9fe657a
--- /dev/null
+++ b/tests/qapi-schema/quoted-structural-chars.json
@@ -0,0 +1 @@ 
+'{' 'key1' ':' 'value1' ',' 'key2' ':' '[' ']' '}'
diff --git a/tests/qapi-schema/quoted-structural-chars.out b/tests/qapi-schema/quoted-structural-chars.out
new file mode 100644
index 0000000..85405be
--- /dev/null
+++ b/tests/qapi-schema/quoted-structural-chars.out
@@ -0,0 +1,3 @@ 
+[OrderedDict([('key1', 'value1'), ('key2', [])])]
+[]
+[]
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
new file mode 100644
index 0000000..3280eff
--- /dev/null
+++ b/tests/qapi-schema/test-qapi.py
@@ -0,0 +1,25 @@ 
+#
+# QAPI parser test harness
+#
+# Copyright (c) 2013 Red Hat Inc.
+#
+# Authors:
+#  Markus Armbruster <armbru@redhat.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later.
+# See the COPYING file in the top-level directory.
+#
+
+from qapi import *
+from pprint import pprint
+import sys
+
+try:
+    exprs = parse_schema(sys.stdin)
+except:
+    print >>sys.stderr, "Crashed:", sys.exc_info()[0]
+    exit(1)
+
+pprint(exprs)
+pprint(enum_types)
+pprint(struct_types)
diff --git a/tests/qapi-schema/trailing-comma-list.err b/tests/qapi-schema/trailing-comma-list.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/trailing-comma-list.exit b/tests/qapi-schema/trailing-comma-list.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-list.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/trailing-comma-list.json b/tests/qapi-schema/trailing-comma-list.json
new file mode 100644
index 0000000..9b0c8bd
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-list.json
@@ -0,0 +1,2 @@ 
+{ 'enum': 'Status',
+  'data': [ 'good', 'bad', 'ugly', ] }
diff --git a/tests/qapi-schema/trailing-comma-list.out b/tests/qapi-schema/trailing-comma-list.out
new file mode 100644
index 0000000..e3bd904
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-list.out
@@ -0,0 +1,3 @@ 
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+['Status']
+[]
diff --git a/tests/qapi-schema/trailing-comma-object.err b/tests/qapi-schema/trailing-comma-object.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/trailing-comma-object.exit b/tests/qapi-schema/trailing-comma-object.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-object.exit
@@ -0,0 +1 @@ 
+0
diff --git a/tests/qapi-schema/trailing-comma-object.json b/tests/qapi-schema/trailing-comma-object.json
new file mode 100644
index 0000000..bbaea55
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-object.json
@@ -0,0 +1,2 @@ 
+{ 'enum': 'Status',
+  'data': [ 'good', 'bad', 'ugly' ], }
diff --git a/tests/qapi-schema/trailing-comma-object.out b/tests/qapi-schema/trailing-comma-object.out
new file mode 100644
index 0000000..e3bd904
--- /dev/null
+++ b/tests/qapi-schema/trailing-comma-object.out
@@ -0,0 +1,3 @@ 
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+['Status']
+[]
diff --git a/tests/qapi-schema/unclosed-list.err b/tests/qapi-schema/unclosed-list.err
new file mode 100644
index 0000000..f9a9c2a
--- /dev/null
+++ b/tests/qapi-schema/unclosed-list.err
@@ -0,0 +1 @@ 
+Crashed: <type 'exceptions.IndexError'>
diff --git a/tests/qapi-schema/unclosed-list.exit b/tests/qapi-schema/unclosed-list.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/unclosed-list.exit
@@ -0,0 +1 @@ 
+1
diff --git a/tests/qapi-schema/unclosed-list.json b/tests/qapi-schema/unclosed-list.json
new file mode 100644
index 0000000..e3e9566
--- /dev/null
+++ b/tests/qapi-schema/unclosed-list.json
@@ -0,0 +1 @@ 
+{ 'key': [ 'value' }
diff --git a/tests/qapi-schema/unclosed-list.out b/tests/qapi-schema/unclosed-list.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/unclosed-object.err b/tests/qapi-schema/unclosed-object.err
new file mode 100644
index 0000000..f9a9c2a
--- /dev/null
+++ b/tests/qapi-schema/unclosed-object.err
@@ -0,0 +1 @@ 
+Crashed: <type 'exceptions.IndexError'>
diff --git a/tests/qapi-schema/unclosed-object.exit b/tests/qapi-schema/unclosed-object.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/unclosed-object.exit
@@ -0,0 +1 @@ 
+1
diff --git a/tests/qapi-schema/unclosed-object.json b/tests/qapi-schema/unclosed-object.json
new file mode 100644
index 0000000..8ac069d
--- /dev/null
+++ b/tests/qapi-schema/unclosed-object.json
@@ -0,0 +1 @@ 
+{ 'key': [ 'value' ]
diff --git a/tests/qapi-schema/unclosed-object.out b/tests/qapi-schema/unclosed-object.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/unclosed-string.err b/tests/qapi-schema/unclosed-string.err
new file mode 100644
index 0000000..5af46c2
--- /dev/null
+++ b/tests/qapi-schema/unclosed-string.err
@@ -0,0 +1 @@ 
+Crashed: <type 'exceptions.Exception'>
diff --git a/tests/qapi-schema/unclosed-string.exit b/tests/qapi-schema/unclosed-string.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/unclosed-string.exit
@@ -0,0 +1 @@ 
+1
diff --git a/tests/qapi-schema/unclosed-string.json b/tests/qapi-schema/unclosed-string.json
new file mode 100644
index 0000000..8c16b6b
--- /dev/null
+++ b/tests/qapi-schema/unclosed-string.json
@@ -0,0 +1,2 @@ 
+{ 'text': 'lorem ips
+}