summary refs log tree commit diff stats
path: root/tests/qapi-schema
diff options
context:
space:
mode:
Diffstat (limited to 'tests/qapi-schema')
-rw-r--r--tests/qapi-schema/allow-preconfig-test.err3
-rw-r--r--tests/qapi-schema/allow-preconfig-test.exit1
-rw-r--r--tests/qapi-schema/alternate-any.err3
-rw-r--r--tests/qapi-schema/alternate-any.exit1
-rw-r--r--tests/qapi-schema/alternate-array.err3
-rw-r--r--tests/qapi-schema/alternate-array.exit1
-rw-r--r--tests/qapi-schema/alternate-base.err3
-rw-r--r--tests/qapi-schema/alternate-base.exit1
-rw-r--r--tests/qapi-schema/alternate-branch-if-invalid.err2
-rw-r--r--tests/qapi-schema/alternate-branch-if-invalid.json3
-rw-r--r--tests/qapi-schema/alternate-branch-if-invalid.out (renamed from tests/qapi-schema/args-boxed-empty.out)0
-rw-r--r--tests/qapi-schema/alternate-clash.err3
-rw-r--r--tests/qapi-schema/alternate-clash.exit1
-rw-r--r--tests/qapi-schema/alternate-conflict-bool-string.err3
-rw-r--r--tests/qapi-schema/alternate-conflict-bool-string.exit1
-rw-r--r--tests/qapi-schema/alternate-conflict-dict.err3
-rw-r--r--tests/qapi-schema/alternate-conflict-dict.exit1
-rw-r--r--tests/qapi-schema/alternate-conflict-enum-bool.err3
-rw-r--r--tests/qapi-schema/alternate-conflict-enum-bool.exit1
-rw-r--r--tests/qapi-schema/alternate-conflict-enum-int.err3
-rw-r--r--tests/qapi-schema/alternate-conflict-enum-int.exit1
-rw-r--r--tests/qapi-schema/alternate-conflict-num-string.err3
-rw-r--r--tests/qapi-schema/alternate-conflict-num-string.exit1
-rw-r--r--tests/qapi-schema/alternate-conflict-string.err3
-rw-r--r--tests/qapi-schema/alternate-conflict-string.exit1
-rw-r--r--tests/qapi-schema/alternate-empty.err3
-rw-r--r--tests/qapi-schema/alternate-empty.exit1
-rw-r--r--tests/qapi-schema/alternate-empty.json4
-rw-r--r--tests/qapi-schema/alternate-invalid-dict.err3
-rw-r--r--tests/qapi-schema/alternate-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/alternate-nested.err3
-rw-r--r--tests/qapi-schema/alternate-nested.exit1
-rw-r--r--tests/qapi-schema/alternate-unknown.err3
-rw-r--r--tests/qapi-schema/alternate-unknown.exit1
-rw-r--r--tests/qapi-schema/args-alternate.err3
-rw-r--r--tests/qapi-schema/args-alternate.exit1
-rw-r--r--tests/qapi-schema/args-any.err3
-rw-r--r--tests/qapi-schema/args-any.exit1
-rw-r--r--tests/qapi-schema/args-array-empty.err3
-rw-r--r--tests/qapi-schema/args-array-empty.exit1
-rw-r--r--tests/qapi-schema/args-array-unknown.err3
-rw-r--r--tests/qapi-schema/args-array-unknown.exit1
-rw-r--r--tests/qapi-schema/args-bad-boxed.err3
-rw-r--r--tests/qapi-schema/args-bad-boxed.exit1
-rw-r--r--tests/qapi-schema/args-boxed-anon.err3
-rw-r--r--tests/qapi-schema/args-boxed-anon.exit1
-rw-r--r--tests/qapi-schema/args-boxed-empty.err1
-rw-r--r--tests/qapi-schema/args-boxed-empty.exit1
-rw-r--r--tests/qapi-schema/args-boxed-empty.json3
-rw-r--r--tests/qapi-schema/args-boxed-string.err3
-rw-r--r--tests/qapi-schema/args-boxed-string.exit1
-rw-r--r--tests/qapi-schema/args-int.err3
-rw-r--r--tests/qapi-schema/args-int.exit1
-rw-r--r--tests/qapi-schema/args-invalid.err3
-rw-r--r--tests/qapi-schema/args-invalid.exit1
-rw-r--r--tests/qapi-schema/args-member-array-bad.err3
-rw-r--r--tests/qapi-schema/args-member-array-bad.exit1
-rw-r--r--tests/qapi-schema/args-member-case.err3
-rw-r--r--tests/qapi-schema/args-member-case.exit1
-rw-r--r--tests/qapi-schema/args-member-case.json2
-rw-r--r--tests/qapi-schema/args-member-unknown.err3
-rw-r--r--tests/qapi-schema/args-member-unknown.exit1
-rw-r--r--tests/qapi-schema/args-name-clash.err3
-rw-r--r--tests/qapi-schema/args-name-clash.exit1
-rw-r--r--tests/qapi-schema/args-union.err3
-rw-r--r--tests/qapi-schema/args-union.exit1
-rw-r--r--tests/qapi-schema/args-unknown.err3
-rw-r--r--tests/qapi-schema/args-unknown.exit1
-rw-r--r--tests/qapi-schema/bad-base.err3
-rw-r--r--tests/qapi-schema/bad-base.exit1
-rw-r--r--tests/qapi-schema/bad-data.err3
-rw-r--r--tests/qapi-schema/bad-data.exit1
-rw-r--r--tests/qapi-schema/bad-ident.err3
-rw-r--r--tests/qapi-schema/bad-ident.exit1
-rw-r--r--tests/qapi-schema/bad-if-empty-list.err3
-rw-r--r--tests/qapi-schema/bad-if-empty-list.exit1
-rw-r--r--tests/qapi-schema/bad-if-empty.err3
-rw-r--r--tests/qapi-schema/bad-if-empty.exit1
-rw-r--r--tests/qapi-schema/bad-if-list.err3
-rw-r--r--tests/qapi-schema/bad-if-list.exit1
-rw-r--r--tests/qapi-schema/bad-if-list.json2
-rw-r--r--tests/qapi-schema/bad-if.err3
-rw-r--r--tests/qapi-schema/bad-if.exit1
-rw-r--r--tests/qapi-schema/bad-type-bool.err2
-rw-r--r--tests/qapi-schema/bad-type-bool.exit1
-rw-r--r--tests/qapi-schema/bad-type-dict.err2
-rw-r--r--tests/qapi-schema/bad-type-dict.exit1
-rw-r--r--tests/qapi-schema/bad-type-int.err2
-rw-r--r--tests/qapi-schema/bad-type-int.exit1
-rw-r--r--tests/qapi-schema/bad-type-int.json2
-rw-r--r--tests/qapi-schema/base-cycle-direct.err3
-rw-r--r--tests/qapi-schema/base-cycle-direct.exit1
-rw-r--r--tests/qapi-schema/base-cycle-indirect.err3
-rw-r--r--tests/qapi-schema/base-cycle-indirect.exit1
-rw-r--r--tests/qapi-schema/command-int.err3
-rw-r--r--tests/qapi-schema/command-int.exit1
-rw-r--r--tests/qapi-schema/comments.exit1
-rw-r--r--tests/qapi-schema/doc-bad-alternate-member.err2
-rw-r--r--tests/qapi-schema/doc-bad-alternate-member.exit1
-rw-r--r--tests/qapi-schema/doc-bad-command-arg.err2
-rw-r--r--tests/qapi-schema/doc-bad-command-arg.exit1
-rw-r--r--tests/qapi-schema/doc-bad-section.exit1
-rw-r--r--tests/qapi-schema/doc-bad-symbol.err3
-rw-r--r--tests/qapi-schema/doc-bad-symbol.exit1
-rw-r--r--tests/qapi-schema/doc-bad-union-member.err2
-rw-r--r--tests/qapi-schema/doc-bad-union-member.exit1
-rw-r--r--tests/qapi-schema/doc-before-include.err2
-rw-r--r--tests/qapi-schema/doc-before-include.exit1
-rw-r--r--tests/qapi-schema/doc-before-pragma.err2
-rw-r--r--tests/qapi-schema/doc-before-pragma.exit1
-rw-r--r--tests/qapi-schema/doc-duplicated-arg.err2
-rw-r--r--tests/qapi-schema/doc-duplicated-arg.exit1
-rw-r--r--tests/qapi-schema/doc-duplicated-return.err2
-rw-r--r--tests/qapi-schema/doc-duplicated-return.exit1
-rw-r--r--tests/qapi-schema/doc-duplicated-since.err2
-rw-r--r--tests/qapi-schema/doc-duplicated-since.exit1
-rw-r--r--tests/qapi-schema/doc-empty-arg.err2
-rw-r--r--tests/qapi-schema/doc-empty-arg.exit1
-rw-r--r--tests/qapi-schema/doc-empty-section.err2
-rw-r--r--tests/qapi-schema/doc-empty-section.exit1
-rw-r--r--tests/qapi-schema/doc-empty-symbol.err2
-rw-r--r--tests/qapi-schema/doc-empty-symbol.exit1
-rw-r--r--tests/qapi-schema/doc-good.exit1
-rw-r--r--tests/qapi-schema/doc-good.json17
-rw-r--r--tests/qapi-schema/doc-good.out9
-rw-r--r--tests/qapi-schema/doc-good.texi22
-rw-r--r--tests/qapi-schema/doc-interleaved-section.err2
-rw-r--r--tests/qapi-schema/doc-interleaved-section.exit1
-rw-r--r--tests/qapi-schema/doc-invalid-end.err2
-rw-r--r--tests/qapi-schema/doc-invalid-end.exit1
-rw-r--r--tests/qapi-schema/doc-invalid-end2.err2
-rw-r--r--tests/qapi-schema/doc-invalid-end2.exit1
-rw-r--r--tests/qapi-schema/doc-invalid-return.err2
-rw-r--r--tests/qapi-schema/doc-invalid-return.exit1
-rw-r--r--tests/qapi-schema/doc-invalid-section.err2
-rw-r--r--tests/qapi-schema/doc-invalid-section.exit1
-rw-r--r--tests/qapi-schema/doc-invalid-start.err2
-rw-r--r--tests/qapi-schema/doc-invalid-start.exit1
-rw-r--r--tests/qapi-schema/doc-missing-colon.err2
-rw-r--r--tests/qapi-schema/doc-missing-colon.exit1
-rw-r--r--tests/qapi-schema/doc-missing-expr.err2
-rw-r--r--tests/qapi-schema/doc-missing-expr.exit1
-rw-r--r--tests/qapi-schema/doc-missing-space.err2
-rw-r--r--tests/qapi-schema/doc-missing-space.exit1
-rw-r--r--tests/qapi-schema/doc-missing.err3
-rw-r--r--tests/qapi-schema/doc-missing.exit1
-rw-r--r--tests/qapi-schema/doc-no-symbol.err2
-rw-r--r--tests/qapi-schema/doc-no-symbol.exit1
-rw-r--r--tests/qapi-schema/double-data.err1
-rw-r--r--tests/qapi-schema/double-data.exit1
-rw-r--r--tests/qapi-schema/double-data.json2
-rw-r--r--tests/qapi-schema/double-type.err3
-rw-r--r--tests/qapi-schema/double-type.exit1
-rw-r--r--tests/qapi-schema/duplicate-key.err2
-rw-r--r--tests/qapi-schema/duplicate-key.exit1
-rw-r--r--tests/qapi-schema/duplicate-key.json2
-rw-r--r--tests/qapi-schema/empty.exit1
-rw-r--r--tests/qapi-schema/enum-bad-member.err3
-rw-r--r--tests/qapi-schema/enum-bad-member.exit1
-rw-r--r--tests/qapi-schema/enum-bad-name.err3
-rw-r--r--tests/qapi-schema/enum-bad-name.exit1
-rw-r--r--tests/qapi-schema/enum-bad-name.json3
-rw-r--r--tests/qapi-schema/enum-bad-prefix.err3
-rw-r--r--tests/qapi-schema/enum-bad-prefix.exit1
-rw-r--r--tests/qapi-schema/enum-clash-member.err3
-rw-r--r--tests/qapi-schema/enum-clash-member.exit1
-rw-r--r--tests/qapi-schema/enum-dict-member-unknown.err3
-rw-r--r--tests/qapi-schema/enum-dict-member-unknown.exit1
-rw-r--r--tests/qapi-schema/enum-if-invalid.err3
-rw-r--r--tests/qapi-schema/enum-if-invalid.exit1
-rw-r--r--tests/qapi-schema/enum-int-member.err2
-rw-r--r--tests/qapi-schema/enum-int-member.exit1
-rw-r--r--tests/qapi-schema/enum-member-case.err3
-rw-r--r--tests/qapi-schema/enum-member-case.exit1
-rw-r--r--tests/qapi-schema/enum-missing-data.err3
-rw-r--r--tests/qapi-schema/enum-missing-data.exit1
-rw-r--r--tests/qapi-schema/enum-wrong-data.err3
-rw-r--r--tests/qapi-schema/enum-wrong-data.exit1
-rw-r--r--tests/qapi-schema/escape-outside-string.err2
-rw-r--r--tests/qapi-schema/escape-outside-string.exit1
-rw-r--r--tests/qapi-schema/escape-outside-string.json3
-rw-r--r--tests/qapi-schema/escape-too-big.err1
-rw-r--r--tests/qapi-schema/escape-too-big.exit1
-rw-r--r--tests/qapi-schema/escape-too-big.json3
-rw-r--r--tests/qapi-schema/escape-too-short.err1
-rw-r--r--tests/qapi-schema/escape-too-short.exit1
-rw-r--r--tests/qapi-schema/escape-too-short.json3
-rw-r--r--tests/qapi-schema/event-boxed-empty.err3
-rw-r--r--tests/qapi-schema/event-boxed-empty.exit1
-rw-r--r--tests/qapi-schema/event-case.exit1
-rw-r--r--tests/qapi-schema/event-case.out2
-rw-r--r--tests/qapi-schema/event-member-invalid-dict.err3
-rw-r--r--tests/qapi-schema/event-member-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/event-nest-struct.err3
-rw-r--r--tests/qapi-schema/event-nest-struct.exit1
-rw-r--r--tests/qapi-schema/features-bad-type.err3
-rw-r--r--tests/qapi-schema/features-bad-type.exit1
-rw-r--r--tests/qapi-schema/features-duplicate-name.err3
-rw-r--r--tests/qapi-schema/features-duplicate-name.exit1
-rw-r--r--tests/qapi-schema/features-if-invalid.err2
-rw-r--r--tests/qapi-schema/features-if-invalid.json4
-rw-r--r--tests/qapi-schema/features-if-invalid.out (renamed from tests/qapi-schema/double-data.out)0
-rw-r--r--tests/qapi-schema/features-missing-name.err3
-rw-r--r--tests/qapi-schema/features-missing-name.exit1
-rw-r--r--tests/qapi-schema/features-name-bad-type.err3
-rw-r--r--tests/qapi-schema/features-name-bad-type.exit1
-rw-r--r--tests/qapi-schema/features-no-list.err3
-rw-r--r--tests/qapi-schema/features-no-list.exit1
-rw-r--r--tests/qapi-schema/features-unknown-key.err3
-rw-r--r--tests/qapi-schema/features-unknown-key.exit1
-rw-r--r--tests/qapi-schema/flat-union-array-branch.err3
-rw-r--r--tests/qapi-schema/flat-union-array-branch.exit1
-rw-r--r--tests/qapi-schema/flat-union-bad-base.err3
-rw-r--r--tests/qapi-schema/flat-union-bad-base.exit1
-rw-r--r--tests/qapi-schema/flat-union-bad-discriminator.err3
-rw-r--r--tests/qapi-schema/flat-union-bad-discriminator.exit1
-rw-r--r--tests/qapi-schema/flat-union-base-any.err3
-rw-r--r--tests/qapi-schema/flat-union-base-any.exit1
-rw-r--r--tests/qapi-schema/flat-union-base-union.err3
-rw-r--r--tests/qapi-schema/flat-union-base-union.exit1
-rw-r--r--tests/qapi-schema/flat-union-clash-member.err3
-rw-r--r--tests/qapi-schema/flat-union-clash-member.exit1
-rw-r--r--tests/qapi-schema/flat-union-discriminator-bad-name.err2
-rw-r--r--tests/qapi-schema/flat-union-discriminator-bad-name.json10
-rw-r--r--tests/qapi-schema/flat-union-discriminator-bad-name.out (renamed from tests/qapi-schema/escape-outside-string.out)0
-rw-r--r--tests/qapi-schema/flat-union-empty.err3
-rw-r--r--tests/qapi-schema/flat-union-empty.exit1
-rw-r--r--tests/qapi-schema/flat-union-empty.json2
-rw-r--r--tests/qapi-schema/flat-union-inline-invalid-dict.err3
-rw-r--r--tests/qapi-schema/flat-union-inline-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/flat-union-inline.err3
-rw-r--r--tests/qapi-schema/flat-union-inline.exit1
-rw-r--r--tests/qapi-schema/flat-union-int-branch.err3
-rw-r--r--tests/qapi-schema/flat-union-int-branch.exit1
-rw-r--r--tests/qapi-schema/flat-union-invalid-branch-key.err3
-rw-r--r--tests/qapi-schema/flat-union-invalid-branch-key.exit1
-rw-r--r--tests/qapi-schema/flat-union-invalid-discriminator.err3
-rw-r--r--tests/qapi-schema/flat-union-invalid-discriminator.exit1
-rw-r--r--tests/qapi-schema/flat-union-invalid-discriminator.json5
-rw-r--r--tests/qapi-schema/flat-union-invalid-if-discriminator.err3
-rw-r--r--tests/qapi-schema/flat-union-invalid-if-discriminator.exit1
-rw-r--r--tests/qapi-schema/flat-union-invalid-if-discriminator.json5
-rw-r--r--tests/qapi-schema/flat-union-no-base.err3
-rw-r--r--tests/qapi-schema/flat-union-no-base.exit1
-rw-r--r--tests/qapi-schema/flat-union-optional-discriminator.err3
-rw-r--r--tests/qapi-schema/flat-union-optional-discriminator.exit1
-rw-r--r--tests/qapi-schema/flat-union-optional-discriminator.json2
-rw-r--r--tests/qapi-schema/flat-union-string-discriminator.err3
-rw-r--r--tests/qapi-schema/flat-union-string-discriminator.exit1
-rw-r--r--tests/qapi-schema/funny-char.err2
-rw-r--r--tests/qapi-schema/funny-char.exit1
-rw-r--r--tests/qapi-schema/funny-word.err1
-rw-r--r--tests/qapi-schema/funny-word.json1
-rw-r--r--tests/qapi-schema/funny-word.out (renamed from tests/qapi-schema/escape-too-big.out)0
-rw-r--r--tests/qapi-schema/ident-with-escape.err1
-rw-r--r--tests/qapi-schema/ident-with-escape.exit1
-rw-r--r--tests/qapi-schema/ident-with-escape.json2
-rw-r--r--tests/qapi-schema/ident-with-escape.out16
-rw-r--r--tests/qapi-schema/include-before-err.err2
-rw-r--r--tests/qapi-schema/include-before-err.exit1
-rw-r--r--tests/qapi-schema/include-cycle.err6
-rw-r--r--tests/qapi-schema/include-cycle.exit1
-rw-r--r--tests/qapi-schema/include-extra-junk.err2
-rw-r--r--tests/qapi-schema/include-extra-junk.exit1
-rw-r--r--tests/qapi-schema/include-format-err.err1
-rw-r--r--tests/qapi-schema/include-format-err.exit1
-rw-r--r--tests/qapi-schema/include-format-err.json2
-rw-r--r--tests/qapi-schema/include-nested-err.err4
-rw-r--r--tests/qapi-schema/include-nested-err.exit1
-rw-r--r--tests/qapi-schema/include-no-file.err2
-rw-r--r--tests/qapi-schema/include-no-file.exit1
-rw-r--r--tests/qapi-schema/include-non-file.err2
-rw-r--r--tests/qapi-schema/include-non-file.exit1
-rw-r--r--tests/qapi-schema/include-repetition.exit1
-rw-r--r--tests/qapi-schema/include-self-cycle.err2
-rw-r--r--tests/qapi-schema/include-self-cycle.exit1
-rw-r--r--tests/qapi-schema/include-simple.exit1
-rw-r--r--tests/qapi-schema/indented-expr.exit1
-rw-r--r--tests/qapi-schema/indented-expr.out4
-rw-r--r--tests/qapi-schema/leading-comma-list.err2
-rw-r--r--tests/qapi-schema/leading-comma-list.exit1
-rw-r--r--tests/qapi-schema/leading-comma-object.err2
-rw-r--r--tests/qapi-schema/leading-comma-object.exit1
-rw-r--r--tests/qapi-schema/missing-colon.err2
-rw-r--r--tests/qapi-schema/missing-colon.exit1
-rw-r--r--tests/qapi-schema/missing-comma-list.err2
-rw-r--r--tests/qapi-schema/missing-comma-list.exit1
-rw-r--r--tests/qapi-schema/missing-comma-object.err2
-rw-r--r--tests/qapi-schema/missing-comma-object.exit1
-rw-r--r--tests/qapi-schema/missing-type.err2
-rw-r--r--tests/qapi-schema/missing-type.exit1
-rw-r--r--tests/qapi-schema/nested-struct-data-invalid-dict.err3
-rw-r--r--tests/qapi-schema/nested-struct-data-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/nested-struct-data.err3
-rw-r--r--tests/qapi-schema/nested-struct-data.exit1
-rw-r--r--tests/qapi-schema/non-objects.err2
-rw-r--r--tests/qapi-schema/non-objects.exit1
-rw-r--r--tests/qapi-schema/oob-test.err3
-rw-r--r--tests/qapi-schema/oob-test.exit1
-rw-r--r--tests/qapi-schema/pragma-doc-required-crap.err2
-rw-r--r--tests/qapi-schema/pragma-doc-required-crap.exit1
-rw-r--r--tests/qapi-schema/pragma-extra-junk.err2
-rw-r--r--tests/qapi-schema/pragma-extra-junk.exit1
-rw-r--r--tests/qapi-schema/pragma-name-case-whitelist-crap.err2
-rw-r--r--tests/qapi-schema/pragma-name-case-whitelist-crap.exit1
-rw-r--r--tests/qapi-schema/pragma-name-case-whitelist-crap.json2
-rw-r--r--tests/qapi-schema/pragma-non-dict.err2
-rw-r--r--tests/qapi-schema/pragma-non-dict.exit1
-rw-r--r--tests/qapi-schema/pragma-returns-whitelist-crap.err2
-rw-r--r--tests/qapi-schema/pragma-returns-whitelist-crap.exit1
-rw-r--r--tests/qapi-schema/pragma-unknown.err1
-rw-r--r--tests/qapi-schema/pragma-unknown.json1
-rw-r--r--tests/qapi-schema/pragma-unknown.out (renamed from tests/qapi-schema/escape-too-short.out)0
-rw-r--r--tests/qapi-schema/qapi-schema-test.exit1
-rw-r--r--tests/qapi-schema/qapi-schema-test.json31
-rw-r--r--tests/qapi-schema/qapi-schema-test.out92
-rw-r--r--tests/qapi-schema/quoted-structural-chars.err2
-rw-r--r--tests/qapi-schema/quoted-structural-chars.exit1
-rw-r--r--tests/qapi-schema/redefined-builtin.err3
-rw-r--r--tests/qapi-schema/redefined-builtin.exit1
-rw-r--r--tests/qapi-schema/redefined-command.err5
-rw-r--r--tests/qapi-schema/redefined-command.exit1
-rw-r--r--tests/qapi-schema/redefined-event.err5
-rw-r--r--tests/qapi-schema/redefined-event.exit1
-rw-r--r--tests/qapi-schema/redefined-type.err5
-rw-r--r--tests/qapi-schema/redefined-type.exit1
-rw-r--r--tests/qapi-schema/reserved-command-q.err3
-rw-r--r--tests/qapi-schema/reserved-command-q.exit1
-rw-r--r--tests/qapi-schema/reserved-enum-q.err3
-rw-r--r--tests/qapi-schema/reserved-enum-q.exit1
-rw-r--r--tests/qapi-schema/reserved-member-has.err3
-rw-r--r--tests/qapi-schema/reserved-member-has.exit1
-rw-r--r--tests/qapi-schema/reserved-member-q.err3
-rw-r--r--tests/qapi-schema/reserved-member-q.exit1
-rw-r--r--tests/qapi-schema/reserved-member-u.err3
-rw-r--r--tests/qapi-schema/reserved-member-u.exit1
-rw-r--r--tests/qapi-schema/reserved-member-underscore.err3
-rw-r--r--tests/qapi-schema/reserved-member-underscore.exit1
-rw-r--r--tests/qapi-schema/reserved-type-kind.err3
-rw-r--r--tests/qapi-schema/reserved-type-kind.exit1
-rw-r--r--tests/qapi-schema/reserved-type-list.err3
-rw-r--r--tests/qapi-schema/reserved-type-list.exit1
-rw-r--r--tests/qapi-schema/returns-alternate.err3
-rw-r--r--tests/qapi-schema/returns-alternate.exit1
-rw-r--r--tests/qapi-schema/returns-array-bad.err3
-rw-r--r--tests/qapi-schema/returns-array-bad.exit1
-rw-r--r--tests/qapi-schema/returns-dict.err3
-rw-r--r--tests/qapi-schema/returns-dict.exit1
-rw-r--r--tests/qapi-schema/returns-unknown.err3
-rw-r--r--tests/qapi-schema/returns-unknown.exit1
-rw-r--r--tests/qapi-schema/returns-whitelist.err3
-rw-r--r--tests/qapi-schema/returns-whitelist.exit1
-rw-r--r--tests/qapi-schema/string-code-point-127.err1
-rw-r--r--tests/qapi-schema/string-code-point-127.json2
-rw-r--r--tests/qapi-schema/string-code-point-127.out (renamed from tests/qapi-schema/include-format-err.out)0
-rw-r--r--tests/qapi-schema/string-code-point-31.err1
-rw-r--r--tests/qapi-schema/string-code-point-31.json2
-rw-r--r--tests/qapi-schema/string-code-point-31.out (renamed from tests/qapi-schema/unicode-str.out)0
-rw-r--r--tests/qapi-schema/struct-base-clash-deep.err3
-rw-r--r--tests/qapi-schema/struct-base-clash-deep.exit1
-rw-r--r--tests/qapi-schema/struct-base-clash.err3
-rw-r--r--tests/qapi-schema/struct-base-clash.exit1
-rw-r--r--tests/qapi-schema/struct-data-invalid.err3
-rw-r--r--tests/qapi-schema/struct-data-invalid.exit1
-rw-r--r--tests/qapi-schema/struct-member-if-invalid.err2
-rw-r--r--tests/qapi-schema/struct-member-if-invalid.json3
-rw-r--r--tests/qapi-schema/struct-member-if-invalid.out0
-rw-r--r--tests/qapi-schema/struct-member-invalid-dict.err3
-rw-r--r--tests/qapi-schema/struct-member-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/struct-member-invalid.err3
-rw-r--r--tests/qapi-schema/struct-member-invalid.exit1
-rwxr-xr-x[-rw-r--r--]tests/qapi-schema/test-qapi.py151
-rw-r--r--tests/qapi-schema/trailing-comma-list.err2
-rw-r--r--tests/qapi-schema/trailing-comma-list.exit1
-rw-r--r--tests/qapi-schema/trailing-comma-object.err2
-rw-r--r--tests/qapi-schema/trailing-comma-object.exit1
-rw-r--r--tests/qapi-schema/type-bypass-bad-gen.err3
-rw-r--r--tests/qapi-schema/type-bypass-bad-gen.exit1
-rw-r--r--tests/qapi-schema/unclosed-list.err2
-rw-r--r--tests/qapi-schema/unclosed-list.exit1
-rw-r--r--tests/qapi-schema/unclosed-object.err2
-rw-r--r--tests/qapi-schema/unclosed-object.exit1
-rw-r--r--tests/qapi-schema/unclosed-string.err2
-rw-r--r--tests/qapi-schema/unclosed-string.exit1
-rw-r--r--tests/qapi-schema/unicode-str.err1
-rw-r--r--tests/qapi-schema/unicode-str.exit1
-rw-r--r--tests/qapi-schema/unicode-str.json2
-rw-r--r--tests/qapi-schema/union-base-empty.err3
-rw-r--r--tests/qapi-schema/union-base-empty.exit1
-rw-r--r--tests/qapi-schema/union-base-no-discriminator.err3
-rw-r--r--tests/qapi-schema/union-base-no-discriminator.exit1
-rw-r--r--tests/qapi-schema/union-branch-case.err3
-rw-r--r--tests/qapi-schema/union-branch-case.exit1
-rw-r--r--tests/qapi-schema/union-branch-case.json4
-rw-r--r--tests/qapi-schema/union-branch-if-invalid.err2
-rw-r--r--tests/qapi-schema/union-branch-if-invalid.json6
-rw-r--r--tests/qapi-schema/union-branch-if-invalid.out0
-rw-r--r--tests/qapi-schema/union-branch-invalid-dict.err3
-rw-r--r--tests/qapi-schema/union-branch-invalid-dict.exit1
-rw-r--r--tests/qapi-schema/union-clash-branches.err3
-rw-r--r--tests/qapi-schema/union-clash-branches.exit1
-rw-r--r--tests/qapi-schema/union-empty.err3
-rw-r--r--tests/qapi-schema/union-empty.exit1
-rw-r--r--tests/qapi-schema/union-empty.json2
-rw-r--r--tests/qapi-schema/union-invalid-base.err3
-rw-r--r--tests/qapi-schema/union-invalid-base.exit1
-rw-r--r--tests/qapi-schema/union-optional-branch.err3
-rw-r--r--tests/qapi-schema/union-optional-branch.exit1
-rw-r--r--tests/qapi-schema/union-unknown.err3
-rw-r--r--tests/qapi-schema/union-unknown.exit1
-rw-r--r--tests/qapi-schema/union-unknown.json2
-rw-r--r--tests/qapi-schema/unknown-escape.err2
-rw-r--r--tests/qapi-schema/unknown-escape.exit1
-rw-r--r--tests/qapi-schema/unknown-escape.json2
-rw-r--r--tests/qapi-schema/unknown-expr-key.err3
-rw-r--r--tests/qapi-schema/unknown-expr-key.exit1
416 files changed, 621 insertions, 479 deletions
diff --git a/tests/qapi-schema/allow-preconfig-test.err b/tests/qapi-schema/allow-preconfig-test.err
index 700d583306..3cd672bc61 100644
--- a/tests/qapi-schema/allow-preconfig-test.err
+++ b/tests/qapi-schema/allow-preconfig-test.err
@@ -1 +1,2 @@
-tests/qapi-schema/allow-preconfig-test.json:2: 'allow-preconfig' of command 'allow-preconfig-test' should only use true value
+allow-preconfig-test.json: In command 'allow-preconfig-test':
+allow-preconfig-test.json:2: flag 'allow-preconfig' may only use true value
diff --git a/tests/qapi-schema/allow-preconfig-test.exit b/tests/qapi-schema/allow-preconfig-test.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/allow-preconfig-test.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-any.err b/tests/qapi-schema/alternate-any.err
index aaa0154731..baeb3f66d1 100644
--- a/tests/qapi-schema/alternate-any.err
+++ b/tests/qapi-schema/alternate-any.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-any.json:2: Alternate 'Alt' member 'one' cannot use type 'any'
+alternate-any.json: In alternate 'Alt':
+alternate-any.json:2: branch 'one' cannot use built-in type 'any'
diff --git a/tests/qapi-schema/alternate-any.exit b/tests/qapi-schema/alternate-any.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-any.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-array.err b/tests/qapi-schema/alternate-array.err
index 7b930c64ab..b1aa1f4e8d 100644
--- a/tests/qapi-schema/alternate-array.err
+++ b/tests/qapi-schema/alternate-array.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-array.json:5: Member 'two' of alternate 'Alt' cannot be an array
+alternate-array.json: In alternate 'Alt':
+alternate-array.json:5: 'data' member 'two' cannot be an array
diff --git a/tests/qapi-schema/alternate-array.exit b/tests/qapi-schema/alternate-array.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-array.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-base.err b/tests/qapi-schema/alternate-base.err
index ebe05bc898..31ebe56bbf 100644
--- a/tests/qapi-schema/alternate-base.err
+++ b/tests/qapi-schema/alternate-base.err
@@ -1,2 +1,3 @@
-tests/qapi-schema/alternate-base.json:4: Unknown key 'base' in alternate 'Alt'
+alternate-base.json: In alternate 'Alt':
+alternate-base.json:4: alternate has unknown key 'base'
 Valid keys are 'alternate', 'data', 'if'.
diff --git a/tests/qapi-schema/alternate-base.exit b/tests/qapi-schema/alternate-base.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-base.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-branch-if-invalid.err b/tests/qapi-schema/alternate-branch-if-invalid.err
new file mode 100644
index 0000000000..d384929c51
--- /dev/null
+++ b/tests/qapi-schema/alternate-branch-if-invalid.err
@@ -0,0 +1,2 @@
+alternate-branch-if-invalid.json: In alternate 'Alt':
+alternate-branch-if-invalid.json:2: 'if' condition ' ' of 'data' member 'branch' makes no sense
diff --git a/tests/qapi-schema/alternate-branch-if-invalid.json b/tests/qapi-schema/alternate-branch-if-invalid.json
new file mode 100644
index 0000000000..fea6d9080c
--- /dev/null
+++ b/tests/qapi-schema/alternate-branch-if-invalid.json
@@ -0,0 +1,3 @@
+# Cover alternative with invalid 'if'
+{ 'alternate': 'Alt',
+  'data': { 'branch': { 'type': 'int', 'if': ' ' } } }
diff --git a/tests/qapi-schema/args-boxed-empty.out b/tests/qapi-schema/alternate-branch-if-invalid.out
index e69de29bb2..e69de29bb2 100644
--- a/tests/qapi-schema/args-boxed-empty.out
+++ b/tests/qapi-schema/alternate-branch-if-invalid.out
diff --git a/tests/qapi-schema/alternate-clash.err b/tests/qapi-schema/alternate-clash.err
index 604d8495eb..f58b977f7b 100644
--- a/tests/qapi-schema/alternate-clash.err
+++ b/tests/qapi-schema/alternate-clash.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-clash.json:7: 'a_b' (branch of Alt1) collides with 'a-b' (branch of Alt1)
+alternate-clash.json: In alternate 'Alt1':
+alternate-clash.json:7: branch 'a_b' collides with branch 'a-b'
diff --git a/tests/qapi-schema/alternate-clash.exit b/tests/qapi-schema/alternate-clash.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-clash.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-conflict-bool-string.err b/tests/qapi-schema/alternate-conflict-bool-string.err
index e52fee7620..59ff5efa87 100644
--- a/tests/qapi-schema/alternate-conflict-bool-string.err
+++ b/tests/qapi-schema/alternate-conflict-bool-string.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-conflict-bool-string.json:2: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
+alternate-conflict-bool-string.json: In alternate 'Alt':
+alternate-conflict-bool-string.json:2: branch 'two' can't be distinguished from 'one'
diff --git a/tests/qapi-schema/alternate-conflict-bool-string.exit b/tests/qapi-schema/alternate-conflict-bool-string.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-conflict-bool-string.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-conflict-dict.err b/tests/qapi-schema/alternate-conflict-dict.err
index 0f411f4faf..d4970284ba 100644
--- a/tests/qapi-schema/alternate-conflict-dict.err
+++ b/tests/qapi-schema/alternate-conflict-dict.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-conflict-dict.json:6: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
+alternate-conflict-dict.json: In alternate 'Alt':
+alternate-conflict-dict.json:6: branch 'two' can't be distinguished from 'one'
diff --git a/tests/qapi-schema/alternate-conflict-dict.exit b/tests/qapi-schema/alternate-conflict-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-conflict-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-conflict-enum-bool.err b/tests/qapi-schema/alternate-conflict-enum-bool.err
index 0dfc00242d..5f35855274 100644
--- a/tests/qapi-schema/alternate-conflict-enum-bool.err
+++ b/tests/qapi-schema/alternate-conflict-enum-bool.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-conflict-enum-bool.json:4: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
+alternate-conflict-enum-bool.json: In alternate 'Alt':
+alternate-conflict-enum-bool.json:4: branch 'two' can't be distinguished from 'one'
diff --git a/tests/qapi-schema/alternate-conflict-enum-bool.exit b/tests/qapi-schema/alternate-conflict-enum-bool.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-conflict-enum-bool.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-conflict-enum-int.err b/tests/qapi-schema/alternate-conflict-enum-int.err
index 2cc8e7b9aa..6a6d156664 100644
--- a/tests/qapi-schema/alternate-conflict-enum-int.err
+++ b/tests/qapi-schema/alternate-conflict-enum-int.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-conflict-enum-int.json:4: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
+alternate-conflict-enum-int.json: In alternate 'Alt':
+alternate-conflict-enum-int.json:4: branch 'two' can't be distinguished from 'one'
diff --git a/tests/qapi-schema/alternate-conflict-enum-int.exit b/tests/qapi-schema/alternate-conflict-enum-int.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-conflict-enum-int.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-conflict-num-string.err b/tests/qapi-schema/alternate-conflict-num-string.err
index 5ba3827dd1..38c805ea1f 100644
--- a/tests/qapi-schema/alternate-conflict-num-string.err
+++ b/tests/qapi-schema/alternate-conflict-num-string.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-conflict-num-string.json:2: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
+alternate-conflict-num-string.json: In alternate 'Alt':
+alternate-conflict-num-string.json:2: branch 'two' can't be distinguished from 'one'
diff --git a/tests/qapi-schema/alternate-conflict-num-string.exit b/tests/qapi-schema/alternate-conflict-num-string.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-conflict-num-string.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-conflict-string.err b/tests/qapi-schema/alternate-conflict-string.err
index fe2f188295..2fa08193db 100644
--- a/tests/qapi-schema/alternate-conflict-string.err
+++ b/tests/qapi-schema/alternate-conflict-string.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-conflict-string.json:2: Alternate 'Alt' member 'two' can't be distinguished from member 'one'
+alternate-conflict-string.json: In alternate 'Alt':
+alternate-conflict-string.json:2: branch 'two' can't be distinguished from 'one'
diff --git a/tests/qapi-schema/alternate-conflict-string.exit b/tests/qapi-schema/alternate-conflict-string.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-conflict-string.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-empty.err b/tests/qapi-schema/alternate-empty.err
index bb06c5bfec..c6f6401d18 100644
--- a/tests/qapi-schema/alternate-empty.err
+++ b/tests/qapi-schema/alternate-empty.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-empty.json:2: Alternate 'Alt' should have at least two branches in 'data'
+alternate-empty.json: In alternate 'Alt':
+alternate-empty.json:2: 'data' must not be empty
diff --git a/tests/qapi-schema/alternate-empty.exit b/tests/qapi-schema/alternate-empty.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-empty.json b/tests/qapi-schema/alternate-empty.json
index fff15baf16..9f445474e6 100644
--- a/tests/qapi-schema/alternate-empty.json
+++ b/tests/qapi-schema/alternate-empty.json
@@ -1,2 +1,2 @@
-# alternates must list at least two types to be useful
-{ 'alternate': 'Alt', 'data': { 'i': 'int' } }
+# alternates cannot be empty
+{ 'alternate': 'Alt', 'data': { } }
diff --git a/tests/qapi-schema/alternate-invalid-dict.err b/tests/qapi-schema/alternate-invalid-dict.err
index 631d46628e..e9e5025226 100644
--- a/tests/qapi-schema/alternate-invalid-dict.err
+++ b/tests/qapi-schema/alternate-invalid-dict.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-invalid-dict.json:2: Key 'type' is missing from member 'two' of alternate 'Alt'
+alternate-invalid-dict.json: In alternate 'Alt':
+alternate-invalid-dict.json:2: 'data' member 'two' misses key 'type'
diff --git a/tests/qapi-schema/alternate-invalid-dict.exit b/tests/qapi-schema/alternate-invalid-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-invalid-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-nested.err b/tests/qapi-schema/alternate-nested.err
index 4d1187e60e..3ae9cd2f11 100644
--- a/tests/qapi-schema/alternate-nested.err
+++ b/tests/qapi-schema/alternate-nested.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-nested.json:4: Member 'nested' of alternate 'Alt2' cannot use alternate type 'Alt1'
+alternate-nested.json: In alternate 'Alt2':
+alternate-nested.json:4: branch 'nested' cannot use alternate type 'Alt1'
diff --git a/tests/qapi-schema/alternate-nested.exit b/tests/qapi-schema/alternate-nested.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-nested.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/alternate-unknown.err b/tests/qapi-schema/alternate-unknown.err
index dea45dc730..17fec1cd17 100644
--- a/tests/qapi-schema/alternate-unknown.err
+++ b/tests/qapi-schema/alternate-unknown.err
@@ -1 +1,2 @@
-tests/qapi-schema/alternate-unknown.json:2: Member 'unknown' of alternate 'Alt' uses unknown type 'MissingType'
+alternate-unknown.json: In alternate 'Alt':
+alternate-unknown.json:2: branch 'unknown' uses unknown type 'MissingType'
diff --git a/tests/qapi-schema/alternate-unknown.exit b/tests/qapi-schema/alternate-unknown.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/alternate-unknown.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-alternate.err b/tests/qapi-schema/args-alternate.err
index 3086eae56b..b1530aa610 100644
--- a/tests/qapi-schema/args-alternate.err
+++ b/tests/qapi-schema/args-alternate.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-alternate.json:3: 'data' for command 'oops' cannot use alternate type 'Alt'
+args-alternate.json: In command 'oops':
+args-alternate.json:3: command's 'data' cannot take alternate type 'Alt'
diff --git a/tests/qapi-schema/args-alternate.exit b/tests/qapi-schema/args-alternate.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-alternate.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-any.err b/tests/qapi-schema/args-any.err
index bf9b5e0730..4b60560247 100644
--- a/tests/qapi-schema/args-any.err
+++ b/tests/qapi-schema/args-any.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-any.json:2: 'data' for command 'oops' cannot use built-in type 'any'
+args-any.json: In command 'oops':
+args-any.json:2: command's 'data' cannot take built-in type 'any'
diff --git a/tests/qapi-schema/args-any.exit b/tests/qapi-schema/args-any.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-any.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-array-empty.err b/tests/qapi-schema/args-array-empty.err
index cb7ed33b3f..181222296e 100644
--- a/tests/qapi-schema/args-array-empty.err
+++ b/tests/qapi-schema/args-array-empty.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-array-empty.json:2: Member 'empty' of 'data' for command 'oops': array type must contain single type name
+args-array-empty.json: In command 'oops':
+args-array-empty.json:2: 'data' member 'empty': array type must contain single type name
diff --git a/tests/qapi-schema/args-array-empty.exit b/tests/qapi-schema/args-array-empty.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-array-empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-array-unknown.err b/tests/qapi-schema/args-array-unknown.err
index cd7a0f98d7..cbc598e4ff 100644
--- a/tests/qapi-schema/args-array-unknown.err
+++ b/tests/qapi-schema/args-array-unknown.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-array-unknown.json:2: Member 'array' of 'data' for command 'oops' uses unknown type 'NoSuchType'
+args-array-unknown.json: In command 'oops':
+args-array-unknown.json:2: command uses unknown type 'NoSuchType'
diff --git a/tests/qapi-schema/args-array-unknown.exit b/tests/qapi-schema/args-array-unknown.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-array-unknown.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-bad-boxed.err b/tests/qapi-schema/args-bad-boxed.err
index ad0d417321..361276eb29 100644
--- a/tests/qapi-schema/args-bad-boxed.err
+++ b/tests/qapi-schema/args-bad-boxed.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-bad-boxed.json:2: 'boxed' of command 'foo' should only use true value
+args-bad-boxed.json: In command 'foo':
+args-bad-boxed.json:2: flag 'boxed' may only use true value
diff --git a/tests/qapi-schema/args-bad-boxed.exit b/tests/qapi-schema/args-bad-boxed.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-bad-boxed.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-boxed-anon.err b/tests/qapi-schema/args-boxed-anon.err
index f24f345218..a89af75bef 100644
--- a/tests/qapi-schema/args-boxed-anon.err
+++ b/tests/qapi-schema/args-boxed-anon.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-boxed-anon.json:2: 'data' for command 'foo' should be a type name
+args-boxed-anon.json: In command 'foo':
+args-boxed-anon.json:2: 'data' should be a type name
diff --git a/tests/qapi-schema/args-boxed-anon.exit b/tests/qapi-schema/args-boxed-anon.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-boxed-anon.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-boxed-empty.err b/tests/qapi-schema/args-boxed-empty.err
deleted file mode 100644
index 039603e85c..0000000000
--- a/tests/qapi-schema/args-boxed-empty.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/args-boxed-empty.json:3: Cannot use 'boxed' with empty type
diff --git a/tests/qapi-schema/args-boxed-empty.exit b/tests/qapi-schema/args-boxed-empty.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-boxed-empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-boxed-empty.json b/tests/qapi-schema/args-boxed-empty.json
deleted file mode 100644
index 52717e065f..0000000000
--- a/tests/qapi-schema/args-boxed-empty.json
+++ /dev/null
@@ -1,3 +0,0 @@
-# 'boxed' requires a non-empty type
-{ 'struct': 'Empty', 'data': {} }
-{ 'command': 'foo', 'boxed': true, 'data': 'Empty' }
diff --git a/tests/qapi-schema/args-boxed-string.err b/tests/qapi-schema/args-boxed-string.err
index d326b48aef..415c1148a9 100644
--- a/tests/qapi-schema/args-boxed-string.err
+++ b/tests/qapi-schema/args-boxed-string.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-boxed-string.json:2: 'data' for command 'foo' cannot use built-in type 'str'
+args-boxed-string.json: In command 'foo':
+args-boxed-string.json:2: command's 'data' cannot take built-in type 'str'
diff --git a/tests/qapi-schema/args-boxed-string.exit b/tests/qapi-schema/args-boxed-string.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-boxed-string.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-int.err b/tests/qapi-schema/args-int.err
index dc1d2504ff..a2331c5543 100644
--- a/tests/qapi-schema/args-int.err
+++ b/tests/qapi-schema/args-int.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-int.json:2: 'data' for command 'oops' cannot use built-in type 'int'
+args-int.json: In command 'oops':
+args-int.json:2: command's 'data' cannot take built-in type 'int'
diff --git a/tests/qapi-schema/args-int.exit b/tests/qapi-schema/args-int.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-int.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-invalid.err b/tests/qapi-schema/args-invalid.err
index fe1e94975b..1527c4a48d 100644
--- a/tests/qapi-schema/args-invalid.err
+++ b/tests/qapi-schema/args-invalid.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-invalid.json:1: 'data' for command 'foo' should be a dictionary or type name
+args-invalid.json: In command 'foo':
+args-invalid.json:1: 'data' should be an object or type name
diff --git a/tests/qapi-schema/args-invalid.exit b/tests/qapi-schema/args-invalid.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-invalid.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-member-array-bad.err b/tests/qapi-schema/args-member-array-bad.err
index 881b4d954f..194a3052d2 100644
--- a/tests/qapi-schema/args-member-array-bad.err
+++ b/tests/qapi-schema/args-member-array-bad.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-member-array-bad.json:2: Member 'member' of 'data' for command 'oops': array type must contain single type name
+args-member-array-bad.json: In command 'oops':
+args-member-array-bad.json:2: 'data' member 'member': array type must contain single type name
diff --git a/tests/qapi-schema/args-member-array-bad.exit b/tests/qapi-schema/args-member-array-bad.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-member-array-bad.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-member-case.err b/tests/qapi-schema/args-member-case.err
index 19c4426601..4f33dbbc38 100644
--- a/tests/qapi-schema/args-member-case.err
+++ b/tests/qapi-schema/args-member-case.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-member-case.json:2: 'Arg' (parameter of no-way-this-will-get-whitelisted) should not use uppercase
+args-member-case.json: In command 'no-way-this-will-get-whitelisted':
+args-member-case.json:2: 'data' member 'Arg' uses uppercase in name
diff --git a/tests/qapi-schema/args-member-case.exit b/tests/qapi-schema/args-member-case.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-member-case.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-member-case.json b/tests/qapi-schema/args-member-case.json
index 93439bee8b..e27c603548 100644
--- a/tests/qapi-schema/args-member-case.json
+++ b/tests/qapi-schema/args-member-case.json
@@ -1,2 +1,2 @@
-# Member names should be 'lower-case' unless the struct/command is whitelisted
+# Member names should be 'lower-case' unless the struct is whitelisted
 { 'command': 'no-way-this-will-get-whitelisted', 'data': { 'Arg': 'int' } }
diff --git a/tests/qapi-schema/args-member-unknown.err b/tests/qapi-schema/args-member-unknown.err
index f6f82828ce..96b6e5d289 100644
--- a/tests/qapi-schema/args-member-unknown.err
+++ b/tests/qapi-schema/args-member-unknown.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-member-unknown.json:2: Member 'member' of 'data' for command 'oops' uses unknown type 'NoSuchType'
+args-member-unknown.json: In command 'oops':
+args-member-unknown.json:2: parameter 'member' uses unknown type 'NoSuchType'
diff --git a/tests/qapi-schema/args-member-unknown.exit b/tests/qapi-schema/args-member-unknown.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-member-unknown.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-name-clash.err b/tests/qapi-schema/args-name-clash.err
index d953e8d241..3e04817bc0 100644
--- a/tests/qapi-schema/args-name-clash.err
+++ b/tests/qapi-schema/args-name-clash.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-name-clash.json:4: 'a_b' (parameter of oops) collides with 'a-b' (parameter of oops)
+args-name-clash.json: In command 'oops':
+args-name-clash.json:4: parameter 'a_b' collides with parameter 'a-b'
diff --git a/tests/qapi-schema/args-name-clash.exit b/tests/qapi-schema/args-name-clash.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-name-clash.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-union.err b/tests/qapi-schema/args-union.err
index f8ad223dde..4bf4955027 100644
--- a/tests/qapi-schema/args-union.err
+++ b/tests/qapi-schema/args-union.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-union.json:3: 'data' for command 'oops' cannot use union type 'Uni'
+args-union.json: In command 'oops':
+args-union.json:3: command's 'data' can take union type 'Uni' only with 'boxed': true
diff --git a/tests/qapi-schema/args-union.exit b/tests/qapi-schema/args-union.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-union.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/args-unknown.err b/tests/qapi-schema/args-unknown.err
index 4d91ec869f..44bf8706ae 100644
--- a/tests/qapi-schema/args-unknown.err
+++ b/tests/qapi-schema/args-unknown.err
@@ -1 +1,2 @@
-tests/qapi-schema/args-unknown.json:2: 'data' for command 'oops' uses unknown type 'NoSuchType'
+args-unknown.json: In command 'oops':
+args-unknown.json:2: command's 'data' uses unknown type 'NoSuchType'
diff --git a/tests/qapi-schema/args-unknown.exit b/tests/qapi-schema/args-unknown.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/args-unknown.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-base.err b/tests/qapi-schema/bad-base.err
index 154274bdd3..61a1efc2c0 100644
--- a/tests/qapi-schema/bad-base.err
+++ b/tests/qapi-schema/bad-base.err
@@ -1 +1,2 @@
-tests/qapi-schema/bad-base.json:3: 'base' for struct 'MyType' cannot use union type 'Union'
+bad-base.json: In struct 'MyType':
+bad-base.json:3: 'base' requires a struct type, union type 'Union' isn't
diff --git a/tests/qapi-schema/bad-base.exit b/tests/qapi-schema/bad-base.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-base.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-data.err b/tests/qapi-schema/bad-data.err
index 8523ac4f46..7991c8898d 100644
--- a/tests/qapi-schema/bad-data.err
+++ b/tests/qapi-schema/bad-data.err
@@ -1 +1,2 @@
-tests/qapi-schema/bad-data.json:2: 'data' for command 'oops' cannot be an array
+bad-data.json: In command 'oops':
+bad-data.json:2: 'data' cannot be an array
diff --git a/tests/qapi-schema/bad-data.exit b/tests/qapi-schema/bad-data.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-data.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-ident.err b/tests/qapi-schema/bad-ident.err
index c4190602b5..263fcd3ecd 100644
--- a/tests/qapi-schema/bad-ident.err
+++ b/tests/qapi-schema/bad-ident.err
@@ -1 +1,2 @@
-tests/qapi-schema/bad-ident.json:2: 'struct' does not allow optional name '*oops'
+bad-ident.json: In struct '*oops':
+bad-ident.json:2: struct has an invalid name
diff --git a/tests/qapi-schema/bad-ident.exit b/tests/qapi-schema/bad-ident.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-ident.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-if-empty-list.err b/tests/qapi-schema/bad-if-empty-list.err
index 75fe6497bc..a946376d06 100644
--- a/tests/qapi-schema/bad-if-empty-list.err
+++ b/tests/qapi-schema/bad-if-empty-list.err
@@ -1 +1,2 @@
-tests/qapi-schema/bad-if-empty-list.json:2: 'if' condition [] is useless
+bad-if-empty-list.json: In struct 'TestIfStruct':
+bad-if-empty-list.json:2: 'if' condition [] of struct is useless
diff --git a/tests/qapi-schema/bad-if-empty-list.exit b/tests/qapi-schema/bad-if-empty-list.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-if-empty-list.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-if-empty.err b/tests/qapi-schema/bad-if-empty.err
index 358bdc3e51..a0f3effefb 100644
--- a/tests/qapi-schema/bad-if-empty.err
+++ b/tests/qapi-schema/bad-if-empty.err
@@ -1 +1,2 @@
-tests/qapi-schema/bad-if-empty.json:2: 'if' condition '' makes no sense
+bad-if-empty.json: In struct 'TestIfStruct':
+bad-if-empty.json:2: 'if' condition '' of struct makes no sense
diff --git a/tests/qapi-schema/bad-if-empty.exit b/tests/qapi-schema/bad-if-empty.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-if-empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-if-list.err b/tests/qapi-schema/bad-if-list.err
index 0af6316f78..c462f11b90 100644
--- a/tests/qapi-schema/bad-if-list.err
+++ b/tests/qapi-schema/bad-if-list.err
@@ -1 +1,2 @@
-tests/qapi-schema/bad-if-list.json:2: 'if' condition '' makes no sense
+bad-if-list.json: In struct 'TestIfStruct':
+bad-if-list.json:2: 'if' condition ' ' of struct makes no sense
diff --git a/tests/qapi-schema/bad-if-list.exit b/tests/qapi-schema/bad-if-list.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-if-list.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-if-list.json b/tests/qapi-schema/bad-if-list.json
index 49ced9b9ca..ea3d95bb6b 100644
--- a/tests/qapi-schema/bad-if-list.json
+++ b/tests/qapi-schema/bad-if-list.json
@@ -1,3 +1,3 @@
 # check invalid 'if' content
 { 'struct': 'TestIfStruct', 'data': { 'foo': 'int' },
-  'if': ['foo', ''] }
+  'if': ['foo', ' '] }
diff --git a/tests/qapi-schema/bad-if.err b/tests/qapi-schema/bad-if.err
index c2e3f5f44c..f83dee65da 100644
--- a/tests/qapi-schema/bad-if.err
+++ b/tests/qapi-schema/bad-if.err
@@ -1 +1,2 @@
-tests/qapi-schema/bad-if.json:2: 'if' condition must be a string or a list of strings
+bad-if.json: In struct 'TestIfStruct':
+bad-if.json:2: 'if' condition of struct must be a string or a list of strings
diff --git a/tests/qapi-schema/bad-if.exit b/tests/qapi-schema/bad-if.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-if.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-type-bool.err b/tests/qapi-schema/bad-type-bool.err
index 62fd70baaf..42ccc18988 100644
--- a/tests/qapi-schema/bad-type-bool.err
+++ b/tests/qapi-schema/bad-type-bool.err
@@ -1 +1 @@
-tests/qapi-schema/bad-type-bool.json:2: 'struct' key must have a string value
+bad-type-bool.json:2: 'struct' requires a string name
diff --git a/tests/qapi-schema/bad-type-bool.exit b/tests/qapi-schema/bad-type-bool.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-type-bool.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-type-dict.err b/tests/qapi-schema/bad-type-dict.err
index 0b2a2aeac4..3d97cd3f0a 100644
--- a/tests/qapi-schema/bad-type-dict.err
+++ b/tests/qapi-schema/bad-type-dict.err
@@ -1 +1 @@
-tests/qapi-schema/bad-type-dict.json:2: 'command' key must have a string value
+bad-type-dict.json:2: 'command' requires a string name
diff --git a/tests/qapi-schema/bad-type-dict.exit b/tests/qapi-schema/bad-type-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-type-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-type-int.err b/tests/qapi-schema/bad-type-int.err
index da89895404..90d06bd94d 100644
--- a/tests/qapi-schema/bad-type-int.err
+++ b/tests/qapi-schema/bad-type-int.err
@@ -1 +1 @@
-tests/qapi-schema/bad-type-int.json:3:13: Stray "1"
+bad-type-int.json:3:13: stray '123'
diff --git a/tests/qapi-schema/bad-type-int.exit b/tests/qapi-schema/bad-type-int.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/bad-type-int.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/bad-type-int.json b/tests/qapi-schema/bad-type-int.json
index 56fc6f8126..f3ad803cb6 100644
--- a/tests/qapi-schema/bad-type-int.json
+++ b/tests/qapi-schema/bad-type-int.json
@@ -1,3 +1,3 @@
 # we reject an expression with a metatype that is not a string
 # FIXME: once the parser understands integer inputs, improve the error message
-{ 'struct': 1, 'data': { } }
+{ 'struct': 123, 'data': { } }
diff --git a/tests/qapi-schema/base-cycle-direct.err b/tests/qapi-schema/base-cycle-direct.err
index 9c68f6543d..4ea6c5064e 100644
--- a/tests/qapi-schema/base-cycle-direct.err
+++ b/tests/qapi-schema/base-cycle-direct.err
@@ -1 +1,2 @@
-tests/qapi-schema/base-cycle-direct.json:2: Object Loopy contains itself
+base-cycle-direct.json: In struct 'Loopy':
+base-cycle-direct.json:2: object Loopy contains itself
diff --git a/tests/qapi-schema/base-cycle-direct.exit b/tests/qapi-schema/base-cycle-direct.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/base-cycle-direct.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/base-cycle-indirect.err b/tests/qapi-schema/base-cycle-indirect.err
index fc92fe47f8..9b5e7ec174 100644
--- a/tests/qapi-schema/base-cycle-indirect.err
+++ b/tests/qapi-schema/base-cycle-indirect.err
@@ -1 +1,2 @@
-tests/qapi-schema/base-cycle-indirect.json:2: Object Base1 contains itself
+base-cycle-indirect.json: In struct 'Base1':
+base-cycle-indirect.json:2: object Base1 contains itself
diff --git a/tests/qapi-schema/base-cycle-indirect.exit b/tests/qapi-schema/base-cycle-indirect.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/base-cycle-indirect.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/command-int.err b/tests/qapi-schema/command-int.err
index 0f9300679b..df0e5f5a57 100644
--- a/tests/qapi-schema/command-int.err
+++ b/tests/qapi-schema/command-int.err
@@ -1 +1,2 @@
-tests/qapi-schema/command-int.json:2: built-in 'int' is already defined
+command-int.json: In command 'int':
+command-int.json:2: built-in type 'int' is already defined
diff --git a/tests/qapi-schema/command-int.exit b/tests/qapi-schema/command-int.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/command-int.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/comments.exit b/tests/qapi-schema/comments.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/comments.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/doc-bad-alternate-member.err b/tests/qapi-schema/doc-bad-alternate-member.err
index 387f7824da..a1c282f935 100644
--- a/tests/qapi-schema/doc-bad-alternate-member.err
+++ b/tests/qapi-schema/doc-bad-alternate-member.err
@@ -1 +1 @@
-tests/qapi-schema/doc-bad-alternate-member.json:3: The following documented members are not in the declaration: aa, bb
+doc-bad-alternate-member.json:3: the following documented members are not in the declaration: aa, bb
diff --git a/tests/qapi-schema/doc-bad-alternate-member.exit b/tests/qapi-schema/doc-bad-alternate-member.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-bad-alternate-member.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-bad-command-arg.err b/tests/qapi-schema/doc-bad-command-arg.err
index 8075b146ae..153ea0330a 100644
--- a/tests/qapi-schema/doc-bad-command-arg.err
+++ b/tests/qapi-schema/doc-bad-command-arg.err
@@ -1 +1 @@
-tests/qapi-schema/doc-bad-command-arg.json:3: The following documented members are not in the declaration: b
+doc-bad-command-arg.json:3: the following documented members are not in the declaration: b
diff --git a/tests/qapi-schema/doc-bad-command-arg.exit b/tests/qapi-schema/doc-bad-command-arg.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-bad-command-arg.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-bad-section.exit b/tests/qapi-schema/doc-bad-section.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/doc-bad-section.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/doc-bad-symbol.err b/tests/qapi-schema/doc-bad-symbol.err
index 8472030c79..166c8dcc18 100644
--- a/tests/qapi-schema/doc-bad-symbol.err
+++ b/tests/qapi-schema/doc-bad-symbol.err
@@ -1 +1,2 @@
-tests/qapi-schema/doc-bad-symbol.json:6: Definition of 'foo' follows documentation for 'food'
+doc-bad-symbol.json: In command 'foo':
+doc-bad-symbol.json:6: documentation comment is for 'food'
diff --git a/tests/qapi-schema/doc-bad-symbol.exit b/tests/qapi-schema/doc-bad-symbol.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-bad-symbol.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-bad-union-member.err b/tests/qapi-schema/doc-bad-union-member.err
index 4b016df7ff..8b9d36eab1 100644
--- a/tests/qapi-schema/doc-bad-union-member.err
+++ b/tests/qapi-schema/doc-bad-union-member.err
@@ -1 +1 @@
-tests/qapi-schema/doc-bad-union-member.json:3: The following documented members are not in the declaration: a, b
+doc-bad-union-member.json:3: the following documented members are not in the declaration: a, b
diff --git a/tests/qapi-schema/doc-bad-union-member.exit b/tests/qapi-schema/doc-bad-union-member.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-bad-union-member.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-before-include.err b/tests/qapi-schema/doc-before-include.err
index a649d38a63..ae23ea2f57 100644
--- a/tests/qapi-schema/doc-before-include.err
+++ b/tests/qapi-schema/doc-before-include.err
@@ -1 +1 @@
-tests/qapi-schema/doc-before-include.json:3: Documentation for 'foo' is not followed by the definition
+doc-before-include.json:3: documentation for 'foo' is not followed by the definition
diff --git a/tests/qapi-schema/doc-before-include.exit b/tests/qapi-schema/doc-before-include.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-before-include.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-before-pragma.err b/tests/qapi-schema/doc-before-pragma.err
index c0fb0660d1..c776252e07 100644
--- a/tests/qapi-schema/doc-before-pragma.err
+++ b/tests/qapi-schema/doc-before-pragma.err
@@ -1 +1 @@
-tests/qapi-schema/doc-before-pragma.json:3: Documentation for 'foo' is not followed by the definition
+doc-before-pragma.json:3: documentation for 'foo' is not followed by the definition
diff --git a/tests/qapi-schema/doc-before-pragma.exit b/tests/qapi-schema/doc-before-pragma.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-before-pragma.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-duplicated-arg.err b/tests/qapi-schema/doc-duplicated-arg.err
index 1c3f8e0a54..0d0d777a1f 100644
--- a/tests/qapi-schema/doc-duplicated-arg.err
+++ b/tests/qapi-schema/doc-duplicated-arg.err
@@ -1 +1 @@
-tests/qapi-schema/doc-duplicated-arg.json:6:1: 'a' parameter name duplicated
+doc-duplicated-arg.json:6:1: 'a' parameter name duplicated
diff --git a/tests/qapi-schema/doc-duplicated-arg.exit b/tests/qapi-schema/doc-duplicated-arg.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-duplicated-arg.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-duplicated-return.err b/tests/qapi-schema/doc-duplicated-return.err
index e48039f8e5..fe97e3db8d 100644
--- a/tests/qapi-schema/doc-duplicated-return.err
+++ b/tests/qapi-schema/doc-duplicated-return.err
@@ -1 +1 @@
-tests/qapi-schema/doc-duplicated-return.json:7:1: Duplicated 'Returns' section
+doc-duplicated-return.json:7:1: duplicated 'Returns' section
diff --git a/tests/qapi-schema/doc-duplicated-return.exit b/tests/qapi-schema/doc-duplicated-return.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-duplicated-return.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-duplicated-since.err b/tests/qapi-schema/doc-duplicated-since.err
index 3fb890744a..abca141a2c 100644
--- a/tests/qapi-schema/doc-duplicated-since.err
+++ b/tests/qapi-schema/doc-duplicated-since.err
@@ -1 +1 @@
-tests/qapi-schema/doc-duplicated-since.json:7:1: Duplicated 'Since' section
+doc-duplicated-since.json:7:1: duplicated 'Since' section
diff --git a/tests/qapi-schema/doc-duplicated-since.exit b/tests/qapi-schema/doc-duplicated-since.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-duplicated-since.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-empty-arg.err b/tests/qapi-schema/doc-empty-arg.err
index 2895518fa7..2d0f35f310 100644
--- a/tests/qapi-schema/doc-empty-arg.err
+++ b/tests/qapi-schema/doc-empty-arg.err
@@ -1 +1 @@
-tests/qapi-schema/doc-empty-arg.json:5:1: Invalid parameter name
+doc-empty-arg.json:5:1: invalid parameter name
diff --git a/tests/qapi-schema/doc-empty-arg.exit b/tests/qapi-schema/doc-empty-arg.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-empty-arg.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-empty-section.err b/tests/qapi-schema/doc-empty-section.err
index b61e4a7886..ba7ba70125 100644
--- a/tests/qapi-schema/doc-empty-section.err
+++ b/tests/qapi-schema/doc-empty-section.err
@@ -1 +1 @@
-tests/qapi-schema/doc-empty-section.json:7:1: Empty doc section 'Note'
+doc-empty-section.json:7:1: empty doc section 'Note'
diff --git a/tests/qapi-schema/doc-empty-section.exit b/tests/qapi-schema/doc-empty-section.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-empty-section.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-empty-symbol.err b/tests/qapi-schema/doc-empty-symbol.err
index 1936ad094f..81b90e882a 100644
--- a/tests/qapi-schema/doc-empty-symbol.err
+++ b/tests/qapi-schema/doc-empty-symbol.err
@@ -1 +1 @@
-tests/qapi-schema/doc-empty-symbol.json:4:1: Invalid name
+doc-empty-symbol.json:4:1: invalid name
diff --git a/tests/qapi-schema/doc-empty-symbol.exit b/tests/qapi-schema/doc-empty-symbol.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-empty-symbol.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-good.exit b/tests/qapi-schema/doc-good.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/doc-good.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/doc-good.json b/tests/qapi-schema/doc-good.json
index f7fb48af38..7dc21e58a3 100644
--- a/tests/qapi-schema/doc-good.json
+++ b/tests/qapi-schema/doc-good.json
@@ -71,8 +71,12 @@
 # A paragraph
 #
 # Another paragraph (but no @var: line)
+#
+# Features:
+# @variant1-feat: a feature
 ##
 { 'struct': 'Variant1',
+  'features': [ 'variant1-feat' ],
   'data': { 'var1': { 'type': 'str', 'if': 'defined(IFSTR)' } } }
 
 ##
@@ -104,6 +108,10 @@
 #
 # @arg2: the second
 # argument
+#
+# Features:
+# @cmd-feat1: a feature
+# @cmd-feat2: another feature
 # Note: @arg3 is undocumented
 # Returns: @Object
 # TODO: frobnicate
@@ -123,11 +131,15 @@
 ##
 { 'command': 'cmd',
   'data': { 'arg1': 'int', '*arg2': 'str', 'arg3': 'bool' },
-  'returns': 'Object' }
+  'returns': 'Object',
+  'features': [ 'cmd-feat1', 'cmd-feat2' ] }
 
 ##
 # @cmd-boxed:
 # If you're bored enough to read this, go see a video of boxed cats
+# Features:
+# @cmd-feat1: a feature
+# @cmd-feat2: another feature
 # Example:
 #
 # -> in
@@ -135,4 +147,5 @@
 # <- out
 ##
 { 'command': 'cmd-boxed', 'boxed': true,
-  'data': 'Object' }
+  'data': 'Object',
+  'features': [ 'cmd-feat1', 'cmd-feat2' ] }
diff --git a/tests/qapi-schema/doc-good.out b/tests/qapi-schema/doc-good.out
index d3bca343eb..f78fdef6a9 100644
--- a/tests/qapi-schema/doc-good.out
+++ b/tests/qapi-schema/doc-good.out
@@ -20,6 +20,7 @@ object Base
 object Variant1
     member var1: str optional=False
         if ['defined(IFSTR)']
+    feature variant1-feat
 object Variant2
 object Object
     base Base
@@ -46,9 +47,13 @@ object q_obj_cmd-arg
     member arg2: str optional=True
     member arg3: bool optional=False
 command cmd q_obj_cmd-arg -> Object
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
+    feature cmd-feat1
+    feature cmd-feat2
 command cmd-boxed Object -> None
-   gen=True success_response=True boxed=True oob=False preconfig=False
+    gen=True success_response=True boxed=True oob=False preconfig=False
+    feature cmd-feat1
+    feature cmd-feat2
 doc freeform
     body=
 = Section
diff --git a/tests/qapi-schema/doc-good.texi b/tests/qapi-schema/doc-good.texi
index 2526abc6d9..2ce8b883c9 100644
--- a/tests/qapi-schema/doc-good.texi
+++ b/tests/qapi-schema/doc-good.texi
@@ -122,6 +122,12 @@ Not documented
 @*@b{If:} @code{defined(IFSTR)}
 @end table
 
+@b{Features:}
+@table @asis
+@item @code{variant1-feat}
+a feature
+@end table
+
 @end deftp
 
 
@@ -182,6 +188,14 @@ argument
 Not documented
 @end table
 
+@b{Features:}
+@table @asis
+@item @code{cmd-feat1}
+a feature
+@item @code{cmd-feat2}
+another feature
+@end table
+
 @b{Note:}
 @code{arg3} is undocumented
 
@@ -227,6 +241,14 @@ If you're bored enough to read this, go see a video of boxed cats
 
 @b{Arguments:} the members of @code{Object}
 
+@b{Features:}
+@table @asis
+@item @code{cmd-feat1}
+a feature
+@item @code{cmd-feat2}
+another feature
+@end table
+
 @b{Example:}
 @example
 -> in
diff --git a/tests/qapi-schema/doc-interleaved-section.err b/tests/qapi-schema/doc-interleaved-section.err
index d373eabc55..715d58cd31 100644
--- a/tests/qapi-schema/doc-interleaved-section.err
+++ b/tests/qapi-schema/doc-interleaved-section.err
@@ -1 +1 @@
-tests/qapi-schema/doc-interleaved-section.json:15:1: '@foobar:' can't follow 'Note' section
+doc-interleaved-section.json:15:1: '@foobar:' can't follow 'Note' section
diff --git a/tests/qapi-schema/doc-interleaved-section.exit b/tests/qapi-schema/doc-interleaved-section.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-interleaved-section.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-invalid-end.err b/tests/qapi-schema/doc-invalid-end.err
index 2bda28cb54..919e4d317e 100644
--- a/tests/qapi-schema/doc-invalid-end.err
+++ b/tests/qapi-schema/doc-invalid-end.err
@@ -1 +1 @@
-tests/qapi-schema/doc-invalid-end.json:5:2: Documentation comment must end with '##'
+doc-invalid-end.json:5:2: documentation comment must end with '##'
diff --git a/tests/qapi-schema/doc-invalid-end.exit b/tests/qapi-schema/doc-invalid-end.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-invalid-end.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-invalid-end2.err b/tests/qapi-schema/doc-invalid-end2.err
index 6fad9c789e..d88a15cc8a 100644
--- a/tests/qapi-schema/doc-invalid-end2.err
+++ b/tests/qapi-schema/doc-invalid-end2.err
@@ -1 +1 @@
-tests/qapi-schema/doc-invalid-end2.json:5:1: Junk after '##' at end of documentation comment
+doc-invalid-end2.json:5:1: junk after '##' at end of documentation comment
diff --git a/tests/qapi-schema/doc-invalid-end2.exit b/tests/qapi-schema/doc-invalid-end2.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-invalid-end2.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-invalid-return.err b/tests/qapi-schema/doc-invalid-return.err
index 5aaba33bb4..2ad89c5941 100644
--- a/tests/qapi-schema/doc-invalid-return.err
+++ b/tests/qapi-schema/doc-invalid-return.err
@@ -1 +1 @@
-tests/qapi-schema/doc-invalid-return.json:3: 'Returns:' is only valid for commands
+doc-invalid-return.json:3: 'Returns:' is only valid for commands
diff --git a/tests/qapi-schema/doc-invalid-return.exit b/tests/qapi-schema/doc-invalid-return.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-invalid-return.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-invalid-section.err b/tests/qapi-schema/doc-invalid-section.err
index bda93b44fd..d2d40e5704 100644
--- a/tests/qapi-schema/doc-invalid-section.err
+++ b/tests/qapi-schema/doc-invalid-section.err
@@ -1 +1 @@
-tests/qapi-schema/doc-invalid-section.json:5:1: '@note:' not allowed in free-form documentation
+doc-invalid-section.json:5:1: '@note:' not allowed in free-form documentation
diff --git a/tests/qapi-schema/doc-invalid-section.exit b/tests/qapi-schema/doc-invalid-section.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-invalid-section.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-invalid-start.err b/tests/qapi-schema/doc-invalid-start.err
index 149af2bfac..276c033600 100644
--- a/tests/qapi-schema/doc-invalid-start.err
+++ b/tests/qapi-schema/doc-invalid-start.err
@@ -1 +1 @@
-tests/qapi-schema/doc-invalid-start.json:3:1: Junk after '##' at start of documentation comment
+doc-invalid-start.json:3:1: junk after '##' at start of documentation comment
diff --git a/tests/qapi-schema/doc-invalid-start.exit b/tests/qapi-schema/doc-invalid-start.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-invalid-start.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-missing-colon.err b/tests/qapi-schema/doc-missing-colon.err
index 817398b8e4..cbcea00715 100644
--- a/tests/qapi-schema/doc-missing-colon.err
+++ b/tests/qapi-schema/doc-missing-colon.err
@@ -1 +1 @@
-tests/qapi-schema/doc-missing-colon.json:4:1: Line should end with :
+doc-missing-colon.json:4:1: line should end with ':'
diff --git a/tests/qapi-schema/doc-missing-colon.exit b/tests/qapi-schema/doc-missing-colon.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-missing-colon.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-missing-expr.err b/tests/qapi-schema/doc-missing-expr.err
index c909e26eca..c9b32a96fa 100644
--- a/tests/qapi-schema/doc-missing-expr.err
+++ b/tests/qapi-schema/doc-missing-expr.err
@@ -1 +1 @@
-tests/qapi-schema/doc-missing-expr.json:3: Documentation for 'bar' is not followed by the definition
+doc-missing-expr.json:3: documentation for 'bar' is not followed by the definition
diff --git a/tests/qapi-schema/doc-missing-expr.exit b/tests/qapi-schema/doc-missing-expr.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-missing-expr.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-missing-space.err b/tests/qapi-schema/doc-missing-space.err
index d6b46ffd77..350031d1d6 100644
--- a/tests/qapi-schema/doc-missing-space.err
+++ b/tests/qapi-schema/doc-missing-space.err
@@ -1 +1 @@
-tests/qapi-schema/doc-missing-space.json:5:1: Missing space after #
+doc-missing-space.json:5:1: missing space after #
diff --git a/tests/qapi-schema/doc-missing-space.exit b/tests/qapi-schema/doc-missing-space.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-missing-space.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-missing.err b/tests/qapi-schema/doc-missing.err
index 7f2f326b30..b89d925bcc 100644
--- a/tests/qapi-schema/doc-missing.err
+++ b/tests/qapi-schema/doc-missing.err
@@ -1 +1,2 @@
-tests/qapi-schema/doc-missing.json:5: Expression missing documentation comment
+doc-missing.json: In command 'undocumented':
+doc-missing.json:5: documentation comment required
diff --git a/tests/qapi-schema/doc-missing.exit b/tests/qapi-schema/doc-missing.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-missing.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/doc-no-symbol.err b/tests/qapi-schema/doc-no-symbol.err
index 75f032a942..1b4fa14a22 100644
--- a/tests/qapi-schema/doc-no-symbol.err
+++ b/tests/qapi-schema/doc-no-symbol.err
@@ -1 +1 @@
-tests/qapi-schema/doc-no-symbol.json:3: Expression documentation required
+doc-no-symbol.json:3: definition documentation required
diff --git a/tests/qapi-schema/doc-no-symbol.exit b/tests/qapi-schema/doc-no-symbol.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/doc-no-symbol.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/double-data.err b/tests/qapi-schema/double-data.err
deleted file mode 100644
index cc765c4ff2..0000000000
--- a/tests/qapi-schema/double-data.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/double-data.json:2:41: Duplicate key "data"
diff --git a/tests/qapi-schema/double-data.exit b/tests/qapi-schema/double-data.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/double-data.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/double-data.json b/tests/qapi-schema/double-data.json
deleted file mode 100644
index e76b519538..0000000000
--- a/tests/qapi-schema/double-data.json
+++ /dev/null
@@ -1,2 +0,0 @@
-# we reject an expression with duplicate top-level keys
-{ 'struct': 'bar', 'data': { }, 'data': { 'string': 'str'} }
diff --git a/tests/qapi-schema/double-type.err b/tests/qapi-schema/double-type.err
index 69457173a7..71fc4dbb52 100644
--- a/tests/qapi-schema/double-type.err
+++ b/tests/qapi-schema/double-type.err
@@ -1,2 +1,3 @@
-tests/qapi-schema/double-type.json:2: Unknown key 'command' in struct 'bar'
+double-type.json: In struct 'bar':
+double-type.json:2: struct has unknown key 'command'
 Valid keys are 'base', 'data', 'features', 'if', 'struct'.
diff --git a/tests/qapi-schema/double-type.exit b/tests/qapi-schema/double-type.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/double-type.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/duplicate-key.err b/tests/qapi-schema/duplicate-key.err
index 6d02f83538..7ea8e95e8c 100644
--- a/tests/qapi-schema/duplicate-key.err
+++ b/tests/qapi-schema/duplicate-key.err
@@ -1 +1 @@
-tests/qapi-schema/duplicate-key.json:3:10: Duplicate key "key"
+duplicate-key.json:3:10: duplicate key 'key'
diff --git a/tests/qapi-schema/duplicate-key.exit b/tests/qapi-schema/duplicate-key.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/duplicate-key.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/duplicate-key.json b/tests/qapi-schema/duplicate-key.json
index 14ac0e8a40..06b55840c9 100644
--- a/tests/qapi-schema/duplicate-key.json
+++ b/tests/qapi-schema/duplicate-key.json
@@ -1,3 +1,3 @@
-# QAPI cannot include the same key more than once in any {}
+# Cannot include the same key more than once in any {}
 { 'key': 'value',
   'key': 'value' }
diff --git a/tests/qapi-schema/empty.exit b/tests/qapi-schema/empty.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/enum-bad-member.err b/tests/qapi-schema/enum-bad-member.err
index 211db9e6fc..f75d8c56ff 100644
--- a/tests/qapi-schema/enum-bad-member.err
+++ b/tests/qapi-schema/enum-bad-member.err
@@ -1 +1,2 @@
-tests/qapi-schema/enum-bad-member.json:2: Member of enum 'MyEnum' requires a string name
+enum-bad-member.json: In enum 'MyEnum':
+enum-bad-member.json:2: 'data' member requires a string name
diff --git a/tests/qapi-schema/enum-bad-member.exit b/tests/qapi-schema/enum-bad-member.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-bad-member.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/enum-bad-name.err b/tests/qapi-schema/enum-bad-name.err
index 9c3c1002b7..d26044b8e3 100644
--- a/tests/qapi-schema/enum-bad-name.err
+++ b/tests/qapi-schema/enum-bad-name.err
@@ -1 +1,2 @@
-tests/qapi-schema/enum-bad-name.json:2: Member of enum 'MyEnum' uses invalid name 'not^possible'
+enum-bad-name.json: In enum 'MyEnum':
+enum-bad-name.json:3: 'data' member 'not\possible' has an invalid name
diff --git a/tests/qapi-schema/enum-bad-name.exit b/tests/qapi-schema/enum-bad-name.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-bad-name.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/enum-bad-name.json b/tests/qapi-schema/enum-bad-name.json
index 8506562b31..1c4620edda 100644
--- a/tests/qapi-schema/enum-bad-name.json
+++ b/tests/qapi-schema/enum-bad-name.json
@@ -1,2 +1,3 @@
 # we ensure all enum names can map to C
-{ 'enum': 'MyEnum', 'data': [ 'not^possible' ] }
+# FIXME reports 'not\possible' instead of 'not\\possible'
+{ 'enum': 'MyEnum', 'data': [ 'not\\possible' ] }
diff --git a/tests/qapi-schema/enum-bad-prefix.err b/tests/qapi-schema/enum-bad-prefix.err
index 399f5f7af5..7a2b35787e 100644
--- a/tests/qapi-schema/enum-bad-prefix.err
+++ b/tests/qapi-schema/enum-bad-prefix.err
@@ -1 +1,2 @@
-tests/qapi-schema/enum-bad-prefix.json:2: Enum 'MyEnum' requires a string for 'prefix'
+enum-bad-prefix.json: In enum 'MyEnum':
+enum-bad-prefix.json:2: 'prefix' must be a string
diff --git a/tests/qapi-schema/enum-bad-prefix.exit b/tests/qapi-schema/enum-bad-prefix.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-bad-prefix.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/enum-clash-member.err b/tests/qapi-schema/enum-clash-member.err
index 5403c78507..5986571427 100644
--- a/tests/qapi-schema/enum-clash-member.err
+++ b/tests/qapi-schema/enum-clash-member.err
@@ -1 +1,2 @@
-tests/qapi-schema/enum-clash-member.json:2: 'one_two' (member of MyEnum) collides with 'one-two' (member of MyEnum)
+enum-clash-member.json: In enum 'MyEnum':
+enum-clash-member.json:2: value 'one_two' collides with value 'one-two'
diff --git a/tests/qapi-schema/enum-clash-member.exit b/tests/qapi-schema/enum-clash-member.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-clash-member.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/enum-dict-member-unknown.err b/tests/qapi-schema/enum-dict-member-unknown.err
index 2aae618be0..f8617ea179 100644
--- a/tests/qapi-schema/enum-dict-member-unknown.err
+++ b/tests/qapi-schema/enum-dict-member-unknown.err
@@ -1,2 +1,3 @@
-tests/qapi-schema/enum-dict-member-unknown.json:2: Unknown key 'bad-key' in dictionary member of enum 'MyEnum'
+enum-dict-member-unknown.json: In enum 'MyEnum':
+enum-dict-member-unknown.json:2: 'data' member has unknown key 'bad-key'
 Valid keys are 'if', 'name'.
diff --git a/tests/qapi-schema/enum-dict-member-unknown.exit b/tests/qapi-schema/enum-dict-member-unknown.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-dict-member-unknown.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/enum-if-invalid.err b/tests/qapi-schema/enum-if-invalid.err
index 54c3cf887b..0556dc967b 100644
--- a/tests/qapi-schema/enum-if-invalid.err
+++ b/tests/qapi-schema/enum-if-invalid.err
@@ -1 +1,2 @@
-tests/qapi-schema/enum-if-invalid.json:2: 'if' condition must be a string or a list of strings
+enum-if-invalid.json: In enum 'TestIfEnum':
+enum-if-invalid.json:2: 'if' condition of 'data' member 'bar' must be a string or a list of strings
diff --git a/tests/qapi-schema/enum-if-invalid.exit b/tests/qapi-schema/enum-if-invalid.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-if-invalid.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/enum-int-member.err b/tests/qapi-schema/enum-int-member.err
index 071c5213d8..3a15294963 100644
--- a/tests/qapi-schema/enum-int-member.err
+++ b/tests/qapi-schema/enum-int-member.err
@@ -1 +1 @@
-tests/qapi-schema/enum-int-member.json:3:31: Stray "1"
+enum-int-member.json:3:31: stray '1'
diff --git a/tests/qapi-schema/enum-int-member.exit b/tests/qapi-schema/enum-int-member.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-int-member.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/enum-member-case.err b/tests/qapi-schema/enum-member-case.err
index 3c67a3a067..8b3aefe37a 100644
--- a/tests/qapi-schema/enum-member-case.err
+++ b/tests/qapi-schema/enum-member-case.err
@@ -1 +1,2 @@
-tests/qapi-schema/enum-member-case.json:4: 'Value' (member of NoWayThisWillGetWhitelisted) should not use uppercase
+enum-member-case.json: In enum 'NoWayThisWillGetWhitelisted':
+enum-member-case.json:4: 'data' member 'Value' uses uppercase in name
diff --git a/tests/qapi-schema/enum-member-case.exit b/tests/qapi-schema/enum-member-case.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-member-case.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/enum-missing-data.err b/tests/qapi-schema/enum-missing-data.err
index ba4873ae69..ec4bdae037 100644
--- a/tests/qapi-schema/enum-missing-data.err
+++ b/tests/qapi-schema/enum-missing-data.err
@@ -1 +1,2 @@
-tests/qapi-schema/enum-missing-data.json:2: Key 'data' is missing from enum 'MyEnum'
+enum-missing-data.json: In enum 'MyEnum':
+enum-missing-data.json:2: enum misses key 'data'
diff --git a/tests/qapi-schema/enum-missing-data.exit b/tests/qapi-schema/enum-missing-data.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-missing-data.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/enum-wrong-data.err b/tests/qapi-schema/enum-wrong-data.err
index 11b43471cf..a9f34481ba 100644
--- a/tests/qapi-schema/enum-wrong-data.err
+++ b/tests/qapi-schema/enum-wrong-data.err
@@ -1 +1,2 @@
-tests/qapi-schema/enum-wrong-data.json:2: Enum 'MyEnum' requires an array for 'data'
+enum-wrong-data.json: In enum 'MyEnum':
+enum-wrong-data.json:2: 'data' must be an array
diff --git a/tests/qapi-schema/enum-wrong-data.exit b/tests/qapi-schema/enum-wrong-data.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/enum-wrong-data.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/escape-outside-string.err b/tests/qapi-schema/escape-outside-string.err
index b9b8837fd2..c49fe0c285 100644
--- a/tests/qapi-schema/escape-outside-string.err
+++ b/tests/qapi-schema/escape-outside-string.err
@@ -1 +1 @@
-tests/qapi-schema/escape-outside-string.json:3:27: Stray "\"
+escape-outside-string.json:3:27: stray '\'
diff --git a/tests/qapi-schema/escape-outside-string.exit b/tests/qapi-schema/escape-outside-string.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/escape-outside-string.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/escape-outside-string.json b/tests/qapi-schema/escape-outside-string.json
deleted file mode 100644
index 482f79554b..0000000000
--- a/tests/qapi-schema/escape-outside-string.json
+++ /dev/null
@@ -1,3 +0,0 @@
-# escape sequences are permitted only inside strings
-# { 'command': 'foo', 'data': {} }
-{ 'command': 'foo', 'data'\u003a{} }
diff --git a/tests/qapi-schema/escape-too-big.err b/tests/qapi-schema/escape-too-big.err
deleted file mode 100644
index d9aeb5dc38..0000000000
--- a/tests/qapi-schema/escape-too-big.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/escape-too-big.json:3:14: For now, \u escape only supports non-zero values up to \u007f
diff --git a/tests/qapi-schema/escape-too-big.exit b/tests/qapi-schema/escape-too-big.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/escape-too-big.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/escape-too-big.json b/tests/qapi-schema/escape-too-big.json
deleted file mode 100644
index 62bcecd557..0000000000
--- a/tests/qapi-schema/escape-too-big.json
+++ /dev/null
@@ -1,3 +0,0 @@
-# we don't support full Unicode strings, yet
-# { 'command': 'é' }
-{ 'command': '\u00e9' }
diff --git a/tests/qapi-schema/escape-too-short.err b/tests/qapi-schema/escape-too-short.err
deleted file mode 100644
index 934de598ee..0000000000
--- a/tests/qapi-schema/escape-too-short.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/escape-too-short.json:3:14: \u escape needs 4 hex digits
diff --git a/tests/qapi-schema/escape-too-short.exit b/tests/qapi-schema/escape-too-short.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/escape-too-short.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/escape-too-short.json b/tests/qapi-schema/escape-too-short.json
deleted file mode 100644
index 6cb1dec8f7..0000000000
--- a/tests/qapi-schema/escape-too-short.json
+++ /dev/null
@@ -1,3 +0,0 @@
-# the \u escape requires 4 hex digits
-# { 'command': 'a' }
-{ 'command': '\u61' }
diff --git a/tests/qapi-schema/event-boxed-empty.err b/tests/qapi-schema/event-boxed-empty.err
index 68ec6f2d2b..b3872cdab5 100644
--- a/tests/qapi-schema/event-boxed-empty.err
+++ b/tests/qapi-schema/event-boxed-empty.err
@@ -1 +1,2 @@
-tests/qapi-schema/event-boxed-empty.json:2: Use of 'boxed' requires 'data'
+event-boxed-empty.json: In event 'FOO':
+event-boxed-empty.json:2: 'boxed': true requires 'data'
diff --git a/tests/qapi-schema/event-boxed-empty.exit b/tests/qapi-schema/event-boxed-empty.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/event-boxed-empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/event-case.exit b/tests/qapi-schema/event-case.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/event-case.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/event-case.out b/tests/qapi-schema/event-case.out
index ec8a1406e4..42ae519656 100644
--- a/tests/qapi-schema/event-case.out
+++ b/tests/qapi-schema/event-case.out
@@ -11,4 +11,4 @@ enum QType
     member qbool
 module event-case.json
 event oops None
-   boxed=False
+    boxed=False
diff --git a/tests/qapi-schema/event-member-invalid-dict.err b/tests/qapi-schema/event-member-invalid-dict.err
index 1a57fa29b0..c7a6a24305 100644
--- a/tests/qapi-schema/event-member-invalid-dict.err
+++ b/tests/qapi-schema/event-member-invalid-dict.err
@@ -1 +1,2 @@
-tests/qapi-schema/event-member-invalid-dict.json:1: Key 'type' is missing from member 'a' of 'data' for event 'EVENT_A'
+event-member-invalid-dict.json: In event 'EVENT_A':
+event-member-invalid-dict.json:1: 'data' member 'a' misses key 'type'
diff --git a/tests/qapi-schema/event-member-invalid-dict.exit b/tests/qapi-schema/event-member-invalid-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/event-member-invalid-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/event-nest-struct.err b/tests/qapi-schema/event-nest-struct.err
index 5a42701b8f..8c5f6ed311 100644
--- a/tests/qapi-schema/event-nest-struct.err
+++ b/tests/qapi-schema/event-nest-struct.err
@@ -1 +1,2 @@
-tests/qapi-schema/event-nest-struct.json:1: Member 'a' of 'data' for event 'EVENT_A' should be a type name
+event-nest-struct.json: In event 'EVENT_A':
+event-nest-struct.json:1: 'data' member 'a' should be a type name
diff --git a/tests/qapi-schema/event-nest-struct.exit b/tests/qapi-schema/event-nest-struct.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/event-nest-struct.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/features-bad-type.err b/tests/qapi-schema/features-bad-type.err
index 5fb95c2f90..3c63591632 100644
--- a/tests/qapi-schema/features-bad-type.err
+++ b/tests/qapi-schema/features-bad-type.err
@@ -1 +1,2 @@
-tests/qapi-schema/features-bad-type.json:1: Feature of struct FeatureStruct0 requires a string name
+features-bad-type.json: In struct 'FeatureStruct0':
+features-bad-type.json:1: 'features' member requires a string name
diff --git a/tests/qapi-schema/features-bad-type.exit b/tests/qapi-schema/features-bad-type.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/features-bad-type.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/features-duplicate-name.err b/tests/qapi-schema/features-duplicate-name.err
index c0a4cccae6..0adbee6b0a 100644
--- a/tests/qapi-schema/features-duplicate-name.err
+++ b/tests/qapi-schema/features-duplicate-name.err
@@ -1 +1,2 @@
-tests/qapi-schema/features-duplicate-name.json:1: 'foo' (feature of FeatureStruct0) collides with 'foo' (feature of FeatureStruct0)
+features-duplicate-name.json: In struct 'FeatureStruct0':
+features-duplicate-name.json:1: feature 'foo' collides with feature 'foo'
diff --git a/tests/qapi-schema/features-duplicate-name.exit b/tests/qapi-schema/features-duplicate-name.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/features-duplicate-name.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/features-if-invalid.err b/tests/qapi-schema/features-if-invalid.err
new file mode 100644
index 0000000000..f63b89535e
--- /dev/null
+++ b/tests/qapi-schema/features-if-invalid.err
@@ -0,0 +1,2 @@
+features-if-invalid.json: In struct 'Stru':
+features-if-invalid.json:2: 'if' condition of 'features' member 'f' must be a string or a list of strings
diff --git a/tests/qapi-schema/features-if-invalid.json b/tests/qapi-schema/features-if-invalid.json
new file mode 100644
index 0000000000..89c2a6c234
--- /dev/null
+++ b/tests/qapi-schema/features-if-invalid.json
@@ -0,0 +1,4 @@
+# Cover feature with invalid 'if'
+{ 'struct': 'Stru',
+  'data': {},
+  'features': [{'name': 'f', 'if': false }] }
diff --git a/tests/qapi-schema/double-data.out b/tests/qapi-schema/features-if-invalid.out
index e69de29bb2..e69de29bb2 100644
--- a/tests/qapi-schema/double-data.out
+++ b/tests/qapi-schema/features-if-invalid.out
diff --git a/tests/qapi-schema/features-missing-name.err b/tests/qapi-schema/features-missing-name.err
index 4f1d2715aa..ce02412d2e 100644
--- a/tests/qapi-schema/features-missing-name.err
+++ b/tests/qapi-schema/features-missing-name.err
@@ -1 +1,2 @@
-tests/qapi-schema/features-missing-name.json:1: Key 'name' is missing from feature of struct FeatureStruct0
+features-missing-name.json: In struct 'FeatureStruct0':
+features-missing-name.json:1: 'features' member misses key 'name'
diff --git a/tests/qapi-schema/features-missing-name.exit b/tests/qapi-schema/features-missing-name.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/features-missing-name.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/features-name-bad-type.err b/tests/qapi-schema/features-name-bad-type.err
index 8a3eecb972..4afcd5fdc3 100644
--- a/tests/qapi-schema/features-name-bad-type.err
+++ b/tests/qapi-schema/features-name-bad-type.err
@@ -1 +1,2 @@
-tests/qapi-schema/features-name-bad-type.json:1: Feature of struct FeatureStruct0 requires a string name
+features-name-bad-type.json: In struct 'FeatureStruct0':
+features-name-bad-type.json:1: 'features' member requires a string name
diff --git a/tests/qapi-schema/features-name-bad-type.exit b/tests/qapi-schema/features-name-bad-type.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/features-name-bad-type.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/features-no-list.err b/tests/qapi-schema/features-no-list.err
index 61ed68612b..5cfaa3f216 100644
--- a/tests/qapi-schema/features-no-list.err
+++ b/tests/qapi-schema/features-no-list.err
@@ -1 +1,2 @@
-tests/qapi-schema/features-no-list.json:1: Struct 'FeatureStruct0' requires an array for 'features'
+features-no-list.json: In struct 'FeatureStruct0':
+features-no-list.json:1: 'features' must be an array
diff --git a/tests/qapi-schema/features-no-list.exit b/tests/qapi-schema/features-no-list.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/features-no-list.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/features-unknown-key.err b/tests/qapi-schema/features-unknown-key.err
index a1d693030d..13e359a216 100644
--- a/tests/qapi-schema/features-unknown-key.err
+++ b/tests/qapi-schema/features-unknown-key.err
@@ -1,2 +1,3 @@
-tests/qapi-schema/features-unknown-key.json:1: Unknown key 'colour' in feature of struct FeatureStruct0
+features-unknown-key.json: In struct 'FeatureStruct0':
+features-unknown-key.json:1: 'features' member has unknown key 'colour'
 Valid keys are 'if', 'name'.
diff --git a/tests/qapi-schema/features-unknown-key.exit b/tests/qapi-schema/features-unknown-key.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/features-unknown-key.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-array-branch.err b/tests/qapi-schema/flat-union-array-branch.err
index 8ea91eadb2..20a8ef1406 100644
--- a/tests/qapi-schema/flat-union-array-branch.err
+++ b/tests/qapi-schema/flat-union-array-branch.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-array-branch.json:8: Member 'value1' of union 'TestUnion' cannot be an array
+flat-union-array-branch.json: In union 'TestUnion':
+flat-union-array-branch.json:8: 'data' member 'value1' cannot be an array
diff --git a/tests/qapi-schema/flat-union-array-branch.exit b/tests/qapi-schema/flat-union-array-branch.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-array-branch.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-bad-base.err b/tests/qapi-schema/flat-union-bad-base.err
index bee24a217a..e0a205a58c 100644
--- a/tests/qapi-schema/flat-union-bad-base.err
+++ b/tests/qapi-schema/flat-union-bad-base.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-bad-base.json:8: 'string' (member of TestTypeA) collides with 'string' (base of TestUnion)
+flat-union-bad-base.json: In union 'TestUnion':
+flat-union-bad-base.json:8: member 'string' of type 'TestTypeA' collides with base member 'string'
diff --git a/tests/qapi-schema/flat-union-bad-base.exit b/tests/qapi-schema/flat-union-bad-base.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-bad-base.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-bad-discriminator.err b/tests/qapi-schema/flat-union-bad-discriminator.err
index c38cc8e4df..b705439bd9 100644
--- a/tests/qapi-schema/flat-union-bad-discriminator.err
+++ b/tests/qapi-schema/flat-union-bad-discriminator.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-bad-discriminator.json:11: Discriminator of flat union 'TestUnion' requires a string name
+flat-union-bad-discriminator.json: In union 'TestUnion':
+flat-union-bad-discriminator.json:11: 'discriminator' requires a string name
diff --git a/tests/qapi-schema/flat-union-bad-discriminator.exit b/tests/qapi-schema/flat-union-bad-discriminator.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-bad-discriminator.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-base-any.err b/tests/qapi-schema/flat-union-base-any.err
index 646f1c9cd1..c2d4de6a5d 100644
--- a/tests/qapi-schema/flat-union-base-any.err
+++ b/tests/qapi-schema/flat-union-base-any.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-base-any.json:8: 'base' for union 'TestUnion' cannot use built-in type 'any'
+flat-union-base-any.json: In union 'TestUnion':
+flat-union-base-any.json:8: 'base' requires a struct type, built-in type 'any' isn't
diff --git a/tests/qapi-schema/flat-union-base-any.exit b/tests/qapi-schema/flat-union-base-any.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-base-any.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-base-union.err b/tests/qapi-schema/flat-union-base-union.err
index f138395e45..3b0087220e 100644
--- a/tests/qapi-schema/flat-union-base-union.err
+++ b/tests/qapi-schema/flat-union-base-union.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-base-union.json:14: 'base' for union 'TestUnion' cannot use union type 'UnionBase'
+flat-union-base-union.json: In union 'TestUnion':
+flat-union-base-union.json:14: 'base' requires a struct type, union type 'UnionBase' isn't
diff --git a/tests/qapi-schema/flat-union-base-union.exit b/tests/qapi-schema/flat-union-base-union.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-base-union.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-clash-member.err b/tests/qapi-schema/flat-union-clash-member.err
index 2adf69755a..07551e6ef5 100644
--- a/tests/qapi-schema/flat-union-clash-member.err
+++ b/tests/qapi-schema/flat-union-clash-member.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-clash-member.json:11: 'name' (member of Branch1) collides with 'name' (member of Base)
+flat-union-clash-member.json: In union 'TestUnion':
+flat-union-clash-member.json:11: member 'name' of type 'Branch1' collides with member 'name' of type 'Base'
diff --git a/tests/qapi-schema/flat-union-clash-member.exit b/tests/qapi-schema/flat-union-clash-member.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-clash-member.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-discriminator-bad-name.err b/tests/qapi-schema/flat-union-discriminator-bad-name.err
new file mode 100644
index 0000000000..28be49c31a
--- /dev/null
+++ b/tests/qapi-schema/flat-union-discriminator-bad-name.err
@@ -0,0 +1,2 @@
+flat-union-discriminator-bad-name.json: In union 'MyUnion':
+flat-union-discriminator-bad-name.json:6: discriminator '*switch' is not a member of 'base'
diff --git a/tests/qapi-schema/flat-union-discriminator-bad-name.json b/tests/qapi-schema/flat-union-discriminator-bad-name.json
new file mode 100644
index 0000000000..3ae8c06a89
--- /dev/null
+++ b/tests/qapi-schema/flat-union-discriminator-bad-name.json
@@ -0,0 +1,10 @@
+# discriminator '*switch' isn't a member of base, 'switch' is
+{ 'enum': 'Enum', 'data': [ 'one', 'two' ] }
+{ 'struct': 'Base',
+  'data': { '*switch': 'Enum' } }
+{ 'struct': 'Branch', 'data': { 'name': 'str' } }
+{ 'union': 'MyUnion',
+  'base': 'Base',
+  'discriminator': '*switch',
+  'data': { 'one': 'Branch',
+            'two': 'Branch' } }
diff --git a/tests/qapi-schema/escape-outside-string.out b/tests/qapi-schema/flat-union-discriminator-bad-name.out
index e69de29bb2..e69de29bb2 100644
--- a/tests/qapi-schema/escape-outside-string.out
+++ b/tests/qapi-schema/flat-union-discriminator-bad-name.out
diff --git a/tests/qapi-schema/flat-union-empty.err b/tests/qapi-schema/flat-union-empty.err
index 15754f54eb..89b0f25cb0 100644
--- a/tests/qapi-schema/flat-union-empty.err
+++ b/tests/qapi-schema/flat-union-empty.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-empty.json:4: Union 'Union' cannot have empty 'data'
+flat-union-empty.json: In union 'Union':
+flat-union-empty.json:4: union has no branches
diff --git a/tests/qapi-schema/flat-union-empty.exit b/tests/qapi-schema/flat-union-empty.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-empty.json b/tests/qapi-schema/flat-union-empty.json
index 77f1d9abfb..83e1cc7b96 100644
--- a/tests/qapi-schema/flat-union-empty.json
+++ b/tests/qapi-schema/flat-union-empty.json
@@ -1,4 +1,4 @@
-# flat unions cannot be empty
+# flat union discriminator cannot be empty
 { 'enum': 'Empty', 'data': [ ] }
 { 'struct': 'Base', 'data': { 'type': 'Empty' } }
 { 'union': 'Union', 'base': 'Base', 'discriminator': 'type', 'data': { } }
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.err b/tests/qapi-schema/flat-union-inline-invalid-dict.err
index 9c4c45b7f0..53e5416707 100644
--- a/tests/qapi-schema/flat-union-inline-invalid-dict.err
+++ b/tests/qapi-schema/flat-union-inline-invalid-dict.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-inline-invalid-dict.json:7: Key 'type' is missing from member 'value1' of union 'TestUnion'
+flat-union-inline-invalid-dict.json: In union 'TestUnion':
+flat-union-inline-invalid-dict.json:7: 'data' member 'value1' misses key 'type'
diff --git a/tests/qapi-schema/flat-union-inline-invalid-dict.exit b/tests/qapi-schema/flat-union-inline-invalid-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-inline-invalid-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-inline.err b/tests/qapi-schema/flat-union-inline.err
index 2333358d28..538283f5db 100644
--- a/tests/qapi-schema/flat-union-inline.err
+++ b/tests/qapi-schema/flat-union-inline.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-inline.json:7: Member 'value1' of union 'TestUnion' should be a type name
+flat-union-inline.json: In union 'TestUnion':
+flat-union-inline.json:7: 'data' member 'value1' should be a type name
diff --git a/tests/qapi-schema/flat-union-inline.exit b/tests/qapi-schema/flat-union-inline.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-inline.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-int-branch.err b/tests/qapi-schema/flat-union-int-branch.err
index faf01573b7..ae7f800603 100644
--- a/tests/qapi-schema/flat-union-int-branch.err
+++ b/tests/qapi-schema/flat-union-int-branch.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-int-branch.json:8: Member 'value1' of union 'TestUnion' cannot use built-in type 'int'
+flat-union-int-branch.json: In union 'TestUnion':
+flat-union-int-branch.json:8: branch 'value1' cannot use built-in type 'int'
diff --git a/tests/qapi-schema/flat-union-int-branch.exit b/tests/qapi-schema/flat-union-int-branch.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-int-branch.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-invalid-branch-key.err b/tests/qapi-schema/flat-union-invalid-branch-key.err
index ccf72d2dfe..5576a25f9b 100644
--- a/tests/qapi-schema/flat-union-invalid-branch-key.err
+++ b/tests/qapi-schema/flat-union-invalid-branch-key.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-invalid-branch-key.json:13: Discriminator value 'value_wrong' is not found in enum 'TestEnum'
+flat-union-invalid-branch-key.json: In union 'TestUnion':
+flat-union-invalid-branch-key.json:13: branch 'value_wrong' is not a value of enum type 'TestEnum'
diff --git a/tests/qapi-schema/flat-union-invalid-branch-key.exit b/tests/qapi-schema/flat-union-invalid-branch-key.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-invalid-branch-key.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.err b/tests/qapi-schema/flat-union-invalid-discriminator.err
index 5f4055614e..99bca2ddab 100644
--- a/tests/qapi-schema/flat-union-invalid-discriminator.err
+++ b/tests/qapi-schema/flat-union-invalid-discriminator.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-invalid-discriminator.json:13: Discriminator 'enum_wrong' is not a member of base struct 'TestBase'
+flat-union-invalid-discriminator.json: In union 'TestUnion':
+flat-union-invalid-discriminator.json:10: discriminator 'enum_wrong' is not a member of 'base'
diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.exit b/tests/qapi-schema/flat-union-invalid-discriminator.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-invalid-discriminator.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.json b/tests/qapi-schema/flat-union-invalid-discriminator.json
index 48b94c3a4d..c4fce97362 100644
--- a/tests/qapi-schema/flat-union-invalid-discriminator.json
+++ b/tests/qapi-schema/flat-union-invalid-discriminator.json
@@ -1,9 +1,6 @@
 { 'enum': 'TestEnum',
   'data': [ 'value1', 'value2' ] }
 
-{ 'struct': 'TestBase',
-  'data': { 'enum1': 'TestEnum' } }
-
 { 'struct': 'TestTypeA',
   'data': { 'string': 'str' } }
 
@@ -11,7 +8,7 @@
   'data': { 'integer': 'int' } }
 
 { 'union': 'TestUnion',
-  'base': 'TestBase',
+  'base': { 'enum1': 'TestEnum' },
   'discriminator': 'enum_wrong',
   'data': { 'value1': 'TestTypeA',
             'value2': 'TestTypeB' } }
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.err b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
index 0c94c9860d..350f28da9d 100644
--- a/tests/qapi-schema/flat-union-invalid-if-discriminator.err
+++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-invalid-if-discriminator.json:13: The discriminator TestBase.enum1 for union TestUnion must not be conditional
+flat-union-invalid-if-discriminator.json: In union 'TestUnion':
+flat-union-invalid-if-discriminator.json:10: discriminator member 'enum1' of 'base' must not be conditional
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.exit b/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-invalid-if-discriminator.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-invalid-if-discriminator.json b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
index 618ec36396..e49992b798 100644
--- a/tests/qapi-schema/flat-union-invalid-if-discriminator.json
+++ b/tests/qapi-schema/flat-union-invalid-if-discriminator.json
@@ -1,9 +1,6 @@
 { 'enum': 'TestEnum',
   'data': [ 'value1', 'value2' ] }
 
-{ 'struct': 'TestBase',
-  'data': { 'enum1': { 'type': 'TestEnum', 'if': 'FOO' } } }
-
 { 'struct': 'TestTypeA',
   'data': { 'string': 'str' } }
 
@@ -11,7 +8,7 @@
   'data': { 'integer': 'int' } }
 
 { 'union': 'TestUnion',
-  'base': 'TestBase',
+  'base': { 'enum1': { 'type': 'TestEnum', 'if': 'FOO' } },
   'discriminator': 'enum1',
   'data': { 'value1': 'TestTypeA',
             'value2': 'TestTypeB' } }
diff --git a/tests/qapi-schema/flat-union-no-base.err b/tests/qapi-schema/flat-union-no-base.err
index 841c93b554..9bd595bcfb 100644
--- a/tests/qapi-schema/flat-union-no-base.err
+++ b/tests/qapi-schema/flat-union-no-base.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-no-base.json:9: Flat union 'TestUnion' must have a base
+flat-union-no-base.json: In union 'TestUnion':
+flat-union-no-base.json:9: 'discriminator' requires 'base'
diff --git a/tests/qapi-schema/flat-union-no-base.exit b/tests/qapi-schema/flat-union-no-base.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-no-base.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-optional-discriminator.err b/tests/qapi-schema/flat-union-optional-discriminator.err
index aaabedb3bd..3d60a1b496 100644
--- a/tests/qapi-schema/flat-union-optional-discriminator.err
+++ b/tests/qapi-schema/flat-union-optional-discriminator.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-optional-discriminator.json:6: Discriminator of flat union 'MyUnion' does not allow optional name '*switch'
+flat-union-optional-discriminator.json: In union 'MyUnion':
+flat-union-optional-discriminator.json:6: discriminator member 'switch' of base type 'Base' must not be optional
diff --git a/tests/qapi-schema/flat-union-optional-discriminator.exit b/tests/qapi-schema/flat-union-optional-discriminator.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-optional-discriminator.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/flat-union-optional-discriminator.json b/tests/qapi-schema/flat-union-optional-discriminator.json
index 08a8f7ef8b..2e7f766f60 100644
--- a/tests/qapi-schema/flat-union-optional-discriminator.json
+++ b/tests/qapi-schema/flat-union-optional-discriminator.json
@@ -5,6 +5,6 @@
 { 'struct': 'Branch', 'data': { 'name': 'str' } }
 { 'union': 'MyUnion',
   'base': 'Base',
-  'discriminator': '*switch',
+  'discriminator': 'switch',
   'data': { 'one': 'Branch',
             'two': 'Branch' } }
diff --git a/tests/qapi-schema/flat-union-string-discriminator.err b/tests/qapi-schema/flat-union-string-discriminator.err
index 200016bd5c..ff42c9728b 100644
--- a/tests/qapi-schema/flat-union-string-discriminator.err
+++ b/tests/qapi-schema/flat-union-string-discriminator.err
@@ -1 +1,2 @@
-tests/qapi-schema/flat-union-string-discriminator.json:13: Discriminator 'kind' must be of enumeration type
+flat-union-string-discriminator.json: In union 'TestUnion':
+flat-union-string-discriminator.json:13: discriminator member 'kind' of base type 'TestBase' must be of enum type
diff --git a/tests/qapi-schema/flat-union-string-discriminator.exit b/tests/qapi-schema/flat-union-string-discriminator.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/flat-union-string-discriminator.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/funny-char.err b/tests/qapi-schema/funny-char.err
index bfc890cd9f..1c8abae2e0 100644
--- a/tests/qapi-schema/funny-char.err
+++ b/tests/qapi-schema/funny-char.err
@@ -1 +1 @@
-tests/qapi-schema/funny-char.json:2:36: Stray ";"
+funny-char.json:2:36: stray ';'
diff --git a/tests/qapi-schema/funny-char.exit b/tests/qapi-schema/funny-char.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/funny-char.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/funny-word.err b/tests/qapi-schema/funny-word.err
new file mode 100644
index 0000000000..a1d9ade970
--- /dev/null
+++ b/tests/qapi-schema/funny-word.err
@@ -0,0 +1 @@
+funny-word.json:1:3: stray 'command'
diff --git a/tests/qapi-schema/funny-word.json b/tests/qapi-schema/funny-word.json
new file mode 100644
index 0000000000..1153b9f12f
--- /dev/null
+++ b/tests/qapi-schema/funny-word.json
@@ -0,0 +1 @@
+{ command: 'foo' }
diff --git a/tests/qapi-schema/escape-too-big.out b/tests/qapi-schema/funny-word.out
index e69de29bb2..e69de29bb2 100644
--- a/tests/qapi-schema/escape-too-big.out
+++ b/tests/qapi-schema/funny-word.out
diff --git a/tests/qapi-schema/ident-with-escape.err b/tests/qapi-schema/ident-with-escape.err
index e69de29bb2..3f6c1e423c 100644
--- a/tests/qapi-schema/ident-with-escape.err
+++ b/tests/qapi-schema/ident-with-escape.err
@@ -0,0 +1 @@
+ident-with-escape.json:3:3: unknown escape \u
diff --git a/tests/qapi-schema/ident-with-escape.exit b/tests/qapi-schema/ident-with-escape.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/ident-with-escape.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/ident-with-escape.json b/tests/qapi-schema/ident-with-escape.json
index 56617501e7..76b4503d95 100644
--- a/tests/qapi-schema/ident-with-escape.json
+++ b/tests/qapi-schema/ident-with-escape.json
@@ -1,4 +1,4 @@
-# we allow escape sequences in strings, if they map back to ASCII
+# we don't recognize any \ escapes other than \\ (tested elsewhere)
 # { 'command': 'fooA', 'data': { 'bar1': 'str' } }
 { 'c\u006fmmand': '\u0066\u006f\u006FA',
   'd\u0061ta': { '\u0062\u0061\u00721': '\u0073\u0074\u0072' } }
diff --git a/tests/qapi-schema/ident-with-escape.out b/tests/qapi-schema/ident-with-escape.out
index 39754eba8c..e69de29bb2 100644
--- a/tests/qapi-schema/ident-with-escape.out
+++ b/tests/qapi-schema/ident-with-escape.out
@@ -1,16 +0,0 @@
-module None
-object q_empty
-enum QType
-    prefix QTYPE
-    member none
-    member qnull
-    member qnum
-    member qstring
-    member qdict
-    member qlist
-    member qbool
-module ident-with-escape.json
-object q_obj_fooA-arg
-    member bar1: str optional=False
-command fooA q_obj_fooA-arg -> None
-   gen=True success_response=True boxed=False oob=False preconfig=False
diff --git a/tests/qapi-schema/include-before-err.err b/tests/qapi-schema/include-before-err.err
index 55652751e1..16da03026f 100644
--- a/tests/qapi-schema/include-before-err.err
+++ b/tests/qapi-schema/include-before-err.err
@@ -1 +1 @@
-tests/qapi-schema/include-before-err.json:2:13: Expected ":"
+include-before-err.json:2:13: expected ':'
diff --git a/tests/qapi-schema/include-before-err.exit b/tests/qapi-schema/include-before-err.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/include-before-err.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/include-cycle.err b/tests/qapi-schema/include-cycle.err
index bdcd07dce2..4c99f5642b 100644
--- a/tests/qapi-schema/include-cycle.err
+++ b/tests/qapi-schema/include-cycle.err
@@ -1,3 +1,3 @@
-In file included from tests/qapi-schema/include-cycle.json:1:
-In file included from tests/qapi-schema/include-cycle-b.json:1:
-tests/qapi-schema/include-cycle-c.json:1: Inclusion loop for include-cycle.json
+In file included from include-cycle.json:1:
+In file included from include-cycle-b.json:1:
+include-cycle-c.json:1: inclusion loop for include-cycle.json
diff --git a/tests/qapi-schema/include-cycle.exit b/tests/qapi-schema/include-cycle.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/include-cycle.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/include-extra-junk.err b/tests/qapi-schema/include-extra-junk.err
index e6ef2a3720..1f7d2e1437 100644
--- a/tests/qapi-schema/include-extra-junk.err
+++ b/tests/qapi-schema/include-extra-junk.err
@@ -1 +1 @@
-tests/qapi-schema/include-extra-junk.json:3: Invalid 'include' directive
+include-extra-junk.json:3: invalid 'include' directive
diff --git a/tests/qapi-schema/include-extra-junk.exit b/tests/qapi-schema/include-extra-junk.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/include-extra-junk.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/include-format-err.err b/tests/qapi-schema/include-format-err.err
deleted file mode 100644
index 721ff4eccc..0000000000
--- a/tests/qapi-schema/include-format-err.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/include-format-err.json:1: Invalid 'include' directive
diff --git a/tests/qapi-schema/include-format-err.exit b/tests/qapi-schema/include-format-err.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/include-format-err.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/include-format-err.json b/tests/qapi-schema/include-format-err.json
deleted file mode 100644
index 44980f026f..0000000000
--- a/tests/qapi-schema/include-format-err.json
+++ /dev/null
@@ -1,2 +0,0 @@
-{ 'include': 'include-simple-sub.json',
-  'foo': 'bar' }
diff --git a/tests/qapi-schema/include-nested-err.err b/tests/qapi-schema/include-nested-err.err
index 1b7b22706b..9eac9eaeea 100644
--- a/tests/qapi-schema/include-nested-err.err
+++ b/tests/qapi-schema/include-nested-err.err
@@ -1,2 +1,2 @@
-In file included from tests/qapi-schema/include-nested-err.json:1:
-tests/qapi-schema/missing-colon.json:1:10: Expected ":"
+In file included from include-nested-err.json:1:
+missing-colon.json:1:10: expected ':'
diff --git a/tests/qapi-schema/include-nested-err.exit b/tests/qapi-schema/include-nested-err.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/include-nested-err.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/include-no-file.err b/tests/qapi-schema/include-no-file.err
index e42bcf4bc1..3115a889fe 100644
--- a/tests/qapi-schema/include-no-file.err
+++ b/tests/qapi-schema/include-no-file.err
@@ -1 +1 @@
-tests/qapi-schema/include-no-file.json:1: No such file or directory: tests/qapi-schema/include-no-file-sub.json
+include-no-file.json:1: can't read include file 'include-no-file-sub.json': No such file or directory
diff --git a/tests/qapi-schema/include-no-file.exit b/tests/qapi-schema/include-no-file.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/include-no-file.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/include-non-file.err b/tests/qapi-schema/include-non-file.err
index faae1eacf1..ec8a331654 100644
--- a/tests/qapi-schema/include-non-file.err
+++ b/tests/qapi-schema/include-non-file.err
@@ -1 +1 @@
-tests/qapi-schema/include-non-file.json:1: Value of 'include' must be a string
+include-non-file.json:1: value of 'include' must be a string
diff --git a/tests/qapi-schema/include-non-file.exit b/tests/qapi-schema/include-non-file.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/include-non-file.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/include-repetition.exit b/tests/qapi-schema/include-repetition.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/include-repetition.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/include-self-cycle.err b/tests/qapi-schema/include-self-cycle.err
index 981742ae5f..284b0d6f0e 100644
--- a/tests/qapi-schema/include-self-cycle.err
+++ b/tests/qapi-schema/include-self-cycle.err
@@ -1 +1 @@
-tests/qapi-schema/include-self-cycle.json:1: Inclusion loop for include-self-cycle.json
+include-self-cycle.json:1: inclusion loop for include-self-cycle.json
diff --git a/tests/qapi-schema/include-self-cycle.exit b/tests/qapi-schema/include-self-cycle.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/include-self-cycle.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/include-simple.exit b/tests/qapi-schema/include-simple.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/include-simple.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/indented-expr.exit b/tests/qapi-schema/indented-expr.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/indented-expr.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/indented-expr.out b/tests/qapi-schema/indented-expr.out
index bffdf6756d..04356775cd 100644
--- a/tests/qapi-schema/indented-expr.out
+++ b/tests/qapi-schema/indented-expr.out
@@ -11,6 +11,6 @@ enum QType
     member qbool
 module indented-expr.json
 command eins None -> None
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
 command zwei None -> None
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
diff --git a/tests/qapi-schema/leading-comma-list.err b/tests/qapi-schema/leading-comma-list.err
index f5c870bb9c..76eed2b5b3 100644
--- a/tests/qapi-schema/leading-comma-list.err
+++ b/tests/qapi-schema/leading-comma-list.err
@@ -1 +1 @@
-tests/qapi-schema/leading-comma-list.json:2:13: Expected "{", "[", "]", string, boolean or "null"
+leading-comma-list.json:2:13: expected '{', '[', ']', string, boolean or 'null'
diff --git a/tests/qapi-schema/leading-comma-list.exit b/tests/qapi-schema/leading-comma-list.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/leading-comma-list.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/leading-comma-object.err b/tests/qapi-schema/leading-comma-object.err
index f767b95544..25f8b6ffd6 100644
--- a/tests/qapi-schema/leading-comma-object.err
+++ b/tests/qapi-schema/leading-comma-object.err
@@ -1 +1 @@
-tests/qapi-schema/leading-comma-object.json:1:3: Expected string or "}"
+leading-comma-object.json:1:3: expected string or '}'
diff --git a/tests/qapi-schema/leading-comma-object.exit b/tests/qapi-schema/leading-comma-object.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/leading-comma-object.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/missing-colon.err b/tests/qapi-schema/missing-colon.err
index d9d66b377a..d5fe235cb9 100644
--- a/tests/qapi-schema/missing-colon.err
+++ b/tests/qapi-schema/missing-colon.err
@@ -1 +1 @@
-tests/qapi-schema/missing-colon.json:1:10: Expected ":"
+missing-colon.json:1:10: expected ':'
diff --git a/tests/qapi-schema/missing-colon.exit b/tests/qapi-schema/missing-colon.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/missing-colon.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/missing-comma-list.err b/tests/qapi-schema/missing-comma-list.err
index e73d2770d6..d0a790c2b3 100644
--- a/tests/qapi-schema/missing-comma-list.err
+++ b/tests/qapi-schema/missing-comma-list.err
@@ -1 +1 @@
-tests/qapi-schema/missing-comma-list.json:2:20: Expected "," or "]"
+missing-comma-list.json:2:20: expected ',' or ']'
diff --git a/tests/qapi-schema/missing-comma-list.exit b/tests/qapi-schema/missing-comma-list.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/missing-comma-list.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/missing-comma-object.err b/tests/qapi-schema/missing-comma-object.err
index 52b3a8a1ec..aa8efbc2f3 100644
--- a/tests/qapi-schema/missing-comma-object.err
+++ b/tests/qapi-schema/missing-comma-object.err
@@ -1 +1 @@
-tests/qapi-schema/missing-comma-object.json:2:3: Expected "," or "}"
+missing-comma-object.json:2:3: expected ',' or '}'
diff --git a/tests/qapi-schema/missing-comma-object.exit b/tests/qapi-schema/missing-comma-object.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/missing-comma-object.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/missing-type.err b/tests/qapi-schema/missing-type.err
index b3e7b14e42..5755386a18 100644
--- a/tests/qapi-schema/missing-type.err
+++ b/tests/qapi-schema/missing-type.err
@@ -1 +1 @@
-tests/qapi-schema/missing-type.json:2: Expression is missing metatype
+missing-type.json:2: expression is missing metatype
diff --git a/tests/qapi-schema/missing-type.exit b/tests/qapi-schema/missing-type.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/missing-type.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.err b/tests/qapi-schema/nested-struct-data-invalid-dict.err
index 5bd364e8d9..c044b2b17a 100644
--- a/tests/qapi-schema/nested-struct-data-invalid-dict.err
+++ b/tests/qapi-schema/nested-struct-data-invalid-dict.err
@@ -1 +1,2 @@
-tests/qapi-schema/nested-struct-data-invalid-dict.json:2: Key 'type' is missing from member 'a' of 'data' for command 'foo'
+nested-struct-data-invalid-dict.json: In command 'foo':
+nested-struct-data-invalid-dict.json:2: 'data' member 'a' misses key 'type'
diff --git a/tests/qapi-schema/nested-struct-data-invalid-dict.exit b/tests/qapi-schema/nested-struct-data-invalid-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/nested-struct-data-invalid-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/nested-struct-data.err b/tests/qapi-schema/nested-struct-data.err
index da767bade2..c7258a0182 100644
--- a/tests/qapi-schema/nested-struct-data.err
+++ b/tests/qapi-schema/nested-struct-data.err
@@ -1 +1,2 @@
-tests/qapi-schema/nested-struct-data.json:2: Member 'a' of 'data' for command 'foo' should be a type name
+nested-struct-data.json: In command 'foo':
+nested-struct-data.json:2: 'data' member 'a' should be a type name
diff --git a/tests/qapi-schema/nested-struct-data.exit b/tests/qapi-schema/nested-struct-data.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/nested-struct-data.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/non-objects.err b/tests/qapi-schema/non-objects.err
index 334f0c91ae..3a4ea36966 100644
--- a/tests/qapi-schema/non-objects.err
+++ b/tests/qapi-schema/non-objects.err
@@ -1 +1 @@
-tests/qapi-schema/non-objects.json:1:1: Expected "{"
+non-objects.json:1:1: expected '{'
diff --git a/tests/qapi-schema/non-objects.exit b/tests/qapi-schema/non-objects.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/non-objects.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/oob-test.err b/tests/qapi-schema/oob-test.err
index 35b60f7480..7b9a50b3d5 100644
--- a/tests/qapi-schema/oob-test.err
+++ b/tests/qapi-schema/oob-test.err
@@ -1 +1,2 @@
-tests/qapi-schema/oob-test.json:2: 'allow-oob' of command 'oob-command-1' should only use true value
+oob-test.json: In command 'oob-command-1':
+oob-test.json:2: flag 'allow-oob' may only use true value
diff --git a/tests/qapi-schema/oob-test.exit b/tests/qapi-schema/oob-test.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/oob-test.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/pragma-doc-required-crap.err b/tests/qapi-schema/pragma-doc-required-crap.err
index 39cd56cd48..717062cb14 100644
--- a/tests/qapi-schema/pragma-doc-required-crap.err
+++ b/tests/qapi-schema/pragma-doc-required-crap.err
@@ -1 +1 @@
-tests/qapi-schema/pragma-doc-required-crap.json:3: Pragma 'doc-required' must be boolean
+pragma-doc-required-crap.json:3: pragma 'doc-required' must be boolean
diff --git a/tests/qapi-schema/pragma-doc-required-crap.exit b/tests/qapi-schema/pragma-doc-required-crap.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/pragma-doc-required-crap.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/pragma-extra-junk.err b/tests/qapi-schema/pragma-extra-junk.err
index 4481688dbf..ba5cc23f56 100644
--- a/tests/qapi-schema/pragma-extra-junk.err
+++ b/tests/qapi-schema/pragma-extra-junk.err
@@ -1 +1 @@
-tests/qapi-schema/pragma-extra-junk.json:3: Invalid 'pragma' directive
+pragma-extra-junk.json:3: invalid 'pragma' directive
diff --git a/tests/qapi-schema/pragma-extra-junk.exit b/tests/qapi-schema/pragma-extra-junk.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/pragma-extra-junk.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/pragma-name-case-whitelist-crap.err b/tests/qapi-schema/pragma-name-case-whitelist-crap.err
index f83b97e075..fbea90d6c5 100644
--- a/tests/qapi-schema/pragma-name-case-whitelist-crap.err
+++ b/tests/qapi-schema/pragma-name-case-whitelist-crap.err
@@ -1 +1 @@
-tests/qapi-schema/pragma-name-case-whitelist-crap.json:3: Pragma name-case-whitelist must be a list of strings
+pragma-name-case-whitelist-crap.json:3: pragma name-case-whitelist must be a list of strings
diff --git a/tests/qapi-schema/pragma-name-case-whitelist-crap.exit b/tests/qapi-schema/pragma-name-case-whitelist-crap.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/pragma-name-case-whitelist-crap.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/pragma-name-case-whitelist-crap.json b/tests/qapi-schema/pragma-name-case-whitelist-crap.json
index 58382bf4e4..734e1c617b 100644
--- a/tests/qapi-schema/pragma-name-case-whitelist-crap.json
+++ b/tests/qapi-schema/pragma-name-case-whitelist-crap.json
@@ -1,3 +1,3 @@
 # 'name-case-whitelist' must be list of strings
 
-{ 'pragma': { 'name-case-whitelist': null } }
+{ 'pragma': { 'name-case-whitelist': false } }
diff --git a/tests/qapi-schema/pragma-non-dict.err b/tests/qapi-schema/pragma-non-dict.err
index 75bc335aea..802f1806c5 100644
--- a/tests/qapi-schema/pragma-non-dict.err
+++ b/tests/qapi-schema/pragma-non-dict.err
@@ -1 +1 @@
-tests/qapi-schema/pragma-non-dict.json:3: Value of 'pragma' must be a dictionary
+pragma-non-dict.json:3: value of 'pragma' must be an object
diff --git a/tests/qapi-schema/pragma-non-dict.exit b/tests/qapi-schema/pragma-non-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/pragma-non-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/pragma-returns-whitelist-crap.err b/tests/qapi-schema/pragma-returns-whitelist-crap.err
index 5d77021674..69784259df 100644
--- a/tests/qapi-schema/pragma-returns-whitelist-crap.err
+++ b/tests/qapi-schema/pragma-returns-whitelist-crap.err
@@ -1 +1 @@
-tests/qapi-schema/pragma-returns-whitelist-crap.json:3: Pragma returns-whitelist must be a list of strings
+pragma-returns-whitelist-crap.json:3: pragma returns-whitelist must be a list of strings
diff --git a/tests/qapi-schema/pragma-returns-whitelist-crap.exit b/tests/qapi-schema/pragma-returns-whitelist-crap.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/pragma-returns-whitelist-crap.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/pragma-unknown.err b/tests/qapi-schema/pragma-unknown.err
new file mode 100644
index 0000000000..d99a772503
--- /dev/null
+++ b/tests/qapi-schema/pragma-unknown.err
@@ -0,0 +1 @@
+pragma-unknown.json:1: unknown pragma 'no-such-pragma'
diff --git a/tests/qapi-schema/pragma-unknown.json b/tests/qapi-schema/pragma-unknown.json
new file mode 100644
index 0000000000..c51bbbb53f
--- /dev/null
+++ b/tests/qapi-schema/pragma-unknown.json
@@ -0,0 +1 @@
+{ 'pragma': { 'no-such-pragma': false } }
diff --git a/tests/qapi-schema/escape-too-short.out b/tests/qapi-schema/pragma-unknown.out
index e69de29bb2..e69de29bb2 100644
--- a/tests/qapi-schema/escape-too-short.out
+++ b/tests/qapi-schema/pragma-unknown.out
diff --git a/tests/qapi-schema/qapi-schema-test.exit b/tests/qapi-schema/qapi-schema-test.exit
deleted file mode 100644
index 573541ac97..0000000000
--- a/tests/qapi-schema/qapi-schema-test.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index c6d59acc3e..9abf175fe0 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -25,6 +25,11 @@
 { 'struct': 'Empty1', 'data': { } }
 { 'struct': 'Empty2', 'base': 'Empty1', 'data': { } }
 
+# Likewise for an empty flat union
+{ 'union': 'Union',
+  'base': { 'type': 'EnumOne' }, 'discriminator': 'type',
+  'data': { } }
+
 { 'command': 'user_def_cmd0', 'data': 'Empty2', 'returns': 'Empty2' }
 
 # for testing override of default naming heuristic
@@ -149,6 +154,7 @@
 { 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
 { 'command': 'boxed-struct', 'boxed': true, 'data': 'UserDefZero' }
 { 'command': 'boxed-union', 'data': 'UserDefListUnion', 'boxed': true }
+{ 'command': 'boxed-empty', 'boxed': true, 'data': 'Empty1' }
 
 # Smoke test on out-of-band and allow-preconfig-test
 { 'command': 'test-flags-command', 'allow-oob': true, 'allow-preconfig': true }
@@ -180,23 +186,26 @@
 { 'event': 'EVENT_D',
   'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
 { 'event': 'EVENT_E', 'boxed': true, 'data': 'UserDefZero' }
-{ 'event': 'EVENT_F', 'boxed': true, 'data': 'UserDefAlternate' }
+{ 'event': 'EVENT_F', 'boxed': true, 'data': 'UserDefFlatUnion' }
+{ 'event': 'EVENT_G', 'boxed': true, 'data': 'Empty1' }
 
 # test that we correctly compile downstream extensions, as well as munge
 # ticklish names
+# also test union and alternate with just one branch
 { 'enum': '__org.qemu_x-Enum', 'data': [ '__org.qemu_x-value' ] }
 { 'struct': '__org.qemu_x-Base',
   'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
 { 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
   'data': { '__org.qemu_x-member2': 'str', '*wchar-t': 'int' } }
 { 'union': '__org.qemu_x-Union1', 'data': { '__org.qemu_x-branch': 'str' } }
+{ 'alternate': '__org.qemu_x-Alt1', 'data': { '__org.qemu_x-branch': 'str' } }
 { 'struct': '__org.qemu_x-Struct2',
   'data': { 'array': ['__org.qemu_x-Union1'] } }
 { 'union': '__org.qemu_x-Union2', 'base': '__org.qemu_x-Base',
   'discriminator': '__org.qemu_x-member1',
   'data': { '__org.qemu_x-value': '__org.qemu_x-Struct2' } }
 { 'alternate': '__org.qemu_x-Alt',
-  'data': { '__org.qemu_x-branch': 'str', 'b': '__org.qemu_x-Base' } }
+  'data': { '__org.qemu_x-branch': '__org.qemu_x-Base' } }
 { 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
 { 'command': '__org.qemu_x-command',
   'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
@@ -281,3 +290,21 @@
             'cfs1': 'CondFeatureStruct1',
             'cfs2': 'CondFeatureStruct2',
             'cfs3': 'CondFeatureStruct3' } }
+
+# test 'features' for command
+
+{ 'command': 'test-command-features0',
+  'features': [] }
+{ 'command': 'test-command-features1',
+  'features': [ 'feature1' ] }
+{ 'command': 'test-command-features3',
+  'features': [ 'feature1', 'feature2' ] }
+
+{ 'command': 'test-command-cond-features1',
+  'features': [ { 'name': 'feature1', 'if': 'defined(TEST_IF_FEATURE_1)'} ] }
+{ 'command': 'test-command-cond-features2',
+  'features': [ { 'name': 'feature1', 'if': 'defined(TEST_IF_FEATURE_1)'},
+                { 'name': 'feature2', 'if': 'defined(TEST_IF_FEATURE_2)'} ] }
+{ 'command': 'test-command-cond-features3',
+  'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)',
+                                              'defined(TEST_IF_COND_2)'] } ] }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 85d510bc00..3660e75a48 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -23,8 +23,17 @@ enum MyEnum
 object Empty1
 object Empty2
     base Empty1
+object q_obj_Union-base
+    member type: EnumOne optional=False
+object Union
+    base q_obj_Union-base
+    tag type
+    case value1: q_empty
+    case value2: q_empty
+    case value3: q_empty
+    case value4: q_empty
 command user_def_cmd0 Empty2 -> Empty2
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
 enum QEnumTwo
     prefix QENUM_TWO
     member value1
@@ -196,33 +205,35 @@ object SecondArrayRef
     member s: StatusList optional=False
 module qapi-schema-test.json
 command user_def_cmd None -> None
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
 object q_obj_user_def_cmd1-arg
     member ud1a: UserDefOne optional=False
 command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
 object q_obj_user_def_cmd2-arg
     member ud1a: UserDefOne optional=False
     member ud1b: UserDefOne optional=True
 command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
 command cmd-success-response None -> None
-   gen=True success_response=False boxed=False oob=False preconfig=False
+    gen=True success_response=False boxed=False oob=False preconfig=False
 object q_obj_guest-get-time-arg
     member a: int optional=False
     member b: int optional=True
 command guest-get-time q_obj_guest-get-time-arg -> int
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
 object q_obj_guest-sync-arg
     member arg: any optional=False
 command guest-sync q_obj_guest-sync-arg -> any
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
 command boxed-struct UserDefZero -> None
-   gen=True success_response=True boxed=True oob=False preconfig=False
+    gen=True success_response=True boxed=True oob=False preconfig=False
 command boxed-union UserDefListUnion -> None
-   gen=True success_response=True boxed=True oob=False preconfig=False
+    gen=True success_response=True boxed=True oob=False preconfig=False
+command boxed-empty Empty1 -> None
+    gen=True success_response=True boxed=True oob=False preconfig=False
 command test-flags-command None -> None
-   gen=True success_response=True boxed=False oob=True preconfig=True
+    gen=True success_response=True boxed=False oob=True preconfig=True
 object UserDefOptions
     member i64: intList optional=True
     member u64: uint64List optional=True
@@ -234,26 +245,28 @@ object EventStructOne
     member string: str optional=False
     member enum2: EnumOne optional=True
 event EVENT_A None
-   boxed=False
+    boxed=False
 event EVENT_B None
-   boxed=False
+    boxed=False
 object q_obj_EVENT_C-arg
     member a: int optional=True
     member b: UserDefOne optional=True
     member c: str optional=False
 event EVENT_C q_obj_EVENT_C-arg
-   boxed=False
+    boxed=False
 object q_obj_EVENT_D-arg
     member a: EventStructOne optional=False
     member b: str optional=False
     member c: str optional=True
     member enum3: EnumOne optional=True
 event EVENT_D q_obj_EVENT_D-arg
-   boxed=False
+    boxed=False
 event EVENT_E UserDefZero
-   boxed=True
-event EVENT_F UserDefAlternate
-   boxed=True
+    boxed=True
+event EVENT_F UserDefFlatUnion
+    boxed=True
+event EVENT_G Empty1
+    boxed=True
 enum __org.qemu_x-Enum
     member __org.qemu_x-value
 object __org.qemu_x-Base
@@ -270,6 +283,9 @@ object __org.qemu_x-Union1
     member type: __org.qemu_x-Union1Kind optional=False
     tag type
     case __org.qemu_x-branch: q_obj_str-wrapper
+alternate __org.qemu_x-Alt1
+    tag type
+    case __org.qemu_x-branch: str
 array __org.qemu_x-Union1List __org.qemu_x-Union1
 object __org.qemu_x-Struct2
     member array: __org.qemu_x-Union1List optional=False
@@ -279,10 +295,9 @@ object __org.qemu_x-Union2
     case __org.qemu_x-value: __org.qemu_x-Struct2
 alternate __org.qemu_x-Alt
     tag type
-    case __org.qemu_x-branch: str
-    case b: __org.qemu_x-Base
+    case __org.qemu_x-branch: __org.qemu_x-Base
 event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
-   boxed=False
+    boxed=False
 array __org.qemu_x-EnumList __org.qemu_x-Enum
 array __org.qemu_x-StructList __org.qemu_x-Struct
 object q_obj___org.qemu_x-command-arg
@@ -291,7 +306,7 @@ object q_obj___org.qemu_x-command-arg
     member c: __org.qemu_x-Union2 optional=False
     member d: __org.qemu_x-Alt optional=False
 command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
 object TestIfStruct
     member foo: int optional=False
     member bar: int optional=False
@@ -320,7 +335,7 @@ object q_obj_TestIfUnionCmd-arg
     member union_cmd_arg: TestIfUnion optional=False
     if ['defined(TEST_IF_UNION)']
 command TestIfUnionCmd q_obj_TestIfUnionCmd-arg -> None
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
     if ['defined(TEST_IF_UNION)']
 alternate TestIfAlternate
     tag type
@@ -332,7 +347,7 @@ object q_obj_TestIfAlternateCmd-arg
     member alt_cmd_arg: TestIfAlternate optional=False
     if ['defined(TEST_IF_ALT)']
 command TestIfAlternateCmd q_obj_TestIfAlternateCmd-arg -> None
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
     if ['defined(TEST_IF_ALT)']
 object q_obj_TestIfCmd-arg
     member foo: TestIfStruct optional=False
@@ -340,10 +355,10 @@ object q_obj_TestIfCmd-arg
         if ['defined(TEST_IF_CMD_BAR)']
     if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
 command TestIfCmd q_obj_TestIfCmd-arg -> UserDefThree
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
     if ['defined(TEST_IF_CMD)', 'defined(TEST_IF_STRUCT)']
 command TestCmdReturnDefThree None -> UserDefThree
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
 array TestIfEnumList TestIfEnum
     if ['defined(TEST_IF_ENUM)']
 object q_obj_TestIfEvent-arg
@@ -352,7 +367,7 @@ object q_obj_TestIfEvent-arg
         if ['defined(TEST_IF_EVT_BAR)']
     if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
 event TestIfEvent q_obj_TestIfEvent-arg
-   boxed=False
+    boxed=False
     if ['defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)']
 object FeatureStruct0
     member foo: int optional=False
@@ -396,4 +411,27 @@ object q_obj_test-features-arg
     member cfs2: CondFeatureStruct2 optional=False
     member cfs3: CondFeatureStruct3 optional=False
 command test-features q_obj_test-features-arg -> None
-   gen=True success_response=True boxed=False oob=False preconfig=False
+    gen=True success_response=True boxed=False oob=False preconfig=False
+command test-command-features0 None -> None
+    gen=True success_response=True boxed=False oob=False preconfig=False
+command test-command-features1 None -> None
+    gen=True success_response=True boxed=False oob=False preconfig=False
+    feature feature1
+command test-command-features3 None -> None
+    gen=True success_response=True boxed=False oob=False preconfig=False
+    feature feature1
+    feature feature2
+command test-command-cond-features1 None -> None
+    gen=True success_response=True boxed=False oob=False preconfig=False
+    feature feature1
+        if ['defined(TEST_IF_FEATURE_1)']
+command test-command-cond-features2 None -> None
+    gen=True success_response=True boxed=False oob=False preconfig=False
+    feature feature1
+        if ['defined(TEST_IF_FEATURE_1)']
+    feature feature2
+        if ['defined(TEST_IF_FEATURE_2)']
+command test-command-cond-features3 None -> None
+    gen=True success_response=True boxed=False oob=False preconfig=False
+    feature feature1
+        if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)']
diff --git a/tests/qapi-schema/quoted-structural-chars.err b/tests/qapi-schema/quoted-structural-chars.err
index 9b183841dd..07d1561d1f 100644
--- a/tests/qapi-schema/quoted-structural-chars.err
+++ b/tests/qapi-schema/quoted-structural-chars.err
@@ -1 +1 @@
-tests/qapi-schema/quoted-structural-chars.json:1:1: Expected "{"
+quoted-structural-chars.json:1:1: expected '{'
diff --git a/tests/qapi-schema/quoted-structural-chars.exit b/tests/qapi-schema/quoted-structural-chars.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/quoted-structural-chars.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/redefined-builtin.err b/tests/qapi-schema/redefined-builtin.err
index b2757225c4..58c7e42ffc 100644
--- a/tests/qapi-schema/redefined-builtin.err
+++ b/tests/qapi-schema/redefined-builtin.err
@@ -1 +1,2 @@
-tests/qapi-schema/redefined-builtin.json:2: built-in 'size' is already defined
+redefined-builtin.json: In struct 'size':
+redefined-builtin.json:2: built-in type 'size' is already defined
diff --git a/tests/qapi-schema/redefined-builtin.exit b/tests/qapi-schema/redefined-builtin.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/redefined-builtin.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/redefined-command.err b/tests/qapi-schema/redefined-command.err
index 82ae256e63..888eea87ca 100644
--- a/tests/qapi-schema/redefined-command.err
+++ b/tests/qapi-schema/redefined-command.err
@@ -1 +1,4 @@
-tests/qapi-schema/redefined-command.json:3: command 'foo' is already defined
+redefined-command.json: In command 'foo':
+redefined-command.json:3: 'foo' is already defined
+redefined-command.json: In command 'foo':
+redefined-command.json:2: previous definition
diff --git a/tests/qapi-schema/redefined-command.exit b/tests/qapi-schema/redefined-command.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/redefined-command.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/redefined-event.err b/tests/qapi-schema/redefined-event.err
index 35429cb481..b1a6d99d2f 100644
--- a/tests/qapi-schema/redefined-event.err
+++ b/tests/qapi-schema/redefined-event.err
@@ -1 +1,4 @@
-tests/qapi-schema/redefined-event.json:3: event 'EVENT_A' is already defined
+redefined-event.json: In event 'EVENT_A':
+redefined-event.json:3: 'EVENT_A' is already defined
+redefined-event.json: In event 'EVENT_A':
+redefined-event.json:2: previous definition
diff --git a/tests/qapi-schema/redefined-event.exit b/tests/qapi-schema/redefined-event.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/redefined-event.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/redefined-type.err b/tests/qapi-schema/redefined-type.err
index 06ea78c478..b7103fc15f 100644
--- a/tests/qapi-schema/redefined-type.err
+++ b/tests/qapi-schema/redefined-type.err
@@ -1 +1,4 @@
-tests/qapi-schema/redefined-type.json:3: struct 'foo' is already defined
+redefined-type.json: In enum 'foo':
+redefined-type.json:3: 'foo' is already defined
+redefined-type.json: In struct 'foo':
+redefined-type.json:2: previous definition
diff --git a/tests/qapi-schema/redefined-type.exit b/tests/qapi-schema/redefined-type.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/redefined-type.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/reserved-command-q.err b/tests/qapi-schema/reserved-command-q.err
index f939e044eb..6fecbaa046 100644
--- a/tests/qapi-schema/reserved-command-q.err
+++ b/tests/qapi-schema/reserved-command-q.err
@@ -1 +1,2 @@
-tests/qapi-schema/reserved-command-q.json:5: 'command' uses invalid name 'q-unix'
+reserved-command-q.json: In command 'q-unix':
+reserved-command-q.json:5: command has an invalid name
diff --git a/tests/qapi-schema/reserved-command-q.exit b/tests/qapi-schema/reserved-command-q.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/reserved-command-q.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/reserved-enum-q.err b/tests/qapi-schema/reserved-enum-q.err
index e1c3480ee2..fc3c757874 100644
--- a/tests/qapi-schema/reserved-enum-q.err
+++ b/tests/qapi-schema/reserved-enum-q.err
@@ -1 +1,2 @@
-tests/qapi-schema/reserved-enum-q.json:4: Member of enum 'Foo' uses invalid name 'q-Unix'
+reserved-enum-q.json: In enum 'Foo':
+reserved-enum-q.json:4: 'data' member 'q-Unix' has an invalid name
diff --git a/tests/qapi-schema/reserved-enum-q.exit b/tests/qapi-schema/reserved-enum-q.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/reserved-enum-q.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/reserved-member-has.err b/tests/qapi-schema/reserved-member-has.err
index e755771446..436e1749f2 100644
--- a/tests/qapi-schema/reserved-member-has.err
+++ b/tests/qapi-schema/reserved-member-has.err
@@ -1 +1,2 @@
-tests/qapi-schema/reserved-member-has.json:5: Member of 'data' for command 'oops' uses reserved name 'has-a'
+reserved-member-has.json: In command 'oops':
+reserved-member-has.json:5: 'data' member 'has-a' uses reserved name
diff --git a/tests/qapi-schema/reserved-member-has.exit b/tests/qapi-schema/reserved-member-has.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/reserved-member-has.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/reserved-member-q.err b/tests/qapi-schema/reserved-member-q.err
index f3d5dd7818..9ac8654a8b 100644
--- a/tests/qapi-schema/reserved-member-q.err
+++ b/tests/qapi-schema/reserved-member-q.err
@@ -1 +1,2 @@
-tests/qapi-schema/reserved-member-q.json:4: Member of 'data' for struct 'Foo' uses invalid name 'q-unix'
+reserved-member-q.json: In struct 'Foo':
+reserved-member-q.json:4: 'data' member 'q-unix' has an invalid name
diff --git a/tests/qapi-schema/reserved-member-q.exit b/tests/qapi-schema/reserved-member-q.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/reserved-member-q.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/reserved-member-u.err b/tests/qapi-schema/reserved-member-u.err
index 87d42296cc..231d552494 100644
--- a/tests/qapi-schema/reserved-member-u.err
+++ b/tests/qapi-schema/reserved-member-u.err
@@ -1 +1,2 @@
-tests/qapi-schema/reserved-member-u.json:7: Member of 'data' for struct 'Oops' uses reserved name 'u'
+reserved-member-u.json: In struct 'Oops':
+reserved-member-u.json:7: 'data' member 'u' uses reserved name
diff --git a/tests/qapi-schema/reserved-member-u.exit b/tests/qapi-schema/reserved-member-u.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/reserved-member-u.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/reserved-member-underscore.err b/tests/qapi-schema/reserved-member-underscore.err
index 65ff0da8ce..df3ab8a11a 100644
--- a/tests/qapi-schema/reserved-member-underscore.err
+++ b/tests/qapi-schema/reserved-member-underscore.err
@@ -1 +1,2 @@
-tests/qapi-schema/reserved-member-underscore.json:4: Member of 'data' for struct 'Oops' uses invalid name '_oops'
+reserved-member-underscore.json: In struct 'Oops':
+reserved-member-underscore.json:4: 'data' member '_oops' has an invalid name
diff --git a/tests/qapi-schema/reserved-member-underscore.exit b/tests/qapi-schema/reserved-member-underscore.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/reserved-member-underscore.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/reserved-type-kind.err b/tests/qapi-schema/reserved-type-kind.err
index 0a38efaad8..d8fb769f9d 100644
--- a/tests/qapi-schema/reserved-type-kind.err
+++ b/tests/qapi-schema/reserved-type-kind.err
@@ -1 +1,2 @@
-tests/qapi-schema/reserved-type-kind.json:2: enum 'UnionKind' should not end in 'Kind'
+reserved-type-kind.json: In enum 'UnionKind':
+reserved-type-kind.json:2: enum name should not end in 'Kind'
diff --git a/tests/qapi-schema/reserved-type-kind.exit b/tests/qapi-schema/reserved-type-kind.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/reserved-type-kind.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/reserved-type-list.err b/tests/qapi-schema/reserved-type-list.err
index 4510fa6d90..e09f5352f8 100644
--- a/tests/qapi-schema/reserved-type-list.err
+++ b/tests/qapi-schema/reserved-type-list.err
@@ -1 +1,2 @@
-tests/qapi-schema/reserved-type-list.json:5: struct 'FooList' should not end in 'List'
+reserved-type-list.json: In struct 'FooList':
+reserved-type-list.json:5: struct name should not end in 'List'
diff --git a/tests/qapi-schema/reserved-type-list.exit b/tests/qapi-schema/reserved-type-list.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/reserved-type-list.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/returns-alternate.err b/tests/qapi-schema/returns-alternate.err
index dfbb419cac..b6421a8917 100644
--- a/tests/qapi-schema/returns-alternate.err
+++ b/tests/qapi-schema/returns-alternate.err
@@ -1 +1,2 @@
-tests/qapi-schema/returns-alternate.json:3: 'returns' for command 'oops' cannot use alternate type 'Alt'
+returns-alternate.json: In command 'oops':
+returns-alternate.json:3: command's 'returns' cannot take alternate type 'Alt'
diff --git a/tests/qapi-schema/returns-alternate.exit b/tests/qapi-schema/returns-alternate.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/returns-alternate.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/returns-array-bad.err b/tests/qapi-schema/returns-array-bad.err
index 138095ccde..52712d139d 100644
--- a/tests/qapi-schema/returns-array-bad.err
+++ b/tests/qapi-schema/returns-array-bad.err
@@ -1 +1,2 @@
-tests/qapi-schema/returns-array-bad.json:2: 'returns' for command 'oops': array type must contain single type name
+returns-array-bad.json: In command 'oops':
+returns-array-bad.json:2: 'returns': array type must contain single type name
diff --git a/tests/qapi-schema/returns-array-bad.exit b/tests/qapi-schema/returns-array-bad.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/returns-array-bad.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/returns-dict.err b/tests/qapi-schema/returns-dict.err
index eb2d0c4661..9b2d90c010 100644
--- a/tests/qapi-schema/returns-dict.err
+++ b/tests/qapi-schema/returns-dict.err
@@ -1 +1,2 @@
-tests/qapi-schema/returns-dict.json:2: 'returns' for command 'oops' should be a type name
+returns-dict.json: In command 'oops':
+returns-dict.json:2: 'returns' should be a type name
diff --git a/tests/qapi-schema/returns-dict.exit b/tests/qapi-schema/returns-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/returns-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/returns-unknown.err b/tests/qapi-schema/returns-unknown.err
index 1f43e3ac9f..bf59086d0c 100644
--- a/tests/qapi-schema/returns-unknown.err
+++ b/tests/qapi-schema/returns-unknown.err
@@ -1 +1,2 @@
-tests/qapi-schema/returns-unknown.json:2: 'returns' for command 'oops' uses unknown type 'NoSuchType'
+returns-unknown.json: In command 'oops':
+returns-unknown.json:2: command's 'returns' uses unknown type 'NoSuchType'
diff --git a/tests/qapi-schema/returns-unknown.exit b/tests/qapi-schema/returns-unknown.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/returns-unknown.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/returns-whitelist.err b/tests/qapi-schema/returns-whitelist.err
index b2ba7a9deb..c6e46b9b86 100644
--- a/tests/qapi-schema/returns-whitelist.err
+++ b/tests/qapi-schema/returns-whitelist.err
@@ -1 +1,2 @@
-tests/qapi-schema/returns-whitelist.json:14: 'returns' for command 'no-way-this-will-get-whitelisted' cannot use built-in type 'int'
+returns-whitelist.json: In command 'no-way-this-will-get-whitelisted':
+returns-whitelist.json:14: command's 'returns' cannot take array type ['int']
diff --git a/tests/qapi-schema/returns-whitelist.exit b/tests/qapi-schema/returns-whitelist.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/returns-whitelist.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/string-code-point-127.err b/tests/qapi-schema/string-code-point-127.err
new file mode 100644
index 0000000000..eb0d1c71a6
--- /dev/null
+++ b/tests/qapi-schema/string-code-point-127.err
@@ -0,0 +1 @@
+string-code-point-127.json:2:14: funny character in string
diff --git a/tests/qapi-schema/string-code-point-127.json b/tests/qapi-schema/string-code-point-127.json
new file mode 100644
index 0000000000..480318a69f
--- /dev/null
+++ b/tests/qapi-schema/string-code-point-127.json
@@ -0,0 +1,2 @@
+# We accept printable ASCII: code points 32..126.  Test code point 127:
+{ 'command': '' }
diff --git a/tests/qapi-schema/include-format-err.out b/tests/qapi-schema/string-code-point-127.out
index e69de29bb2..e69de29bb2 100644
--- a/tests/qapi-schema/include-format-err.out
+++ b/tests/qapi-schema/string-code-point-127.out
diff --git a/tests/qapi-schema/string-code-point-31.err b/tests/qapi-schema/string-code-point-31.err
new file mode 100644
index 0000000000..ae969d6e10
--- /dev/null
+++ b/tests/qapi-schema/string-code-point-31.err
@@ -0,0 +1 @@
+string-code-point-31.json:2:14: funny character in string
diff --git a/tests/qapi-schema/string-code-point-31.json b/tests/qapi-schema/string-code-point-31.json
new file mode 100644
index 0000000000..f186cbd720
--- /dev/null
+++ b/tests/qapi-schema/string-code-point-31.json
@@ -0,0 +1,2 @@
+# We accept printable ASCII: code points 32..126.  Test code point 127:
+{ 'command': '' }
diff --git a/tests/qapi-schema/unicode-str.out b/tests/qapi-schema/string-code-point-31.out
index e69de29bb2..e69de29bb2 100644
--- a/tests/qapi-schema/unicode-str.out
+++ b/tests/qapi-schema/string-code-point-31.out
diff --git a/tests/qapi-schema/struct-base-clash-deep.err b/tests/qapi-schema/struct-base-clash-deep.err
index e2d7943f21..79879681d9 100644
--- a/tests/qapi-schema/struct-base-clash-deep.err
+++ b/tests/qapi-schema/struct-base-clash-deep.err
@@ -1 +1,2 @@
-tests/qapi-schema/struct-base-clash-deep.json:10: 'name' (member of Sub) collides with 'name' (member of Base)
+struct-base-clash-deep.json: In struct 'Sub':
+struct-base-clash-deep.json:10: member 'name' collides with member 'name' of type 'Base'
diff --git a/tests/qapi-schema/struct-base-clash-deep.exit b/tests/qapi-schema/struct-base-clash-deep.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/struct-base-clash-deep.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/struct-base-clash.err b/tests/qapi-schema/struct-base-clash.err
index c52f33d27b..46473947e6 100644
--- a/tests/qapi-schema/struct-base-clash.err
+++ b/tests/qapi-schema/struct-base-clash.err
@@ -1 +1,2 @@
-tests/qapi-schema/struct-base-clash.json:5: 'name' (member of Sub) collides with 'name' (member of Base)
+struct-base-clash.json: In struct 'Sub':
+struct-base-clash.json:5: member 'name' collides with member 'name' of type 'Base'
diff --git a/tests/qapi-schema/struct-base-clash.exit b/tests/qapi-schema/struct-base-clash.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/struct-base-clash.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/struct-data-invalid.err b/tests/qapi-schema/struct-data-invalid.err
index 6644f4c2ad..5ed4bec573 100644
--- a/tests/qapi-schema/struct-data-invalid.err
+++ b/tests/qapi-schema/struct-data-invalid.err
@@ -1 +1,2 @@
-tests/qapi-schema/struct-data-invalid.json:1: 'data' for struct 'foo' should be a dictionary or type name
+struct-data-invalid.json: In struct 'foo':
+struct-data-invalid.json:1: 'data' should be an object or type name
diff --git a/tests/qapi-schema/struct-data-invalid.exit b/tests/qapi-schema/struct-data-invalid.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/struct-data-invalid.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/struct-member-if-invalid.err b/tests/qapi-schema/struct-member-if-invalid.err
new file mode 100644
index 0000000000..42e7fdae3c
--- /dev/null
+++ b/tests/qapi-schema/struct-member-if-invalid.err
@@ -0,0 +1,2 @@
+struct-member-if-invalid.json: In struct 'Stru':
+struct-member-if-invalid.json:2: 'if' condition of 'data' member 'member' must be a string or a list of strings
diff --git a/tests/qapi-schema/struct-member-if-invalid.json b/tests/qapi-schema/struct-member-if-invalid.json
new file mode 100644
index 0000000000..35078bd660
--- /dev/null
+++ b/tests/qapi-schema/struct-member-if-invalid.json
@@ -0,0 +1,3 @@
+# Cover member with invalid 'if'
+{ 'struct': 'Stru',
+  'data': { 'member': { 'type': 'int', 'if': true } } }
diff --git a/tests/qapi-schema/struct-member-if-invalid.out b/tests/qapi-schema/struct-member-if-invalid.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/struct-member-if-invalid.out
diff --git a/tests/qapi-schema/struct-member-invalid-dict.err b/tests/qapi-schema/struct-member-invalid-dict.err
index 6a765bc668..0621aecfbd 100644
--- a/tests/qapi-schema/struct-member-invalid-dict.err
+++ b/tests/qapi-schema/struct-member-invalid-dict.err
@@ -1 +1,2 @@
-tests/qapi-schema/struct-member-invalid-dict.json:2: Key 'type' is missing from member '*a' of 'data' for struct 'foo'
+struct-member-invalid-dict.json: In struct 'foo':
+struct-member-invalid-dict.json:2: 'data' member '*a' misses key 'type'
diff --git a/tests/qapi-schema/struct-member-invalid-dict.exit b/tests/qapi-schema/struct-member-invalid-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/struct-member-invalid-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/struct-member-invalid.err b/tests/qapi-schema/struct-member-invalid.err
index 69a326d450..9a2c934538 100644
--- a/tests/qapi-schema/struct-member-invalid.err
+++ b/tests/qapi-schema/struct-member-invalid.err
@@ -1 +1,2 @@
-tests/qapi-schema/struct-member-invalid.json:1: Member 'a' of 'data' for struct 'foo' should be a type name
+struct-member-invalid.json: In struct 'foo':
+struct-member-invalid.json:1: 'data' member 'a' should be a type name
diff --git a/tests/qapi-schema/struct-member-invalid.exit b/tests/qapi-schema/struct-member-invalid.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/struct-member-invalid.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index b0f770b9bd..2bd9fd8742 100644..100755
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 #
 # QAPI parser test harness
 #
@@ -11,8 +12,19 @@
 #
 
 from __future__ import print_function
+
+import argparse
+import difflib
+import os
 import sys
-from qapi.common import QAPIError, QAPISchema, QAPISchemaVisitor
+
+from qapi.error import QAPIError
+from qapi.schema import QAPISchema, QAPISchemaVisitor
+
+if sys.version_info[0] < 3:
+    from cStringIO import StringIO
+else:
+    from io import StringIO
 
 
 class QAPISchemaTestVisitor(QAPISchemaVisitor):
@@ -49,10 +61,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
             self._print_if(m.ifcond, 8)
         self._print_variants(variants)
         self._print_if(ifcond)
-        if features:
-            for f in features:
-                print('    feature %s' % f.name)
-                self._print_if(f.ifcond, 8)
+        self._print_features(features)
 
     def visit_alternate_type(self, name, info, ifcond, variants):
         print('alternate %s' % name)
@@ -60,17 +69,19 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
         self._print_if(ifcond)
 
     def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
-                      success_response, boxed, allow_oob, allow_preconfig):
+                      success_response, boxed, allow_oob, allow_preconfig,
+                      features):
         print('command %s %s -> %s'
               % (name, arg_type and arg_type.name,
                  ret_type and ret_type.name))
-        print('   gen=%s success_response=%s boxed=%s oob=%s preconfig=%s'
+        print('    gen=%s success_response=%s boxed=%s oob=%s preconfig=%s'
               % (gen, success_response, boxed, allow_oob, allow_preconfig))
         self._print_if(ifcond)
+        self._print_features(features)
 
     def visit_event(self, name, info, ifcond, arg_type, boxed):
         print('event %s %s' % (name, arg_type and arg_type.name))
-        print('   boxed=%s' % boxed)
+        print('    boxed=%s' % boxed)
         self._print_if(ifcond)
 
     @staticmethod
@@ -86,22 +97,110 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
         if ifcond:
             print('%sif %s' % (' ' * indent, ifcond))
 
-
-try:
-    schema = QAPISchema(sys.argv[1])
-except QAPIError as err:
-    print(err, file=sys.stderr)
-    exit(1)
-
-schema.visit(QAPISchemaTestVisitor())
-
-for doc in schema.docs:
-    if doc.symbol:
-        print('doc symbol=%s' % doc.symbol)
+    @classmethod
+    def _print_features(cls, features):
+        if features:
+            for f in features:
+                print('    feature %s' % f.name)
+                cls._print_if(f.ifcond, 8)
+
+
+def test_frontend(fname):
+    schema = QAPISchema(fname)
+    schema.visit(QAPISchemaTestVisitor())
+
+    for doc in schema.docs:
+        if doc.symbol:
+            print('doc symbol=%s' % doc.symbol)
+        else:
+            print('doc freeform')
+        print('    body=\n%s' % doc.body.text)
+        for arg, section in doc.args.items():
+            print('    arg=%s\n%s' % (arg, section.text))
+        for section in doc.sections:
+            print('    section=%s\n%s' % (section.name, section.text))
+
+
+def test_and_diff(test_name, dir_name, update):
+    sys.stdout = StringIO()
+    try:
+        test_frontend(os.path.join(dir_name, test_name + '.json'))
+    except QAPIError as err:
+        if err.info.fname is None:
+            print("%s" % err, file=sys.stderr)
+            return 2
+        errstr = str(err) + '\n'
+        if dir_name:
+            errstr = errstr.replace(dir_name + '/', '')
+        actual_err = errstr.splitlines(True)
     else:
-        print('doc freeform')
-    print('    body=\n%s' % doc.body.text)
-    for arg, section in doc.args.items():
-        print('    arg=%s\n%s' % (arg, section.text))
-    for section in doc.sections:
-        print('    section=%s\n%s' % (section.name, section.text))
+        actual_err = []
+    finally:
+        actual_out = sys.stdout.getvalue().splitlines(True)
+        sys.stdout.close()
+        sys.stdout = sys.__stdout__
+
+    mode = 'r+' if update else 'r'
+    try:
+        outfp = open(os.path.join(dir_name, test_name + '.out'), mode)
+        errfp = open(os.path.join(dir_name, test_name + '.err'), mode)
+        expected_out = outfp.readlines()
+        expected_err = errfp.readlines()
+    except IOError as err:
+        print("%s: can't open '%s': %s"
+              % (sys.argv[0], err.filename, err.strerror),
+              file=sys.stderr)
+        return 2
+
+    if actual_out == expected_out and actual_err == expected_err:
+        return 0
+
+    print("%s %s" % (test_name, 'UPDATE' if update else 'FAIL'),
+          file=sys.stderr)
+    out_diff = difflib.unified_diff(expected_out, actual_out, outfp.name)
+    err_diff = difflib.unified_diff(expected_err, actual_err, errfp.name)
+    sys.stdout.writelines(out_diff)
+    sys.stdout.writelines(err_diff)
+
+    if not update:
+        return 1
+
+    try:
+        outfp.truncate(0)
+        outfp.seek(0)
+        outfp.writelines(actual_out)
+        errfp.truncate(0)
+        errfp.seek(0)
+        errfp.writelines(actual_err)
+    except IOError as err:
+        print("%s: can't write '%s': %s"
+              % (sys.argv[0], err.filename, err.strerror),
+              file=sys.stderr)
+        return 2
+
+    return 0
+
+
+def main(argv):
+    parser = argparse.ArgumentParser(
+        description='QAPI schema tester')
+    parser.add_argument('-d', '--dir', action='store', default='',
+                        help="directory containing tests")
+    parser.add_argument('-u', '--update', action='store_true',
+                        help="update expected test results")
+    parser.add_argument('tests', nargs='*', metavar='TEST', action='store')
+    args = parser.parse_args()
+
+    status = 0
+    for t in args.tests:
+        (dir_name, base_name) = os.path.split(t)
+        dir_name = dir_name or args.dir
+        test_name = os.path.splitext(base_name)[0]
+        status |= test_and_diff(test_name, dir_name, args.update)
+
+    exit(status)
+
+
+if __name__ == '__main__':
+    main(sys.argv)
+    exit(0)
diff --git a/tests/qapi-schema/trailing-comma-list.err b/tests/qapi-schema/trailing-comma-list.err
index 212e14ae28..ad2f2d7c97 100644
--- a/tests/qapi-schema/trailing-comma-list.err
+++ b/tests/qapi-schema/trailing-comma-list.err
@@ -1 +1 @@
-tests/qapi-schema/trailing-comma-list.json:2:36: Expected "{", "[", string, boolean or "null"
+trailing-comma-list.json:2:36: expected '{', '[', string, boolean or 'null'
diff --git a/tests/qapi-schema/trailing-comma-list.exit b/tests/qapi-schema/trailing-comma-list.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/trailing-comma-list.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/trailing-comma-object.err b/tests/qapi-schema/trailing-comma-object.err
index 30bce5e194..29aafc69cd 100644
--- a/tests/qapi-schema/trailing-comma-object.err
+++ b/tests/qapi-schema/trailing-comma-object.err
@@ -1 +1 @@
-tests/qapi-schema/trailing-comma-object.json:2:38: Expected string
+trailing-comma-object.json:2:38: expected string
diff --git a/tests/qapi-schema/trailing-comma-object.exit b/tests/qapi-schema/trailing-comma-object.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/trailing-comma-object.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/type-bypass-bad-gen.err b/tests/qapi-schema/type-bypass-bad-gen.err
index a83c3c655d..2ca95cd86d 100644
--- a/tests/qapi-schema/type-bypass-bad-gen.err
+++ b/tests/qapi-schema/type-bypass-bad-gen.err
@@ -1 +1,2 @@
-tests/qapi-schema/type-bypass-bad-gen.json:2: 'gen' of command 'foo' should only use false value
+type-bypass-bad-gen.json: In command 'foo':
+type-bypass-bad-gen.json:2: flag 'gen' may only use false value
diff --git a/tests/qapi-schema/type-bypass-bad-gen.exit b/tests/qapi-schema/type-bypass-bad-gen.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/type-bypass-bad-gen.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/unclosed-list.err b/tests/qapi-schema/unclosed-list.err
index fb41a86abd..aa2c430b22 100644
--- a/tests/qapi-schema/unclosed-list.err
+++ b/tests/qapi-schema/unclosed-list.err
@@ -1 +1 @@
-tests/qapi-schema/unclosed-list.json:1:20: Expected "," or "]"
+unclosed-list.json:1:20: expected ',' or ']'
diff --git a/tests/qapi-schema/unclosed-list.exit b/tests/qapi-schema/unclosed-list.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/unclosed-list.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/unclosed-object.err b/tests/qapi-schema/unclosed-object.err
index db3deedd63..c08499b341 100644
--- a/tests/qapi-schema/unclosed-object.err
+++ b/tests/qapi-schema/unclosed-object.err
@@ -1 +1 @@
-tests/qapi-schema/unclosed-object.json:1:21: Expected "," or "}"
+unclosed-object.json:1:21: expected ',' or '}'
diff --git a/tests/qapi-schema/unclosed-object.exit b/tests/qapi-schema/unclosed-object.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/unclosed-object.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/unclosed-string.err b/tests/qapi-schema/unclosed-string.err
index 12b187074e..175e192b24 100644
--- a/tests/qapi-schema/unclosed-string.err
+++ b/tests/qapi-schema/unclosed-string.err
@@ -1 +1 @@
-tests/qapi-schema/unclosed-string.json:1:11: Missing terminating "'"
+unclosed-string.json:1:11: missing terminating "'"
diff --git a/tests/qapi-schema/unclosed-string.exit b/tests/qapi-schema/unclosed-string.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/unclosed-string.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/unicode-str.err b/tests/qapi-schema/unicode-str.err
deleted file mode 100644
index f621cd6448..0000000000
--- a/tests/qapi-schema/unicode-str.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/unicode-str.json:2: 'command' uses invalid name 'é'
diff --git a/tests/qapi-schema/unicode-str.exit b/tests/qapi-schema/unicode-str.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/unicode-str.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/unicode-str.json b/tests/qapi-schema/unicode-str.json
deleted file mode 100644
index 5253a1b9f3..0000000000
--- a/tests/qapi-schema/unicode-str.json
+++ /dev/null
@@ -1,2 +0,0 @@
-# we don't support full Unicode strings, yet
-{ 'command': 'é' }
diff --git a/tests/qapi-schema/union-base-empty.err b/tests/qapi-schema/union-base-empty.err
index 7695806d81..3630b341a6 100644
--- a/tests/qapi-schema/union-base-empty.err
+++ b/tests/qapi-schema/union-base-empty.err
@@ -1 +1,2 @@
-tests/qapi-schema/union-base-empty.json:5: Discriminator 'type' is not a member of base struct 'Empty'
+union-base-empty.json: In union 'TestUnion':
+union-base-empty.json:5: discriminator 'type' is not a member of 'base'
diff --git a/tests/qapi-schema/union-base-empty.exit b/tests/qapi-schema/union-base-empty.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/union-base-empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/union-base-no-discriminator.err b/tests/qapi-schema/union-base-no-discriminator.err
index 8b7a24260f..9cd5d11b0b 100644
--- a/tests/qapi-schema/union-base-no-discriminator.err
+++ b/tests/qapi-schema/union-base-no-discriminator.err
@@ -1 +1,2 @@
-tests/qapi-schema/union-base-no-discriminator.json:11: Simple union 'TestUnion' must not have a base
+union-base-no-discriminator.json: In union 'TestUnion':
+union-base-no-discriminator.json:11: 'base' requires 'discriminator'
diff --git a/tests/qapi-schema/union-base-no-discriminator.exit b/tests/qapi-schema/union-base-no-discriminator.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/union-base-no-discriminator.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/union-branch-case.err b/tests/qapi-schema/union-branch-case.err
index 11521901d8..b1e9417303 100644
--- a/tests/qapi-schema/union-branch-case.err
+++ b/tests/qapi-schema/union-branch-case.err
@@ -1 +1,2 @@
-tests/qapi-schema/union-branch-case.json:2: 'Branch' (branch of NoWayThisWillGetWhitelisted) should not use uppercase
+union-branch-case.json: In union 'Uni':
+union-branch-case.json:2: 'data' member 'Branch' uses uppercase in name
diff --git a/tests/qapi-schema/union-branch-case.exit b/tests/qapi-schema/union-branch-case.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/union-branch-case.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/union-branch-case.json b/tests/qapi-schema/union-branch-case.json
index e6565dc3b3..b7894b75d6 100644
--- a/tests/qapi-schema/union-branch-case.json
+++ b/tests/qapi-schema/union-branch-case.json
@@ -1,2 +1,2 @@
-# Branch names should be 'lower-case' unless the union is whitelisted
-{ 'union': 'NoWayThisWillGetWhitelisted', 'data': { 'Branch': 'int' } }
+# Branch names should be 'lower-case'
+{ 'union': 'Uni', 'data': { 'Branch': 'int' } }
diff --git a/tests/qapi-schema/union-branch-if-invalid.err b/tests/qapi-schema/union-branch-if-invalid.err
new file mode 100644
index 0000000000..dd4518233e
--- /dev/null
+++ b/tests/qapi-schema/union-branch-if-invalid.err
@@ -0,0 +1,2 @@
+union-branch-if-invalid.json: In union 'Uni':
+union-branch-if-invalid.json:4: 'if' condition '' of 'data' member 'branch1' makes no sense
diff --git a/tests/qapi-schema/union-branch-if-invalid.json b/tests/qapi-schema/union-branch-if-invalid.json
new file mode 100644
index 0000000000..46d4239af6
--- /dev/null
+++ b/tests/qapi-schema/union-branch-if-invalid.json
@@ -0,0 +1,6 @@
+# Cover branch with invalid 'if'
+{ 'enum': 'Branches', 'data': ['branch1'] }
+{ 'struct': 'Stru', 'data': { 'member': 'str' } }
+{ 'union': 'Uni',
+  'base': { 'tag': 'Branches' }, 'discriminator': 'tag',
+  'data': { 'branch1': { 'type': 'Stru', 'if': [''] } } }
diff --git a/tests/qapi-schema/union-branch-if-invalid.out b/tests/qapi-schema/union-branch-if-invalid.out
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/qapi-schema/union-branch-if-invalid.out
diff --git a/tests/qapi-schema/union-branch-invalid-dict.err b/tests/qapi-schema/union-branch-invalid-dict.err
index 89f9b36791..8137c5a767 100644
--- a/tests/qapi-schema/union-branch-invalid-dict.err
+++ b/tests/qapi-schema/union-branch-invalid-dict.err
@@ -1 +1,2 @@
-tests/qapi-schema/union-branch-invalid-dict.json:2: Key 'type' is missing from member 'integer' of union 'UnionInvalidBranch'
+union-branch-invalid-dict.json: In union 'UnionInvalidBranch':
+union-branch-invalid-dict.json:2: 'data' member 'integer' misses key 'type'
diff --git a/tests/qapi-schema/union-branch-invalid-dict.exit b/tests/qapi-schema/union-branch-invalid-dict.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/union-branch-invalid-dict.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/union-clash-branches.err b/tests/qapi-schema/union-clash-branches.err
index e5b21135bb..73bbc2cabd 100644
--- a/tests/qapi-schema/union-clash-branches.err
+++ b/tests/qapi-schema/union-clash-branches.err
@@ -1 +1,2 @@
-tests/qapi-schema/union-clash-branches.json:4: 'a_b' (branch of TestUnion) collides with 'a-b' (branch of TestUnion)
+union-clash-branches.json: In union 'TestUnion':
+union-clash-branches.json:4: branch 'a_b' collides with branch 'a-b'
diff --git a/tests/qapi-schema/union-clash-branches.exit b/tests/qapi-schema/union-clash-branches.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/union-clash-branches.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/union-empty.err b/tests/qapi-schema/union-empty.err
index 12c20221bd..59788c94ce 100644
--- a/tests/qapi-schema/union-empty.err
+++ b/tests/qapi-schema/union-empty.err
@@ -1 +1,2 @@
-tests/qapi-schema/union-empty.json:2: Union 'Union' cannot have empty 'data'
+union-empty.json: In union 'Union':
+union-empty.json:2: union has no branches
diff --git a/tests/qapi-schema/union-empty.exit b/tests/qapi-schema/union-empty.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/union-empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/union-empty.json b/tests/qapi-schema/union-empty.json
index 1f0b13ca21..df3e5e639a 100644
--- a/tests/qapi-schema/union-empty.json
+++ b/tests/qapi-schema/union-empty.json
@@ -1,2 +1,2 @@
-# unions cannot be empty
+# simple unions cannot be empty
 { 'union': 'Union', 'data': { } }
diff --git a/tests/qapi-schema/union-invalid-base.err b/tests/qapi-schema/union-invalid-base.err
index 03d7b97a93..a804028438 100644
--- a/tests/qapi-schema/union-invalid-base.err
+++ b/tests/qapi-schema/union-invalid-base.err
@@ -1 +1,2 @@
-tests/qapi-schema/union-invalid-base.json:8: 'base' for union 'TestUnion' cannot use built-in type 'int'
+union-invalid-base.json: In union 'TestUnion':
+union-invalid-base.json:8: 'base' requires a struct type, built-in type 'int' isn't
diff --git a/tests/qapi-schema/union-invalid-base.exit b/tests/qapi-schema/union-invalid-base.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/union-invalid-base.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/union-optional-branch.err b/tests/qapi-schema/union-optional-branch.err
index 3ada1334dc..b33f111de4 100644
--- a/tests/qapi-schema/union-optional-branch.err
+++ b/tests/qapi-schema/union-optional-branch.err
@@ -1 +1,2 @@
-tests/qapi-schema/union-optional-branch.json:2: Member of union 'Union' does not allow optional name '*a'
+union-optional-branch.json: In union 'Union':
+union-optional-branch.json:2: 'data' member '*a' has an invalid name
diff --git a/tests/qapi-schema/union-optional-branch.exit b/tests/qapi-schema/union-optional-branch.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/union-optional-branch.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/union-unknown.err b/tests/qapi-schema/union-unknown.err
index 54fe456f9c..7aba9f94da 100644
--- a/tests/qapi-schema/union-unknown.err
+++ b/tests/qapi-schema/union-unknown.err
@@ -1 +1,2 @@
-tests/qapi-schema/union-unknown.json:2: Member 'unknown' of union 'Union' uses unknown type 'MissingType'
+union-unknown.json: In union 'Union':
+union-unknown.json:2: union uses unknown type 'MissingType'
diff --git a/tests/qapi-schema/union-unknown.exit b/tests/qapi-schema/union-unknown.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/union-unknown.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/union-unknown.json b/tests/qapi-schema/union-unknown.json
index aa7e8143d8..64d3666176 100644
--- a/tests/qapi-schema/union-unknown.json
+++ b/tests/qapi-schema/union-unknown.json
@@ -1,3 +1,3 @@
 # we reject a union with unknown type in branch
 { 'union': 'Union',
-  'data': { 'unknown': 'MissingType' } }
+  'data': { 'unknown': ['MissingType'] } }
diff --git a/tests/qapi-schema/unknown-escape.err b/tests/qapi-schema/unknown-escape.err
index 000e30ddf3..759a5990d8 100644
--- a/tests/qapi-schema/unknown-escape.err
+++ b/tests/qapi-schema/unknown-escape.err
@@ -1 +1 @@
-tests/qapi-schema/unknown-escape.json:3:21: Unknown escape \x
+unknown-escape.json:3:21: unknown escape \x
diff --git a/tests/qapi-schema/unknown-escape.exit b/tests/qapi-schema/unknown-escape.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/unknown-escape.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests/qapi-schema/unknown-escape.json b/tests/qapi-schema/unknown-escape.json
index 8e6891e52a..8372e8024f 100644
--- a/tests/qapi-schema/unknown-escape.json
+++ b/tests/qapi-schema/unknown-escape.json
@@ -1,3 +1,3 @@
-# we only recognize JSON escape sequences, plus our \' extension (no \x)
+# we only recognize \\
 # { 'command': 'foo', 'data': {} }
 { 'command': 'foo', 'dat\x61':{} }
diff --git a/tests/qapi-schema/unknown-expr-key.err b/tests/qapi-schema/unknown-expr-key.err
index 4340eaf894..c5f395bf79 100644
--- a/tests/qapi-schema/unknown-expr-key.err
+++ b/tests/qapi-schema/unknown-expr-key.err
@@ -1,2 +1,3 @@
-tests/qapi-schema/unknown-expr-key.json:2: Unknown keys 'bogus', 'phony' in struct 'bar'
+unknown-expr-key.json: In struct 'bar':
+unknown-expr-key.json:2: struct has unknown keys 'bogus', 'phony'
 Valid keys are 'base', 'data', 'features', 'if', 'struct'.
diff --git a/tests/qapi-schema/unknown-expr-key.exit b/tests/qapi-schema/unknown-expr-key.exit
deleted file mode 100644
index d00491fd7e..0000000000
--- a/tests/qapi-schema/unknown-expr-key.exit
+++ /dev/null
@@ -1 +0,0 @@
-1