summaryrefslogtreecommitdiffstats
path: root/qemu/tests
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-05-18 13:18:31 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-05-18 13:42:15 +0300
commit437fd90c0250dee670290f9b714253671a990160 (patch)
treeb871786c360704244a07411c69fb58da9ead4a06 /qemu/tests
parent5bbd6fe9b8bab2a93e548c5a53b032d1939eec05 (diff)
These changes are the raw update to qemu-2.6.
Collission happened in the following patches: migration: do cleanup operation after completion(738df5b9) Bug fix.(1750c932f86) kvmclock: add a new function to update env->tsc.(b52baab2) The code provided by the patches was already in the upstreamed version. Change-Id: I3cc11841a6a76ae20887b2e245710199e1ea7f9a Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'qemu/tests')
-rw-r--r--qemu/tests/.gitignore30
-rw-r--r--qemu/tests/Makefile384
-rw-r--r--qemu/tests/ac97-test.c3
-rw-r--r--qemu/tests/acpi-test-data/pc/DSDTbin3028 -> 5587 bytes
-rw-r--r--qemu/tests/acpi-test-data/pc/DSDT.bridge (renamed from qemu/tests/acpi-test-data/pc/SSDT.bridge)bin4345 -> 7446 bytes
-rw-r--r--qemu/tests/acpi-test-data/pc/SSDTbin2486 -> 0 bytes
-rw-r--r--qemu/tests/acpi-test-data/q35/DSDTbin7666 -> 8357 bytes
-rw-r--r--qemu/tests/acpi-test-data/q35/DSDT.bridgebin0 -> 8374 bytes
-rw-r--r--qemu/tests/acpi-test-data/q35/SSDTbin691 -> 0 bytes
-rw-r--r--qemu/tests/acpi-test-data/q35/SSDT.bridgebin708 -> 0 bytes
-rw-r--r--qemu/tests/ahci-test.c293
-rw-r--r--qemu/tests/bios-tables-test.c138
-rw-r--r--qemu/tests/boot-order-test.c6
-rw-r--r--qemu/tests/boot-sector.c118
-rw-r--r--qemu/tests/boot-sector.h26
-rwxr-xr-xqemu/tests/check-block.sh2
-rw-r--r--qemu/tests/check-qdict.c1
-rw-r--r--qemu/tests/check-qfloat.c1
-rw-r--r--qemu/tests/check-qint.c1
-rw-r--r--qemu/tests/check-qjson.c26
-rw-r--r--qemu/tests/check-qlist.c1
-rw-r--r--qemu/tests/check-qom-interface.c1
-rw-r--r--qemu/tests/check-qom-proplist.c237
-rw-r--r--qemu/tests/check-qstring.c1
-rw-r--r--qemu/tests/crypto-tls-x509-helpers.c485
-rw-r--r--qemu/tests/crypto-tls-x509-helpers.h133
-rw-r--r--qemu/tests/device-introspect-test.c124
-rw-r--r--qemu/tests/display-vga-test.c3
-rw-r--r--qemu/tests/drive_del-test.c24
-rw-r--r--qemu/tests/ds1338-test.c79
-rw-r--r--qemu/tests/e1000-test.c3
-rw-r--r--qemu/tests/eepro100-test.c3
-rw-r--r--qemu/tests/endianness-test.c5
-rw-r--r--qemu/tests/es1370-test.c3
-rw-r--r--qemu/tests/fdc-test.c10
-rw-r--r--qemu/tests/fw_cfg-test.c9
-rw-r--r--qemu/tests/guest-debug/test-gdbstub.py176
-rw-r--r--qemu/tests/hd-geo-test.c8
-rw-r--r--qemu/tests/i440fx-test.c10
-rw-r--r--qemu/tests/i82801b11-test.c3
-rw-r--r--qemu/tests/ide-test.c275
-rwxr-xr-xqemu/tests/image-fuzzer/runner.py14
-rw-r--r--qemu/tests/intel-hda-test.c3
-rw-r--r--qemu/tests/io-channel-helpers.c248
-rw-r--r--qemu/tests/io-channel-helpers.h42
-rw-r--r--qemu/tests/ioh3420-test.c3
-rw-r--r--qemu/tests/ipmi-bt-test.c433
-rw-r--r--qemu/tests/ipmi-kcs-test.c293
-rw-r--r--qemu/tests/ipoctal232-test.c3
-rw-r--r--qemu/tests/ivshmem-test.c518
-rw-r--r--qemu/tests/libqos/ahci.c180
-rw-r--r--qemu/tests/libqos/ahci.h69
-rw-r--r--qemu/tests/libqos/fw_cfg.c1
-rw-r--r--qemu/tests/libqos/fw_cfg.h2
-rw-r--r--qemu/tests/libqos/i2c-imx.c208
-rw-r--r--qemu/tests/libqos/i2c-omap.c3
-rw-r--r--qemu/tests/libqos/i2c.c1
-rw-r--r--qemu/tests/libqos/i2c.h4
-rw-r--r--qemu/tests/libqos/libqos-pc.c1
-rw-r--r--qemu/tests/libqos/libqos.c60
-rw-r--r--qemu/tests/libqos/libqos.h2
-rw-r--r--qemu/tests/libqos/malloc-generic.c1
-rw-r--r--qemu/tests/libqos/malloc-pc.c4
-rw-r--r--qemu/tests/libqos/malloc.c7
-rw-r--r--qemu/tests/libqos/malloc.h2
-rw-r--r--qemu/tests/libqos/pci-pc.c9
-rw-r--r--qemu/tests/libqos/pci.c3
-rw-r--r--qemu/tests/libqos/pci.h1
-rw-r--r--qemu/tests/libqos/usb.c3
-rw-r--r--qemu/tests/libqos/virtio-mmio.c2
-rw-r--r--qemu/tests/libqos/virtio-pci.c2
-rw-r--r--qemu/tests/libqos/virtio.c1
-rw-r--r--qemu/tests/libqtest.c144
-rw-r--r--qemu/tests/libqtest.h53
-rw-r--r--qemu/tests/m48t59-test.c5
-rw-r--r--qemu/tests/ne2000-test.c3
-rw-r--r--qemu/tests/nvme-test.c3
-rw-r--r--qemu/tests/pc-cpu-test.c3
-rw-r--r--qemu/tests/pcnet-test.c3
-rw-r--r--qemu/tests/pkix_asn1_tab.c1105
-rw-r--r--qemu/tests/pvpanic-test.c3
-rw-r--r--qemu/tests/pxe-test.c68
-rw-r--r--qemu/tests/q35-test.c3
-rw-r--r--qemu/tests/qapi-schema/alternate-any.err1
-rw-r--r--qemu/tests/qapi-schema/alternate-any.exit (renamed from qemu/tests/qapi-schema/data-array-empty.exit)0
-rw-r--r--qemu/tests/qapi-schema/alternate-any.json4
-rw-r--r--qemu/tests/qapi-schema/alternate-any.out (renamed from qemu/tests/qapi-schema/alternate-good.err)0
-rw-r--r--qemu/tests/qapi-schema/alternate-clash.err2
-rw-r--r--qemu/tests/qapi-schema/alternate-clash.json9
-rw-r--r--qemu/tests/qapi-schema/alternate-empty.err1
-rw-r--r--qemu/tests/qapi-schema/alternate-empty.exit (renamed from qemu/tests/qapi-schema/data-array-unknown.exit)0
-rw-r--r--qemu/tests/qapi-schema/alternate-empty.json2
-rw-r--r--qemu/tests/qapi-schema/alternate-empty.out (renamed from qemu/tests/qapi-schema/data-array-empty.out)0
-rw-r--r--qemu/tests/qapi-schema/alternate-good.exit1
-rw-r--r--qemu/tests/qapi-schema/alternate-good.json9
-rw-r--r--qemu/tests/qapi-schema/alternate-good.out6
-rw-r--r--qemu/tests/qapi-schema/alternate-nested.json2
-rw-r--r--qemu/tests/qapi-schema/alternate-unknown.json2
-rw-r--r--qemu/tests/qapi-schema/args-alternate.err1
-rw-r--r--qemu/tests/qapi-schema/args-alternate.exit (renamed from qemu/tests/qapi-schema/data-int.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-alternate.json3
-rw-r--r--qemu/tests/qapi-schema/args-alternate.out (renamed from qemu/tests/qapi-schema/data-array-unknown.out)0
-rw-r--r--qemu/tests/qapi-schema/args-any.err1
-rw-r--r--qemu/tests/qapi-schema/args-any.exit (renamed from qemu/tests/qapi-schema/data-member-array-bad.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-any.json2
-rw-r--r--qemu/tests/qapi-schema/args-any.out (renamed from qemu/tests/qapi-schema/data-int.out)0
-rw-r--r--qemu/tests/qapi-schema/args-array-empty.err (renamed from qemu/tests/qapi-schema/data-array-empty.err)2
-rw-r--r--qemu/tests/qapi-schema/args-array-empty.exit (renamed from qemu/tests/qapi-schema/data-member-unknown.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-array-empty.json (renamed from qemu/tests/qapi-schema/data-array-empty.json)0
-rw-r--r--qemu/tests/qapi-schema/args-array-empty.out (renamed from qemu/tests/qapi-schema/data-member-array-bad.out)0
-rw-r--r--qemu/tests/qapi-schema/args-array-unknown.err1
-rw-r--r--qemu/tests/qapi-schema/args-array-unknown.exit (renamed from qemu/tests/qapi-schema/data-unknown.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-array-unknown.json (renamed from qemu/tests/qapi-schema/data-array-unknown.json)0
-rw-r--r--qemu/tests/qapi-schema/args-array-unknown.out (renamed from qemu/tests/qapi-schema/data-member-array.err)0
-rw-r--r--qemu/tests/qapi-schema/args-int.err1
-rw-r--r--qemu/tests/qapi-schema/args-int.exit (renamed from qemu/tests/qapi-schema/enum-max-member.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-int.json (renamed from qemu/tests/qapi-schema/data-int.json)0
-rw-r--r--qemu/tests/qapi-schema/args-int.out (renamed from qemu/tests/qapi-schema/data-member-unknown.out)0
-rw-r--r--qemu/tests/qapi-schema/args-invalid.err1
-rw-r--r--qemu/tests/qapi-schema/args-invalid.exit (renamed from qemu/tests/qapi-schema/enum-union-clash.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-invalid.json2
-rw-r--r--qemu/tests/qapi-schema/args-invalid.out (renamed from qemu/tests/qapi-schema/data-unknown.out)0
-rw-r--r--qemu/tests/qapi-schema/args-member-array-bad.err (renamed from qemu/tests/qapi-schema/data-member-array-bad.err)2
-rw-r--r--qemu/tests/qapi-schema/args-member-array-bad.exit (renamed from qemu/tests/qapi-schema/event-max.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-member-array-bad.json (renamed from qemu/tests/qapi-schema/data-member-array-bad.json)0
-rw-r--r--qemu/tests/qapi-schema/args-member-array-bad.out (renamed from qemu/tests/qapi-schema/enum-empty.err)0
-rw-r--r--qemu/tests/qapi-schema/args-member-case.err1
-rw-r--r--qemu/tests/qapi-schema/args-member-case.exit (renamed from qemu/tests/qapi-schema/flat-union-base-star.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-member-case.json2
-rw-r--r--qemu/tests/qapi-schema/args-member-case.out (renamed from qemu/tests/qapi-schema/enum-max-member.out)0
-rw-r--r--qemu/tests/qapi-schema/args-member-unknown.err1
-rw-r--r--qemu/tests/qapi-schema/args-member-unknown.exit (renamed from qemu/tests/qapi-schema/flat-union-branch-clash.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-member-unknown.json (renamed from qemu/tests/qapi-schema/data-member-unknown.json)0
-rw-r--r--qemu/tests/qapi-schema/args-member-unknown.out (renamed from qemu/tests/qapi-schema/enum-union-clash.out)0
-rw-r--r--qemu/tests/qapi-schema/args-name-clash.err1
-rw-r--r--qemu/tests/qapi-schema/args-name-clash.exit (renamed from qemu/tests/qapi-schema/nested-struct-returns.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-name-clash.json4
-rw-r--r--qemu/tests/qapi-schema/args-name-clash.out (renamed from qemu/tests/qapi-schema/event-max.out)0
-rw-r--r--qemu/tests/qapi-schema/args-union.err1
-rw-r--r--qemu/tests/qapi-schema/args-union.exit (renamed from qemu/tests/qapi-schema/type-bypass-no-gen.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-union.json4
-rw-r--r--qemu/tests/qapi-schema/args-union.out (renamed from qemu/tests/qapi-schema/flat-union-base-star.out)0
-rw-r--r--qemu/tests/qapi-schema/args-unknown.err1
-rw-r--r--qemu/tests/qapi-schema/args-unknown.exit (renamed from qemu/tests/qapi-schema/union-bad-branch.exit)0
-rw-r--r--qemu/tests/qapi-schema/args-unknown.json (renamed from qemu/tests/qapi-schema/data-unknown.json)0
-rw-r--r--qemu/tests/qapi-schema/args-unknown.out (renamed from qemu/tests/qapi-schema/flat-union-branch-clash.out)0
-rw-r--r--qemu/tests/qapi-schema/base-cycle-direct.err1
-rw-r--r--qemu/tests/qapi-schema/base-cycle-direct.exit (renamed from qemu/tests/qapi-schema/union-max.exit)0
-rw-r--r--qemu/tests/qapi-schema/base-cycle-direct.json2
-rw-r--r--qemu/tests/qapi-schema/base-cycle-direct.out (renamed from qemu/tests/qapi-schema/flat-union-reverse-define.err)0
-rw-r--r--qemu/tests/qapi-schema/base-cycle-indirect.err1
-rw-r--r--qemu/tests/qapi-schema/base-cycle-indirect.exit1
-rw-r--r--qemu/tests/qapi-schema/base-cycle-indirect.json3
-rw-r--r--qemu/tests/qapi-schema/base-cycle-indirect.out (renamed from qemu/tests/qapi-schema/nested-struct-returns.out)0
-rw-r--r--qemu/tests/qapi-schema/command-int.json3
-rw-r--r--qemu/tests/qapi-schema/comments.out7
-rw-r--r--qemu/tests/qapi-schema/data-array-unknown.err1
-rw-r--r--qemu/tests/qapi-schema/data-int.err1
-rw-r--r--qemu/tests/qapi-schema/data-member-array.exit1
-rw-r--r--qemu/tests/qapi-schema/data-member-array.json4
-rw-r--r--qemu/tests/qapi-schema/data-member-array.out5
-rw-r--r--qemu/tests/qapi-schema/data-member-unknown.err1
-rw-r--r--qemu/tests/qapi-schema/data-unknown.err1
-rw-r--r--qemu/tests/qapi-schema/duplicate-key.err2
-rw-r--r--qemu/tests/qapi-schema/duplicate-key.json1
-rw-r--r--qemu/tests/qapi-schema/empty.out6
-rw-r--r--qemu/tests/qapi-schema/enum-bad-prefix.err1
-rw-r--r--qemu/tests/qapi-schema/enum-bad-prefix.exit1
-rw-r--r--qemu/tests/qapi-schema/enum-bad-prefix.json2
-rw-r--r--qemu/tests/qapi-schema/enum-bad-prefix.out (renamed from qemu/tests/qapi-schema/returns-int.err)0
-rw-r--r--qemu/tests/qapi-schema/enum-clash-member.err2
-rw-r--r--qemu/tests/qapi-schema/enum-clash-member.json2
-rw-r--r--qemu/tests/qapi-schema/enum-empty.exit1
-rw-r--r--qemu/tests/qapi-schema/enum-empty.json2
-rw-r--r--qemu/tests/qapi-schema/enum-empty.out3
-rw-r--r--qemu/tests/qapi-schema/enum-max-member.err1
-rw-r--r--qemu/tests/qapi-schema/enum-max-member.json3
-rw-r--r--qemu/tests/qapi-schema/enum-member-case.err1
-rw-r--r--qemu/tests/qapi-schema/enum-member-case.exit1
-rw-r--r--qemu/tests/qapi-schema/enum-member-case.json3
-rw-r--r--qemu/tests/qapi-schema/enum-member-case.out (renamed from qemu/tests/qapi-schema/type-bypass-no-gen.out)0
-rw-r--r--qemu/tests/qapi-schema/enum-union-clash.err1
-rw-r--r--qemu/tests/qapi-schema/event-case.out7
-rw-r--r--qemu/tests/qapi-schema/event-max.err1
-rw-r--r--qemu/tests/qapi-schema/event-max.json2
-rw-r--r--qemu/tests/qapi-schema/flat-union-bad-base.err2
-rw-r--r--qemu/tests/qapi-schema/flat-union-bad-base.json5
-rw-r--r--qemu/tests/qapi-schema/flat-union-base-any.err1
-rw-r--r--qemu/tests/qapi-schema/flat-union-base-any.exit1
-rw-r--r--qemu/tests/qapi-schema/flat-union-base-any.json (renamed from qemu/tests/qapi-schema/flat-union-base-star.json)2
-rw-r--r--qemu/tests/qapi-schema/flat-union-base-any.out (renamed from qemu/tests/qapi-schema/type-bypass.err)0
-rw-r--r--qemu/tests/qapi-schema/flat-union-base-star.err1
-rw-r--r--qemu/tests/qapi-schema/flat-union-base-union.err2
-rw-r--r--qemu/tests/qapi-schema/flat-union-base-union.json5
-rw-r--r--qemu/tests/qapi-schema/flat-union-branch-clash.err1
-rw-r--r--qemu/tests/qapi-schema/flat-union-clash-member.err1
-rw-r--r--qemu/tests/qapi-schema/flat-union-clash-member.exit1
-rw-r--r--qemu/tests/qapi-schema/flat-union-clash-member.json (renamed from qemu/tests/qapi-schema/flat-union-branch-clash.json)3
-rw-r--r--qemu/tests/qapi-schema/flat-union-clash-member.out (renamed from qemu/tests/qapi-schema/union-bad-branch.out)0
-rw-r--r--qemu/tests/qapi-schema/flat-union-empty.err1
-rw-r--r--qemu/tests/qapi-schema/flat-union-empty.exit1
-rw-r--r--qemu/tests/qapi-schema/flat-union-empty.json4
-rw-r--r--qemu/tests/qapi-schema/flat-union-empty.out (renamed from qemu/tests/qapi-schema/union-max.out)0
-rw-r--r--qemu/tests/qapi-schema/flat-union-inline.err2
-rw-r--r--qemu/tests/qapi-schema/flat-union-inline.json4
-rw-r--r--qemu/tests/qapi-schema/flat-union-no-base.err2
-rw-r--r--qemu/tests/qapi-schema/flat-union-reverse-define.exit1
-rw-r--r--qemu/tests/qapi-schema/flat-union-reverse-define.json17
-rw-r--r--qemu/tests/qapi-schema/flat-union-reverse-define.out9
-rw-r--r--qemu/tests/qapi-schema/ident-with-escape.out10
-rw-r--r--qemu/tests/qapi-schema/include-non-file.err2
-rw-r--r--qemu/tests/qapi-schema/include-non-file.json2
-rw-r--r--qemu/tests/qapi-schema/include-relpath.out7
-rw-r--r--qemu/tests/qapi-schema/include-repetition.out7
-rw-r--r--qemu/tests/qapi-schema/include-simple.out7
-rw-r--r--qemu/tests/qapi-schema/indented-expr.out10
-rw-r--r--qemu/tests/qapi-schema/leading-comma-list.err1
-rw-r--r--qemu/tests/qapi-schema/leading-comma-list.exit1
-rw-r--r--qemu/tests/qapi-schema/leading-comma-list.json2
-rw-r--r--qemu/tests/qapi-schema/leading-comma-list.out0
-rw-r--r--qemu/tests/qapi-schema/leading-comma-object.err1
-rw-r--r--qemu/tests/qapi-schema/leading-comma-object.exit1
-rw-r--r--qemu/tests/qapi-schema/leading-comma-object.json2
-rw-r--r--qemu/tests/qapi-schema/leading-comma-object.out0
-rw-r--r--qemu/tests/qapi-schema/nested-struct-data.json3
-rw-r--r--qemu/tests/qapi-schema/nested-struct-returns.err1
-rw-r--r--qemu/tests/qapi-schema/nested-struct-returns.json3
-rw-r--r--qemu/tests/qapi-schema/qapi-schema-test.json100
-rw-r--r--qemu/tests/qapi-schema/qapi-schema-test.out266
-rw-r--r--qemu/tests/qapi-schema/reserved-command-q.err1
-rw-r--r--qemu/tests/qapi-schema/reserved-command-q.exit1
-rw-r--r--qemu/tests/qapi-schema/reserved-command-q.json5
-rw-r--r--qemu/tests/qapi-schema/reserved-command-q.out0
-rw-r--r--qemu/tests/qapi-schema/reserved-enum-q.err1
-rw-r--r--qemu/tests/qapi-schema/reserved-enum-q.exit1
-rw-r--r--qemu/tests/qapi-schema/reserved-enum-q.json4
-rw-r--r--qemu/tests/qapi-schema/reserved-enum-q.out0
-rw-r--r--qemu/tests/qapi-schema/reserved-member-has.err1
-rw-r--r--qemu/tests/qapi-schema/reserved-member-has.exit1
-rw-r--r--qemu/tests/qapi-schema/reserved-member-has.json5
-rw-r--r--qemu/tests/qapi-schema/reserved-member-has.out0
-rw-r--r--qemu/tests/qapi-schema/reserved-member-q.err1
-rw-r--r--qemu/tests/qapi-schema/reserved-member-q.exit1
-rw-r--r--qemu/tests/qapi-schema/reserved-member-q.json4
-rw-r--r--qemu/tests/qapi-schema/reserved-member-q.out0
-rw-r--r--qemu/tests/qapi-schema/reserved-member-u.err1
-rw-r--r--qemu/tests/qapi-schema/reserved-member-u.exit1
-rw-r--r--qemu/tests/qapi-schema/reserved-member-u.json7
-rw-r--r--qemu/tests/qapi-schema/reserved-member-u.out0
-rw-r--r--qemu/tests/qapi-schema/reserved-member-underscore.err1
-rw-r--r--qemu/tests/qapi-schema/reserved-member-underscore.exit1
-rw-r--r--qemu/tests/qapi-schema/reserved-member-underscore.json4
-rw-r--r--qemu/tests/qapi-schema/reserved-member-underscore.out0
-rw-r--r--qemu/tests/qapi-schema/reserved-type-kind.err1
-rw-r--r--qemu/tests/qapi-schema/reserved-type-kind.exit1
-rw-r--r--qemu/tests/qapi-schema/reserved-type-kind.json (renamed from qemu/tests/qapi-schema/enum-union-clash.json)2
-rw-r--r--qemu/tests/qapi-schema/reserved-type-kind.out0
-rw-r--r--qemu/tests/qapi-schema/reserved-type-list.err1
-rw-r--r--qemu/tests/qapi-schema/reserved-type-list.exit1
-rw-r--r--qemu/tests/qapi-schema/reserved-type-list.json5
-rw-r--r--qemu/tests/qapi-schema/reserved-type-list.out0
-rw-r--r--qemu/tests/qapi-schema/returns-dict.err1
-rw-r--r--qemu/tests/qapi-schema/returns-dict.exit1
-rw-r--r--qemu/tests/qapi-schema/returns-dict.json2
-rw-r--r--qemu/tests/qapi-schema/returns-dict.out0
-rw-r--r--qemu/tests/qapi-schema/returns-int.exit1
-rw-r--r--qemu/tests/qapi-schema/returns-int.json3
-rw-r--r--qemu/tests/qapi-schema/returns-int.out3
-rw-r--r--qemu/tests/qapi-schema/returns-whitelist.err2
-rw-r--r--qemu/tests/qapi-schema/struct-base-clash-deep.err2
-rw-r--r--qemu/tests/qapi-schema/struct-base-clash-deep.json5
-rw-r--r--qemu/tests/qapi-schema/struct-base-clash.err2
-rw-r--r--qemu/tests/qapi-schema/struct-base-clash.json3
-rw-r--r--qemu/tests/qapi-schema/struct-data-invalid.err1
-rw-r--r--qemu/tests/qapi-schema/struct-data-invalid.exit1
-rw-r--r--qemu/tests/qapi-schema/struct-data-invalid.json2
-rw-r--r--qemu/tests/qapi-schema/struct-data-invalid.out0
-rw-r--r--qemu/tests/qapi-schema/struct-member-invalid.err1
-rw-r--r--qemu/tests/qapi-schema/struct-member-invalid.exit1
-rw-r--r--qemu/tests/qapi-schema/struct-member-invalid.json2
-rw-r--r--qemu/tests/qapi-schema/struct-member-invalid.out0
-rw-r--r--qemu/tests/qapi-schema/test-qapi.py47
-rw-r--r--qemu/tests/qapi-schema/type-bypass-no-gen.err1
-rw-r--r--qemu/tests/qapi-schema/type-bypass-no-gen.json2
-rw-r--r--qemu/tests/qapi-schema/type-bypass.exit1
-rw-r--r--qemu/tests/qapi-schema/type-bypass.json2
-rw-r--r--qemu/tests/qapi-schema/type-bypass.out3
-rw-r--r--qemu/tests/qapi-schema/union-bad-branch.err1
-rw-r--r--qemu/tests/qapi-schema/union-bad-branch.json8
-rw-r--r--qemu/tests/qapi-schema/union-base-no-discriminator.err2
-rw-r--r--qemu/tests/qapi-schema/union-branch-case.err1
-rw-r--r--qemu/tests/qapi-schema/union-branch-case.exit1
-rw-r--r--qemu/tests/qapi-schema/union-branch-case.json2
-rw-r--r--qemu/tests/qapi-schema/union-branch-case.out0
-rw-r--r--qemu/tests/qapi-schema/union-clash-branches.err1
-rw-r--r--qemu/tests/qapi-schema/union-clash-branches.exit1
-rw-r--r--qemu/tests/qapi-schema/union-clash-branches.json5
-rw-r--r--qemu/tests/qapi-schema/union-clash-branches.out0
-rw-r--r--qemu/tests/qapi-schema/union-empty.err1
-rw-r--r--qemu/tests/qapi-schema/union-empty.exit1
-rw-r--r--qemu/tests/qapi-schema/union-empty.json2
-rw-r--r--qemu/tests/qapi-schema/union-empty.out0
-rw-r--r--qemu/tests/qapi-schema/union-invalid-base.err2
-rw-r--r--qemu/tests/qapi-schema/union-max.err1
-rw-r--r--qemu/tests/qapi-schema/union-max.json3
-rwxr-xr-xqemu/tests/qemu-iotests/0011
-rwxr-xr-xqemu/tests/qemu-iotests/0021
-rwxr-xr-xqemu/tests/qemu-iotests/0031
-rwxr-xr-xqemu/tests/qemu-iotests/0041
-rwxr-xr-xqemu/tests/qemu-iotests/0051
-rwxr-xr-xqemu/tests/qemu-iotests/0071
-rwxr-xr-xqemu/tests/qemu-iotests/0081
-rwxr-xr-xqemu/tests/qemu-iotests/0091
-rwxr-xr-xqemu/tests/qemu-iotests/0101
-rwxr-xr-xqemu/tests/qemu-iotests/0111
-rwxr-xr-xqemu/tests/qemu-iotests/0121
-rwxr-xr-xqemu/tests/qemu-iotests/0131
-rwxr-xr-xqemu/tests/qemu-iotests/0141
-rwxr-xr-xqemu/tests/qemu-iotests/0151
-rwxr-xr-xqemu/tests/qemu-iotests/0171
-rw-r--r--qemu/tests/qemu-iotests/017.out2
-rwxr-xr-xqemu/tests/qemu-iotests/0189
-rw-r--r--qemu/tests/qemu-iotests/018.out2
-rwxr-xr-xqemu/tests/qemu-iotests/01914
-rw-r--r--qemu/tests/qemu-iotests/019.out4
-rwxr-xr-xqemu/tests/qemu-iotests/0208
-rw-r--r--qemu/tests/qemu-iotests/020.out4
-rwxr-xr-xqemu/tests/qemu-iotests/0211
-rwxr-xr-xqemu/tests/qemu-iotests/0221
-rwxr-xr-xqemu/tests/qemu-iotests/0231
-rwxr-xr-xqemu/tests/qemu-iotests/02411
-rw-r--r--qemu/tests/qemu-iotests/024.out6
-rwxr-xr-xqemu/tests/qemu-iotests/0251
-rwxr-xr-xqemu/tests/qemu-iotests/02619
-rw-r--r--qemu/tests/qemu-iotests/026.out80
-rw-r--r--qemu/tests/qemu-iotests/026.out.nocache222
-rwxr-xr-xqemu/tests/qemu-iotests/0271
-rwxr-xr-xqemu/tests/qemu-iotests/02812
-rw-r--r--qemu/tests/qemu-iotests/028.out9
-rwxr-xr-xqemu/tests/qemu-iotests/0291
-rwxr-xr-xqemu/tests/qemu-iotests/03026
-rw-r--r--qemu/tests/qemu-iotests/030.out4
-rwxr-xr-xqemu/tests/qemu-iotests/0311
-rw-r--r--qemu/tests/qemu-iotests/031.out17
-rwxr-xr-xqemu/tests/qemu-iotests/0321
-rwxr-xr-xqemu/tests/qemu-iotests/0339
-rw-r--r--qemu/tests/qemu-iotests/033.out82
-rwxr-xr-xqemu/tests/qemu-iotests/0347
-rw-r--r--qemu/tests/qemu-iotests/034.out4
-rwxr-xr-xqemu/tests/qemu-iotests/0351
-rwxr-xr-xqemu/tests/qemu-iotests/0363
-rw-r--r--qemu/tests/qemu-iotests/036.out21
-rwxr-xr-xqemu/tests/qemu-iotests/0376
-rw-r--r--qemu/tests/qemu-iotests/037.out4
-rwxr-xr-xqemu/tests/qemu-iotests/0386
-rw-r--r--qemu/tests/qemu-iotests/038.out4
-rwxr-xr-xqemu/tests/qemu-iotests/03947
-rw-r--r--qemu/tests/qemu-iotests/039.out46
-rwxr-xr-xqemu/tests/qemu-iotests/04030
-rw-r--r--qemu/tests/qemu-iotests/040.out4
-rwxr-xr-xqemu/tests/qemu-iotests/041128
-rw-r--r--qemu/tests/qemu-iotests/041.out4
-rwxr-xr-xqemu/tests/qemu-iotests/0421
-rwxr-xr-xqemu/tests/qemu-iotests/0431
-rw-r--r--qemu/tests/qemu-iotests/043.out14
-rwxr-xr-xqemu/tests/qemu-iotests/0461
-rw-r--r--qemu/tests/qemu-iotests/046.out2
-rwxr-xr-xqemu/tests/qemu-iotests/0471
-rwxr-xr-xqemu/tests/qemu-iotests/0491
-rw-r--r--qemu/tests/qemu-iotests/049.out39
-rwxr-xr-xqemu/tests/qemu-iotests/05010
-rw-r--r--qemu/tests/qemu-iotests/050.out6
-rwxr-xr-xqemu/tests/qemu-iotests/051147
-rw-r--r--qemu/tests/qemu-iotests/051.out249
-rw-r--r--qemu/tests/qemu-iotests/051.pc.out525
-rwxr-xr-xqemu/tests/qemu-iotests/0521
-rwxr-xr-xqemu/tests/qemu-iotests/0531
-rwxr-xr-xqemu/tests/qemu-iotests/0541
-rwxr-xr-xqemu/tests/qemu-iotests/05519
-rwxr-xr-xqemu/tests/qemu-iotests/05625
-rw-r--r--qemu/tests/qemu-iotests/056.out4
-rwxr-xr-xqemu/tests/qemu-iotests/05813
-rwxr-xr-xqemu/tests/qemu-iotests/05911
-rw-r--r--qemu/tests/qemu-iotests/059.out49
-rwxr-xr-xqemu/tests/qemu-iotests/0601
-rw-r--r--qemu/tests/qemu-iotests/060.out2
-rwxr-xr-xqemu/tests/qemu-iotests/0617
-rw-r--r--qemu/tests/qemu-iotests/061.out69
-rwxr-xr-xqemu/tests/qemu-iotests/0621
-rwxr-xr-xqemu/tests/qemu-iotests/0631
-rwxr-xr-xqemu/tests/qemu-iotests/0641
-rwxr-xr-xqemu/tests/qemu-iotests/0661
-rwxr-xr-xqemu/tests/qemu-iotests/06721
-rw-r--r--qemu/tests/qemu-iotests/067.out419
-rwxr-xr-xqemu/tests/qemu-iotests/06815
-rwxr-xr-xqemu/tests/qemu-iotests/0691
-rw-r--r--qemu/tests/qemu-iotests/069.out4
-rwxr-xr-xqemu/tests/qemu-iotests/0701
-rw-r--r--qemu/tests/qemu-iotests/070.out5
-rwxr-xr-xqemu/tests/qemu-iotests/07155
-rw-r--r--qemu/tests/qemu-iotests/071.out16
-rwxr-xr-xqemu/tests/qemu-iotests/0721
-rwxr-xr-xqemu/tests/qemu-iotests/0731
-rw-r--r--qemu/tests/qemu-iotests/073.out2
-rwxr-xr-xqemu/tests/qemu-iotests/0751
-rw-r--r--qemu/tests/qemu-iotests/075.out14
-rwxr-xr-xqemu/tests/qemu-iotests/0761
-rw-r--r--qemu/tests/qemu-iotests/076.out6
-rwxr-xr-xqemu/tests/qemu-iotests/07725
-rwxr-xr-xqemu/tests/qemu-iotests/0781
-rw-r--r--qemu/tests/qemu-iotests/078.out12
-rwxr-xr-xqemu/tests/qemu-iotests/0791
-rw-r--r--qemu/tests/qemu-iotests/079.out18
-rwxr-xr-xqemu/tests/qemu-iotests/0801
-rw-r--r--qemu/tests/qemu-iotests/080.out36
-rwxr-xr-xqemu/tests/qemu-iotests/08122
-rw-r--r--qemu/tests/qemu-iotests/081.out7
-rwxr-xr-xqemu/tests/qemu-iotests/0821
-rw-r--r--qemu/tests/qemu-iotests/082.out4
-rwxr-xr-xqemu/tests/qemu-iotests/08314
-rw-r--r--qemu/tests/qemu-iotests/083.out44
-rwxr-xr-xqemu/tests/qemu-iotests/0841
-rwxr-xr-xqemu/tests/qemu-iotests/085120
-rw-r--r--qemu/tests/qemu-iotests/085.out72
-rwxr-xr-xqemu/tests/qemu-iotests/0863
-rwxr-xr-xqemu/tests/qemu-iotests/0876
-rw-r--r--qemu/tests/qemu-iotests/087.out44
-rwxr-xr-xqemu/tests/qemu-iotests/0881
-rw-r--r--qemu/tests/qemu-iotests/088.out12
-rwxr-xr-xqemu/tests/qemu-iotests/0891
-rwxr-xr-xqemu/tests/qemu-iotests/0901
-rwxr-xr-xqemu/tests/qemu-iotests/0921
-rw-r--r--qemu/tests/qemu-iotests/092.out24
-rwxr-xr-xqemu/tests/qemu-iotests/09365
-rw-r--r--qemu/tests/qemu-iotests/093.out4
-rwxr-xr-xqemu/tests/qemu-iotests/0949
-rwxr-xr-xqemu/tests/qemu-iotests/09510
-rw-r--r--qemu/tests/qemu-iotests/095.out8
-rw-r--r--qemu/tests/qemu-iotests/09669
-rw-r--r--qemu/tests/qemu-iotests/096.out5
-rwxr-xr-xqemu/tests/qemu-iotests/0971
-rw-r--r--qemu/tests/qemu-iotests/097.out16
-rwxr-xr-xqemu/tests/qemu-iotests/0981
-rw-r--r--qemu/tests/qemu-iotests/098.out8
-rwxr-xr-xqemu/tests/qemu-iotests/0991
-rwxr-xr-xqemu/tests/qemu-iotests/1001
-rwxr-xr-xqemu/tests/qemu-iotests/1011
-rwxr-xr-xqemu/tests/qemu-iotests/1021
-rwxr-xr-xqemu/tests/qemu-iotests/1031
-rw-r--r--qemu/tests/qemu-iotests/103.out8
-rwxr-xr-xqemu/tests/qemu-iotests/1041
-rwxr-xr-xqemu/tests/qemu-iotests/1051
-rwxr-xr-xqemu/tests/qemu-iotests/1071
-rwxr-xr-xqemu/tests/qemu-iotests/1081
-rwxr-xr-xqemu/tests/qemu-iotests/1091
-rw-r--r--qemu/tests/qemu-iotests/109.out38
-rwxr-xr-xqemu/tests/qemu-iotests/1101
-rw-r--r--qemu/tests/qemu-iotests/110.out9
-rwxr-xr-xqemu/tests/qemu-iotests/1111
-rwxr-xr-xqemu/tests/qemu-iotests/112110
-rw-r--r--qemu/tests/qemu-iotests/112.out75
-rwxr-xr-xqemu/tests/qemu-iotests/1131
-rwxr-xr-xqemu/tests/qemu-iotests/1141
-rw-r--r--qemu/tests/qemu-iotests/114.out4
-rwxr-xr-xqemu/tests/qemu-iotests/1151
-rw-r--r--qemu/tests/qemu-iotests/115.out2
-rwxr-xr-xqemu/tests/qemu-iotests/1161
-rw-r--r--qemu/tests/qemu-iotests/116.out14
-rwxr-xr-xqemu/tests/qemu-iotests/11785
-rw-r--r--qemu/tests/qemu-iotests/117.out14
-rwxr-xr-xqemu/tests/qemu-iotests/118677
-rw-r--r--qemu/tests/qemu-iotests/118.out5
-rwxr-xr-xqemu/tests/qemu-iotests/1193
-rwxr-xr-xqemu/tests/qemu-iotests/1203
-rwxr-xr-xqemu/tests/qemu-iotests/1211
-rw-r--r--qemu/tests/qemu-iotests/121.out4
-rwxr-xr-xqemu/tests/qemu-iotests/1221
-rw-r--r--qemu/tests/qemu-iotests/122.out12
-rwxr-xr-xqemu/tests/qemu-iotests/1231
-rw-r--r--qemu/tests/qemu-iotests/124316
-rw-r--r--qemu/tests/qemu-iotests/124.out4
-rwxr-xr-xqemu/tests/qemu-iotests/12810
-rwxr-xr-xqemu/tests/qemu-iotests/1309
-rw-r--r--qemu/tests/qemu-iotests/130.out8
-rwxr-xr-xqemu/tests/qemu-iotests/1311
-rw-r--r--qemu/tests/qemu-iotests/131.out2
-rwxr-xr-xqemu/tests/qemu-iotests/13389
-rw-r--r--qemu/tests/qemu-iotests/133.out22
-rwxr-xr-xqemu/tests/qemu-iotests/1341
-rw-r--r--qemu/tests/qemu-iotests/134.out18
-rwxr-xr-xqemu/tests/qemu-iotests/1351
-rw-r--r--qemu/tests/qemu-iotests/136349
-rw-r--r--qemu/tests/qemu-iotests/136.out5
-rwxr-xr-xqemu/tests/qemu-iotests/137144
-rw-r--r--qemu/tests/qemu-iotests/137.out46
-rwxr-xr-xqemu/tests/qemu-iotests/13872
-rw-r--r--qemu/tests/qemu-iotests/138.out9
-rw-r--r--qemu/tests/qemu-iotests/139416
-rw-r--r--qemu/tests/qemu-iotests/139.out5
-rwxr-xr-xqemu/tests/qemu-iotests/14095
-rw-r--r--qemu/tests/qemu-iotests/140.out15
-rwxr-xr-xqemu/tests/qemu-iotests/141185
-rw-r--r--qemu/tests/qemu-iotests/141.out59
-rwxr-xr-xqemu/tests/qemu-iotests/142358
-rw-r--r--qemu/tests/qemu-iotests/142.out750
-rwxr-xr-xqemu/tests/qemu-iotests/14372
-rw-r--r--qemu/tests/qemu-iotests/143.out7
-rwxr-xr-xqemu/tests/qemu-iotests/144114
-rw-r--r--qemu/tests/qemu-iotests/144.out24
-rwxr-xr-xqemu/tests/qemu-iotests/14551
-rw-r--r--qemu/tests/qemu-iotests/145.out5
-rwxr-xr-xqemu/tests/qemu-iotests/146165
-rw-r--r--qemu/tests/qemu-iotests/146.out70
-rw-r--r--qemu/tests/qemu-iotests/148140
-rw-r--r--qemu/tests/qemu-iotests/148.out5
-rwxr-xr-xqemu/tests/qemu-iotests/149519
-rw-r--r--qemu/tests/qemu-iotests/149.out1880
-rwxr-xr-xqemu/tests/qemu-iotests/15073
-rw-r--r--qemu/tests/qemu-iotests/150.out11
-rw-r--r--qemu/tests/qemu-iotests/15262
-rw-r--r--qemu/tests/qemu-iotests/152.out5
-rwxr-xr-xqemu/tests/qemu-iotests/check34
-rw-r--r--qemu/tests/qemu-iotests/common11
-rw-r--r--qemu/tests/qemu-iotests/common.config63
-rw-r--r--qemu/tests/qemu-iotests/common.filter121
-rw-r--r--qemu/tests/qemu-iotests/common.qemu31
-rw-r--r--qemu/tests/qemu-iotests/common.rc76
-rw-r--r--qemu/tests/qemu-iotests/group19
-rw-r--r--qemu/tests/qemu-iotests/iotests.py141
-rwxr-xr-xqemu/tests/qemu-iotests/qed.py2
-rw-r--r--qemu/tests/qemu-iotests/sample_images/d2v-zerofilled.vhd.bz2bin0 -> 1021 bytes
-rw-r--r--qemu/tests/qemu-iotests/sample_images/hyperv2012r2-dynamic.vhd.bz2bin0 -> 214 bytes
-rw-r--r--qemu/tests/qemu-iotests/sample_images/virtualpc-dynamic.vhd.bz2bin0 -> 212 bytes
-rw-r--r--qemu/tests/qemu-iotests/socket_scm_helper.c8
-rw-r--r--qemu/tests/qom-test.c25
-rw-r--r--qemu/tests/rcutorture.c5
-rw-r--r--qemu/tests/rtc-test.c5
-rw-r--r--qemu/tests/rtl8139-test.c5
-rw-r--r--qemu/tests/spapr-phb-test.c1
-rw-r--r--qemu/tests/tcg/linux-test.c1
-rw-r--r--qemu/tests/tcg/test-i386-fprem.c4
-rw-r--r--qemu/tests/tcg/testthread.c1
-rw-r--r--qemu/tests/tco-test.c4
-rw-r--r--qemu/tests/test-aio.c89
-rw-r--r--qemu/tests/test-base64.c110
-rw-r--r--qemu/tests/test-bitops.c3
-rw-r--r--qemu/tests/test-blockjob-txn.c251
-rw-r--r--qemu/tests/test-coroutine.c5
-rw-r--r--qemu/tests/test-crypto-afsplit.c194
-rw-r--r--qemu/tests/test-crypto-block.c363
-rw-r--r--qemu/tests/test-crypto-cipher.c305
-rw-r--r--qemu/tests/test-crypto-hash.c6
-rw-r--r--qemu/tests/test-crypto-ivgen.c174
-rw-r--r--qemu/tests/test-crypto-pbkdf.c393
-rw-r--r--qemu/tests/test-crypto-secret.c455
-rw-r--r--qemu/tests/test-crypto-tlscredsx509.c730
-rw-r--r--qemu/tests/test-crypto-tlssession.c534
-rw-r--r--qemu/tests/test-crypto-xts.c423
-rw-r--r--qemu/tests/test-cutils.c1352
-rw-r--r--qemu/tests/test-filter-mirror.c93
-rw-r--r--qemu/tests/test-filter-redirector.c221
-rw-r--r--qemu/tests/test-hbitmap.c10
-rw-r--r--qemu/tests/test-int128.c3
-rw-r--r--qemu/tests/test-io-channel-buffer.c51
-rw-r--r--qemu/tests/test-io-channel-command.c131
-rw-r--r--qemu/tests/test-io-channel-file.c123
-rw-r--r--qemu/tests/test-io-channel-socket.c568
-rw-r--r--qemu/tests/test-io-channel-tls.c340
-rw-r--r--qemu/tests/test-io-task.c270
-rw-r--r--qemu/tests/test-iov.c1
-rw-r--r--qemu/tests/test-logging.c141
-rw-r--r--qemu/tests/test-mul64.c3
-rw-r--r--qemu/tests/test-netfilter.c201
-rw-r--r--qemu/tests/test-opts-visitor.c14
-rw-r--r--qemu/tests/test-qdev-global-props.c20
-rw-r--r--qemu/tests/test-qemu-opts.c2
-rw-r--r--qemu/tests/test-qga.c869
-rw-r--r--qemu/tests/test-qmp-commands.c43
-rw-r--r--qemu/tests/test-qmp-event.c12
-rw-r--r--qemu/tests/test-qmp-input-strict.c162
-rw-r--r--qemu/tests/test-qmp-input-visitor.c472
-rw-r--r--qemu/tests/test-qmp-output-visitor.c289
-rw-r--r--qemu/tests/test-rcu-list.c6
-rw-r--r--qemu/tests/test-rfifolock.c1
-rw-r--r--qemu/tests/test-string-input-visitor.c37
-rw-r--r--qemu/tests/test-string-output-visitor.c42
-rw-r--r--qemu/tests/test-thread-pool.c6
-rw-r--r--qemu/tests/test-throttle.c118
-rw-r--r--qemu/tests/test-timed-average.c90
-rw-r--r--qemu/tests/test-visitor-serialization.c148
-rw-r--r--qemu/tests/test-vmstate.c3
-rw-r--r--qemu/tests/test-write-threshold.c2
-rw-r--r--qemu/tests/test-x86-cpuid.c1
-rw-r--r--qemu/tests/test-xbzrle.c9
-rw-r--r--qemu/tests/tmp105-test.c1
-rw-r--r--qemu/tests/tpci200-test.c3
-rw-r--r--qemu/tests/usb-hcd-ehci-test.c4
-rw-r--r--qemu/tests/usb-hcd-ohci-test.c3
-rw-r--r--qemu/tests/usb-hcd-uhci-test.c3
-rw-r--r--qemu/tests/usb-hcd-xhci-test.c3
-rw-r--r--qemu/tests/vhost-user-bridge.c1418
-rw-r--r--qemu/tests/vhost-user-test.c576
-rw-r--r--qemu/tests/virtio-9p-test.c4
-rw-r--r--qemu/tests/virtio-balloon-test.c3
-rw-r--r--qemu/tests/virtio-blk-test.c5
-rw-r--r--qemu/tests/virtio-console-test.c3
-rw-r--r--qemu/tests/virtio-net-test.c240
-rw-r--r--qemu/tests/virtio-rng-test.c3
-rw-r--r--qemu/tests/virtio-scsi-test.c104
-rw-r--r--qemu/tests/virtio-serial-test.c3
-rw-r--r--qemu/tests/vmxnet3-test.c3
-rw-r--r--qemu/tests/wdt_ib700-test.c3
612 files changed, 27067 insertions, 3296 deletions
diff --git a/qemu/tests/.gitignore b/qemu/tests/.gitignore
index ccc92e476..9eed22988 100644
--- a/qemu/tests/.gitignore
+++ b/qemu/tests/.gitignore
@@ -8,14 +8,38 @@ check-qom-interface
check-qom-proplist
rcutorture
test-aio
+test-base64
test-bitops
+test-blockjob-txn
test-coroutine
+test-crypto-afsplit
+test-crypto-block
test-crypto-cipher
test-crypto-hash
+test-crypto-ivgen
+test-crypto-pbkdf
+test-crypto-secret
+test-crypto-tlscredsx509
+test-crypto-tlscredsx509-work/
+test-crypto-tlscredsx509-certs/
+test-crypto-tlssession
+test-crypto-tlssession-work/
+test-crypto-tlssession-client/
+test-crypto-tlssession-server/
+test-crypto-xts
test-cutils
test-hbitmap
test-int128
test-iov
+test-io-channel-buffer
+test-io-channel-command
+test-io-channel-command.fifo
+test-io-channel-file
+test-io-channel-file.txt
+test-io-channel-socket
+test-io-channel-tls
+test-io-task
+test-logging
test-mul64
test-opts-visitor
test-qapi-event.[ch]
@@ -23,11 +47,13 @@ test-qapi-types.[ch]
test-qapi-visit.[ch]
test-qdev-global-props
test-qemu-opts
+test-qga
test-qmp-commands
test-qmp-commands.h
test-qmp-event
test-qmp-input-strict
test-qmp-input-visitor
+test-qmp-introspect.[ch]
test-qmp-marshal.c
test-qmp-output-visitor
test-rcu-list
@@ -36,10 +62,14 @@ test-string-input-visitor
test-string-output-visitor
test-thread-pool
test-throttle
+test-timed-average
test-visitor-serialization
test-vmstate
test-write-threshold
test-x86-cpuid
test-xbzrle
+test-netfilter
+test-filter-mirror
+test-filter-redirector
*-test
qapi-schema/*.test.*
diff --git a/qemu/tests/Makefile b/qemu/tests/Makefile
index 749458224..9194f1850 100644
--- a/qemu/tests/Makefile
+++ b/qemu/tests/Makefile
@@ -1,5 +1,7 @@
export SRC_PATH
+qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py
+
# Get the list of all supported sysemu targets
SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \
$(wildcard $(SRC_PATH)/default-configs/*-softmmu.mak)))
@@ -45,6 +47,8 @@ check-unit-y += tests/test-thread-pool$(EXESUF)
gcov-files-test-thread-pool-y = thread-pool.c
gcov-files-test-hbitmap-y = util/hbitmap.c
check-unit-y += tests/test-hbitmap$(EXESUF)
+gcov-files-test-hbitmap-y = blockjob.c
+check-unit-y += tests/test-blockjob-txn$(EXESUF)
check-unit-y += tests/test-x86-cpuid$(EXESUF)
# all code tested by test-x86-cpuid is inside topology.h
gcov-files-test-x86-cpuid-y =
@@ -76,12 +80,36 @@ check-unit-y += tests/test-write-threshold$(EXESUF)
gcov-files-test-write-threshold-y = block/write-threshold.c
check-unit-$(CONFIG_GNUTLS_HASH) += tests/test-crypto-hash$(EXESUF)
check-unit-y += tests/test-crypto-cipher$(EXESUF)
+check-unit-y += tests/test-crypto-secret$(EXESUF)
+check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF)
+check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlssession$(EXESUF)
+ifneq (,$(findstring qemu-ga,$(TOOLS)))
+check-unit-$(CONFIG_LINUX) += tests/test-qga$(EXESUF)
+endif
+check-unit-y += tests/test-timed-average$(EXESUF)
+check-unit-y += tests/test-io-task$(EXESUF)
+check-unit-y += tests/test-io-channel-socket$(EXESUF)
+check-unit-y += tests/test-io-channel-file$(EXESUF)
+check-unit-$(CONFIG_GNUTLS) += tests/test-io-channel-tls$(EXESUF)
+check-unit-y += tests/test-io-channel-command$(EXESUF)
+check-unit-y += tests/test-io-channel-buffer$(EXESUF)
+check-unit-y += tests/test-base64$(EXESUF)
+check-unit-$(if $(CONFIG_NETTLE_KDF),y,$(CONFIG_GCRYPT_KDF)) += tests/test-crypto-pbkdf$(EXESUF)
+check-unit-y += tests/test-crypto-ivgen$(EXESUF)
+check-unit-y += tests/test-crypto-afsplit$(EXESUF)
+check-unit-y += tests/test-crypto-xts$(EXESUF)
+check-unit-y += tests/test-crypto-block$(EXESUF)
+gcov-files-test-logging-y = tests/test-logging.c
+check-unit-y += tests/test-logging$(EXESUF)
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
# All QTests for now are POSIX-only, but the dependencies are
# really in libqtest, not in the testcases themselves.
+check-qtest-generic-y = tests/device-introspect-test$(EXESUF)
+gcov-files-generic-y = qdev-monitor.c qmp.c
+
gcov-files-ipack-y += hw/ipack/ipack.c
check-qtest-ipack-y += tests/ipoctal232-test$(EXESUF)
gcov-files-ipack-y += hw/char/ipoctal232.c
@@ -142,6 +170,8 @@ gcov-files-pci-y += hw/display/virtio-gpu-pci.c
gcov-files-pci-$(CONFIG_VIRTIO_VGA) += hw/display/virtio-vga.c
check-qtest-pci-y += tests/intel-hda-test$(EXESUF)
gcov-files-pci-y += hw/audio/intel-hda.c hw/audio/hda-codec.c
+check-qtest-pci-$(CONFIG_EVENTFD) += tests/ivshmem-test$(EXESUF)
+gcov-files-pci-y += hw/misc/ivshmem.c
check-qtest-i386-y = tests/endianness-test$(EXESUF)
check-qtest-i386-y += tests/fdc-test$(EXESUF)
@@ -152,7 +182,10 @@ check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
gcov-files-i386-y += hw/block/hd-geometry.c
check-qtest-i386-y += tests/boot-order-test$(EXESUF)
check-qtest-i386-y += tests/bios-tables-test$(EXESUF)
+check-qtest-i386-y += tests/pxe-test$(EXESUF)
check-qtest-i386-y += tests/rtc-test$(EXESUF)
+check-qtest-i386-y += tests/ipmi-kcs-test$(EXESUF)
+check-qtest-i386-y += tests/ipmi-bt-test$(EXESUF)
check-qtest-i386-y += tests/i440fx-test$(EXESUF)
check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
check-qtest-i386-y += tests/drive_del-test$(EXESUF)
@@ -184,7 +217,13 @@ gcov-files-i386-y += hw/usb/hcd-xhci.c
check-qtest-i386-y += tests/pc-cpu-test$(EXESUF)
check-qtest-i386-y += tests/q35-test$(EXESUF)
gcov-files-i386-y += hw/pci-host/q35.c
-check-qtest-i386-$(CONFIG_LINUX) += tests/vhost-user-test$(EXESUF)
+check-qtest-i386-$(CONFIG_VHOST_NET_TEST_i386) += tests/vhost-user-test$(EXESUF)
+ifeq ($(CONFIG_VHOST_NET_TEST_i386),)
+check-qtest-x86_64-$(CONFIG_VHOST_NET_TEST_x86_64) += tests/vhost-user-test$(EXESUF)
+endif
+check-qtest-i386-y += tests/test-netfilter$(EXESUF)
+check-qtest-i386-y += tests/test-filter-mirror$(EXESUF)
+check-qtest-i386-y += tests/test-filter-redirector$(EXESUF)
check-qtest-x86_64-y = $(check-qtest-i386-y)
gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
@@ -201,6 +240,7 @@ check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
gcov-files-sparc-y += hw/timer/m48t59.c
gcov-files-sparc64-y += hw/timer/m48t59.c
check-qtest-arm-y = tests/tmp105-test$(EXESUF)
+check-qtest-arm-y = tests/ds1338-test$(EXESUF)
gcov-files-arm-y += hw/misc/tmp105.c
check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
@@ -211,54 +251,135 @@ gcov-files-ppc64-y += ppc64-softmmu/hw/ppc/spapr_pci.c
check-qtest-microblazeel-y = $(check-qtest-microblaze-y)
check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
-# qom-test works for all sysemu architectures:
-$(foreach target,$(SYSEMU_TARGET_LIST), \
- $(if $(findstring tests/qom-test$(EXESUF), $(check-qtest-$(target)-y)),, \
- $(eval check-qtest-$(target)-y += tests/qom-test$(EXESUF))))
-
-check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
- comments.json empty.json enum-empty.json enum-missing-data.json \
- enum-wrong-data.json enum-int-member.json enum-dict-member.json \
- enum-clash-member.json enum-max-member.json enum-union-clash.json \
- enum-bad-name.json funny-char.json indented-expr.json \
- missing-type.json bad-ident.json ident-with-escape.json \
- escape-outside-string.json unknown-escape.json \
- escape-too-short.json escape-too-big.json unicode-str.json \
- double-type.json bad-base.json bad-type-bool.json bad-type-int.json \
- bad-type-dict.json double-data.json unknown-expr-key.json \
- redefined-type.json redefined-command.json redefined-builtin.json \
- redefined-event.json command-int.json bad-data.json event-max.json \
- type-bypass.json type-bypass-no-gen.json type-bypass-bad-gen.json \
- data-array-empty.json data-array-unknown.json data-int.json \
- data-unknown.json data-member-unknown.json data-member-array.json \
- data-member-array-bad.json returns-array-bad.json returns-int.json \
- returns-unknown.json returns-alternate.json returns-whitelist.json \
- missing-colon.json missing-comma-list.json missing-comma-object.json \
- nested-struct-data.json nested-struct-returns.json non-objects.json \
- qapi-schema-test.json quoted-structural-chars.json \
- trailing-comma-list.json trailing-comma-object.json \
- unclosed-list.json unclosed-object.json unclosed-string.json \
- duplicate-key.json union-invalid-base.json union-bad-branch.json \
- union-optional-branch.json union-unknown.json union-max.json \
- flat-union-optional-discriminator.json flat-union-no-base.json \
- flat-union-invalid-discriminator.json flat-union-inline.json \
- flat-union-invalid-branch-key.json flat-union-reverse-define.json \
- flat-union-string-discriminator.json union-base-no-discriminator.json \
- flat-union-bad-discriminator.json flat-union-bad-base.json \
- flat-union-base-star.json \
- flat-union-array-branch.json flat-union-int-branch.json \
- flat-union-base-union.json flat-union-branch-clash.json \
- alternate-nested.json alternate-unknown.json alternate-clash.json \
- alternate-good.json alternate-base.json alternate-array.json \
- alternate-conflict-string.json alternate-conflict-dict.json \
- include-simple.json include-relpath.json include-format-err.json \
- include-non-file.json include-no-file.json include-before-err.json \
- include-nested-err.json include-self-cycle.json include-cycle.json \
- include-repetition.json event-nest-struct.json event-case.json \
- struct-base-clash.json struct-base-clash-deep.json )
+check-qtest-generic-y += tests/qom-test$(EXESUF)
+
+qapi-schema += alternate-any.json
+qapi-schema += alternate-array.json
+qapi-schema += alternate-base.json
+qapi-schema += alternate-clash.json
+qapi-schema += alternate-conflict-dict.json
+qapi-schema += alternate-conflict-string.json
+qapi-schema += alternate-empty.json
+qapi-schema += alternate-nested.json
+qapi-schema += alternate-unknown.json
+qapi-schema += args-alternate.json
+qapi-schema += args-any.json
+qapi-schema += args-array-empty.json
+qapi-schema += args-array-unknown.json
+qapi-schema += args-int.json
+qapi-schema += args-invalid.json
+qapi-schema += args-member-array-bad.json
+qapi-schema += args-member-case.json
+qapi-schema += args-member-unknown.json
+qapi-schema += args-name-clash.json
+qapi-schema += args-union.json
+qapi-schema += args-unknown.json
+qapi-schema += bad-base.json
+qapi-schema += bad-data.json
+qapi-schema += bad-ident.json
+qapi-schema += bad-type-bool.json
+qapi-schema += bad-type-dict.json
+qapi-schema += bad-type-int.json
+qapi-schema += base-cycle-direct.json
+qapi-schema += base-cycle-indirect.json
+qapi-schema += command-int.json
+qapi-schema += comments.json
+qapi-schema += double-data.json
+qapi-schema += double-type.json
+qapi-schema += duplicate-key.json
+qapi-schema += empty.json
+qapi-schema += enum-bad-name.json
+qapi-schema += enum-bad-prefix.json
+qapi-schema += enum-clash-member.json
+qapi-schema += enum-dict-member.json
+qapi-schema += enum-int-member.json
+qapi-schema += enum-member-case.json
+qapi-schema += enum-missing-data.json
+qapi-schema += enum-wrong-data.json
+qapi-schema += escape-outside-string.json
+qapi-schema += escape-too-big.json
+qapi-schema += escape-too-short.json
+qapi-schema += event-case.json
+qapi-schema += event-nest-struct.json
+qapi-schema += flat-union-array-branch.json
+qapi-schema += flat-union-bad-base.json
+qapi-schema += flat-union-bad-discriminator.json
+qapi-schema += flat-union-base-any.json
+qapi-schema += flat-union-base-union.json
+qapi-schema += flat-union-clash-member.json
+qapi-schema += flat-union-empty.json
+qapi-schema += flat-union-inline.json
+qapi-schema += flat-union-int-branch.json
+qapi-schema += flat-union-invalid-branch-key.json
+qapi-schema += flat-union-invalid-discriminator.json
+qapi-schema += flat-union-no-base.json
+qapi-schema += flat-union-optional-discriminator.json
+qapi-schema += flat-union-string-discriminator.json
+qapi-schema += funny-char.json
+qapi-schema += ident-with-escape.json
+qapi-schema += include-before-err.json
+qapi-schema += include-cycle.json
+qapi-schema += include-format-err.json
+qapi-schema += include-nested-err.json
+qapi-schema += include-no-file.json
+qapi-schema += include-non-file.json
+qapi-schema += include-relpath.json
+qapi-schema += include-repetition.json
+qapi-schema += include-self-cycle.json
+qapi-schema += include-simple.json
+qapi-schema += indented-expr.json
+qapi-schema += leading-comma-list.json
+qapi-schema += leading-comma-object.json
+qapi-schema += missing-colon.json
+qapi-schema += missing-comma-list.json
+qapi-schema += missing-comma-object.json
+qapi-schema += missing-type.json
+qapi-schema += nested-struct-data.json
+qapi-schema += non-objects.json
+qapi-schema += qapi-schema-test.json
+qapi-schema += quoted-structural-chars.json
+qapi-schema += redefined-builtin.json
+qapi-schema += redefined-command.json
+qapi-schema += redefined-event.json
+qapi-schema += redefined-type.json
+qapi-schema += reserved-command-q.json
+qapi-schema += reserved-enum-q.json
+qapi-schema += reserved-member-has.json
+qapi-schema += reserved-member-q.json
+qapi-schema += reserved-member-u.json
+qapi-schema += reserved-member-underscore.json
+qapi-schema += reserved-type-kind.json
+qapi-schema += reserved-type-list.json
+qapi-schema += returns-alternate.json
+qapi-schema += returns-array-bad.json
+qapi-schema += returns-dict.json
+qapi-schema += returns-unknown.json
+qapi-schema += returns-whitelist.json
+qapi-schema += struct-base-clash-deep.json
+qapi-schema += struct-base-clash.json
+qapi-schema += struct-data-invalid.json
+qapi-schema += struct-member-invalid.json
+qapi-schema += trailing-comma-list.json
+qapi-schema += trailing-comma-object.json
+qapi-schema += type-bypass-bad-gen.json
+qapi-schema += unclosed-list.json
+qapi-schema += unclosed-object.json
+qapi-schema += unclosed-string.json
+qapi-schema += unicode-str.json
+qapi-schema += union-base-no-discriminator.json
+qapi-schema += union-branch-case.json
+qapi-schema += union-clash-branches.json
+qapi-schema += union-empty.json
+qapi-schema += union-invalid-base.json
+qapi-schema += union-optional-branch.json
+qapi-schema += union-unknown.json
+qapi-schema += unknown-escape.json
+qapi-schema += unknown-expr-key.json
+check-qapi-schema-y := $(addprefix tests/qapi-schema/, $(qapi-schema))
GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h \
- tests/test-qmp-commands.h tests/test-qapi-event.h
+ tests/test-qmp-commands.h tests/test-qapi-event.h \
+ tests/test-qmp-introspect.h
test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
tests/check-qlist.o tests/check-qfloat.o tests/check-qjson.o \
@@ -270,48 +391,59 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
tests/test-opts-visitor.o tests/test-qmp-event.o \
tests/rcutorture.o tests/test-rcu-list.o
-test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
- tests/test-qapi-event.o
-
$(test-obj-y): QEMU_INCLUDES += -Itests
QEMU_CFLAGS += -I$(SRC_PATH)/tests
-qom-core-obj = qom/object.o qom/qom-qobject.o qom/container.o qom/object_interfaces.o
-
-tests/check-qint$(EXESUF): tests/check-qint.o libqemuutil.a
-tests/check-qstring$(EXESUF): tests/check-qstring.o libqemuutil.a
-tests/check-qdict$(EXESUF): tests/check-qdict.o libqemuutil.a
-tests/check-qlist$(EXESUF): tests/check-qlist.o libqemuutil.a
-tests/check-qfloat$(EXESUF): tests/check-qfloat.o libqemuutil.a
-tests/check-qjson$(EXESUF): tests/check-qjson.o libqemuutil.a libqemustub.a
-tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(qom-core-obj) libqemuutil.a libqemustub.a
-tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(qom-core-obj) libqemuutil.a libqemustub.a
-tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(block-obj-y) libqemuutil.a libqemustub.a
-tests/test-aio$(EXESUF): tests/test-aio.o $(block-obj-y) libqemuutil.a libqemustub.a
-tests/test-rfifolock$(EXESUF): tests/test-rfifolock.o libqemuutil.a libqemustub.a
-tests/test-throttle$(EXESUF): tests/test-throttle.o $(block-obj-y) libqemuutil.a libqemustub.a
-tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(block-obj-y) libqemuutil.a libqemustub.a
-tests/test-iov$(EXESUF): tests/test-iov.o libqemuutil.a
-tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o libqemuutil.a libqemustub.a
+
+
+# Deps that are common to various different sets of tests below
+test-util-obj-y = libqemuutil.a libqemustub.a
+test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y)
+test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
+ tests/test-qapi-event.o tests/test-qmp-introspect.o \
+ $(test-qom-obj-y)
+test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
+test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
+test-block-obj-y = $(block-obj-y) $(test-io-obj-y)
+
+tests/check-qint$(EXESUF): tests/check-qint.o $(test-util-obj-y)
+tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y)
+tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y)
+tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y)
+tests/check-qfloat$(EXESUF): tests/check-qfloat.o $(test-util-obj-y)
+tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
+tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
+tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
+tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
+tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
+tests/test-rfifolock$(EXESUF): tests/test-rfifolock.o $(test-util-obj-y)
+tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
+tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y)
+tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y)
+tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
+tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y)
tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o
-tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o page_cache.o libqemuutil.a
+tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o page_cache.o $(test-util-obj-y)
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
tests/test-int128$(EXESUF): tests/test-int128.o
-tests/rcutorture$(EXESUF): tests/rcutorture.o libqemuutil.a libqemustub.a
-tests/test-rcu-list$(EXESUF): tests/test-rcu-list.o libqemuutil.a libqemustub.a
+tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y)
+tests/test-rcu-list$(EXESUF): tests/test-rcu-list.o $(test-util-obj-y)
tests/test-qdev-global-props$(EXESUF): tests/test-qdev-global-props.o \
hw/core/qdev.o hw/core/qdev-properties.o hw/core/hotplug.o\
hw/core/irq.o \
hw/core/fw-path-provider.o \
- $(qom-core-obj) \
- $(test-qapi-obj-y) \
- libqemuutil.a libqemustub.a
+ $(test-qapi-obj-y)
tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
migration/vmstate.o migration/qemu-file.o migration/qemu-file-buf.o \
migration/qemu-file-unix.o qjson.o \
- $(qom-core-obj) \
+ $(test-qom-obj-y)
+tests/test-timed-average$(EXESUF): tests/test-timed-average.o qemu-timer.o \
+ $(test-util-obj-y)
+tests/test-base64$(EXESUF): tests/test-base64.o \
libqemuutil.a libqemustub.a
+tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y)
+
tests/test-qapi-types.c tests/test-qapi-types.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
@@ -332,21 +464,56 @@ $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-eve
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
$(gen-out-type) -o tests -p "test-" $<, \
" GEN $@")
+tests/test-qmp-introspect.c tests/test-qmp-introspect.h :\
+$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-introspect.py $(qapi-py)
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-introspect.py \
+ $(gen-out-type) -o tests -p "test-" $<, \
+ " GEN $@")
-tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
-tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
-tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
-tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
-tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
-tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
-tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
-tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
-tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
-
-tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a
-tests/test-bitops$(EXESUF): tests/test-bitops.o libqemuutil.a
-tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o libqemuutil.a libqemustub.a
-tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o libqemuutil.a libqemustub.a
+tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
+tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
+tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
+tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y)
+tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y)
+tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
+tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
+tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
+tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
+
+tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y)
+tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y)
+tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y)
+tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o $(test-crypto-obj-y)
+tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o $(test-crypto-obj-y)
+tests/test-crypto-xts$(EXESUF): tests/test-crypto-xts.o $(test-crypto-obj-y)
+
+tests/crypto-tls-x509-helpers.o-cflags := $(TASN1_CFLAGS)
+tests/crypto-tls-x509-helpers.o-libs := $(TASN1_LIBS)
+tests/pkix_asn1_tab.o-cflags := $(TASN1_CFLAGS)
+
+tests/test-crypto-tlscredsx509.o-cflags := $(TASN1_CFLAGS)
+tests/test-crypto-tlscredsx509$(EXESUF): tests/test-crypto-tlscredsx509.o \
+ tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o $(test-crypto-obj-y)
+
+tests/test-crypto-tlssession.o-cflags := $(TASN1_CFLAGS)
+tests/test-crypto-tlssession$(EXESUF): tests/test-crypto-tlssession.o \
+ tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o $(test-crypto-obj-y)
+tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y)
+tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \
+ tests/io-channel-helpers.o $(test-io-obj-y)
+tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \
+ tests/io-channel-helpers.o $(test-io-obj-y)
+tests/test-io-channel-tls$(EXESUF): tests/test-io-channel-tls.o \
+ tests/crypto-tls-x509-helpers.o tests/pkix_asn1_tab.o \
+ tests/io-channel-helpers.o $(test-io-obj-y)
+tests/test-io-channel-command$(EXESUF): tests/test-io-channel-command.o \
+ tests/io-channel-helpers.o $(test-io-obj-y)
+tests/test-io-channel-buffer$(EXESUF): tests/test-io-channel-buffer.o \
+ tests/io-channel-helpers.o $(test-io-obj-y)
+tests/test-crypto-pbkdf$(EXESUF): tests/test-crypto-pbkdf.o $(test-crypto-obj-y)
+tests/test-crypto-ivgen$(EXESUF): tests/test-crypto-ivgen.o $(test-crypto-obj-y)
+tests/test-crypto-afsplit$(EXESUF): tests/test-crypto-afsplit.o $(test-crypto-obj-y)
+tests/test-crypto-block$(EXESUF): tests/test-crypto-block.o $(test-crypto-obj-y)
libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o tests/libqos/malloc.o
libqos-obj-y += tests/libqos/i2c.o tests/libqos/libqos.o
@@ -354,9 +521,11 @@ libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
libqos-pc-obj-y += tests/libqos/ahci.o
libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
+libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
libqos-usb-obj-y = $(libqos-pc-obj-y) tests/libqos/usb.o
libqos-virtio-obj-y = $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o
+tests/device-introspect-test$(EXESUF): tests/device-introspect-test.o
tests/rtc-test$(EXESUF): tests/rtc-test.o
tests/m48t59-test$(EXESUF): tests/m48t59-test.o
tests/endianness-test$(EXESUF): tests/endianness-test.o
@@ -364,10 +533,15 @@ tests/spapr-phb-test$(EXESUF): tests/spapr-phb-test.o $(libqos-obj-y)
tests/fdc-test$(EXESUF): tests/fdc-test.o
tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
tests/ahci-test$(EXESUF): tests/ahci-test.o $(libqos-pc-obj-y)
+tests/ipmi-kcs-test$(EXESUF): tests/ipmi-kcs-test.o
+tests/ipmi-bt-test$(EXESUF): tests/ipmi-bt-test.o
tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
-tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o $(libqos-obj-y)
+tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
+ tests/boot-sector.o $(libqos-obj-y)
+tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
+tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
@@ -381,7 +555,7 @@ tests/wdt_ib700-test$(EXESUF): tests/wdt_ib700-test.o
tests/tco-test$(EXESUF): tests/tco-test.o $(libqos-pc-obj-y)
tests/virtio-balloon-test$(EXESUF): tests/virtio-balloon-test.o
tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o $(libqos-virtio-obj-y)
-tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o $(libqos-pc-obj-y)
+tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o $(libqos-pc-obj-y) $(libqos-virtio-obj-y)
tests/virtio-rng-test$(EXESUF): tests/virtio-rng-test.o $(libqos-pc-obj-y)
tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o $(libqos-virtio-obj-y)
tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o
@@ -405,10 +579,15 @@ tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o $(libqos-usb-obj-y)
tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y)
tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
tests/pc-cpu-test$(EXESUF): tests/pc-cpu-test.o
-tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y)
+tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) $(test-io-obj-y)
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
-tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o libqemuutil.a libqemustub.a
-tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(block-obj-y) libqemuutil.a libqemustub.a
+tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y)
+tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-block-obj-y)
+tests/test-netfilter$(EXESUF): tests/test-netfilter.o $(qtest-obj-y)
+tests/test-filter-mirror$(EXESUF): tests/test-filter-mirror.o $(qtest-obj-y)
+tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o $(qtest-obj-y)
+tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
+tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
ifeq ($(CONFIG_POSIX),y)
LIBS += -lutil
@@ -418,13 +597,18 @@ endif
TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
ifeq ($(CONFIG_POSIX),y)
-QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TARGET),))
+QTEST_TARGETS = $(TARGETS)
check-qtest-y=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
+check-qtest-y += $(check-qtest-generic-y)
+else
+QTEST_TARGETS =
endif
-qtest-obj-y = tests/libqtest.o libqemuutil.a libqemustub.a
+qtest-obj-y = tests/libqtest.o $(test-util-obj-y)
$(check-qtest-y): $(qtest-obj-y)
+tests/test-qga: tests/test-qga.o $(qtest-obj-y)
+
.PHONY: check-help
check-help:
@echo "Regression testing targets:"
@@ -457,8 +641,8 @@ $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y)
$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
QTEST_QEMU_IMG=qemu-img$(EXESUF) \
MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
- gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y),"GTESTER $@")
- $(if $(CONFIG_GCOV),@for f in $(gcov-files-$*-y); do \
+ gtester $(GTESTER_OPTIONS) -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER $@")
+ $(if $(CONFIG_GCOV),@for f in $(gcov-files-$*-y) $(gcov-files-generic-y); do \
echo Gcov report for $$f:;\
$(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
done,)
@@ -469,7 +653,7 @@ $(patsubst %, check-%, $(check-unit-y)): check-%: %
$(call quiet-command, \
MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
gtester $(GTESTER_OPTIONS) -m=$(SPEED) $*,"GTESTER $*")
- $(if $(CONFIG_GCOV),@for f in $(gcov-files-$(subst tests/,,$*)-y); do \
+ $(if $(CONFIG_GCOV),@for f in $(gcov-files-$(subst tests/,,$*)-y) $(gcov-files-generic-y); do \
echo Gcov report for $$f:;\
$(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
done,)
@@ -479,7 +663,7 @@ $(patsubst %, check-%, $(check-unit-y)): check-%: %
$(patsubst %, check-report-qtest-%.xml, $(QTEST_TARGETS)): check-report-qtest-%.xml: $(check-qtest-y)
$(call quiet-command,QTEST_QEMU_BINARY=$*-softmmu/qemu-system-$* \
QTEST_QEMU_IMG=qemu-img$(EXESUF) \
- gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $(check-qtest-$*-y),"GTESTER $@")
+ gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $(check-qtest-$*-y) $(check-qtest-generic-y),"GTESTER $@")
check-report-unit.xml: $(check-unit-y)
$(call quiet-command,gtester -q $(GTESTER_OPTIONS) -o $@ -m=$(SPEED) $^, "GTESTER $@")
@@ -527,7 +711,7 @@ check: check-qapi-schema check-unit check-qtest
check-clean:
$(MAKE) -C tests/tcg clean
rm -rf $(check-unit-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y)
- rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y)))
+ rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y)) $(check-qtest-generic-y))
clean: check-clean
diff --git a/qemu/tests/ac97-test.c b/qemu/tests/ac97-test.c
index af30ea1dd..75cab8f98 100644
--- a/qemu/tests/ac97-test.c
+++ b/qemu/tests/ac97-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void nop(void)
diff --git a/qemu/tests/acpi-test-data/pc/DSDT b/qemu/tests/acpi-test-data/pc/DSDT
index c658203db..9d1274d3c 100644
--- a/qemu/tests/acpi-test-data/pc/DSDT
+++ b/qemu/tests/acpi-test-data/pc/DSDT
Binary files differ
diff --git a/qemu/tests/acpi-test-data/pc/SSDT.bridge b/qemu/tests/acpi-test-data/pc/DSDT.bridge
index 6e6660b1f..cf48c62aa 100644
--- a/qemu/tests/acpi-test-data/pc/SSDT.bridge
+++ b/qemu/tests/acpi-test-data/pc/DSDT.bridge
Binary files differ
diff --git a/qemu/tests/acpi-test-data/pc/SSDT b/qemu/tests/acpi-test-data/pc/SSDT
deleted file mode 100644
index 210d6a71e..000000000
--- a/qemu/tests/acpi-test-data/pc/SSDT
+++ /dev/null
Binary files differ
diff --git a/qemu/tests/acpi-test-data/q35/DSDT b/qemu/tests/acpi-test-data/q35/DSDT
index 4723e5954..1c089c34b 100644
--- a/qemu/tests/acpi-test-data/q35/DSDT
+++ b/qemu/tests/acpi-test-data/q35/DSDT
Binary files differ
diff --git a/qemu/tests/acpi-test-data/q35/DSDT.bridge b/qemu/tests/acpi-test-data/q35/DSDT.bridge
new file mode 100644
index 000000000..b29fcda0b
--- /dev/null
+++ b/qemu/tests/acpi-test-data/q35/DSDT.bridge
Binary files differ
diff --git a/qemu/tests/acpi-test-data/q35/SSDT b/qemu/tests/acpi-test-data/q35/SSDT
deleted file mode 100644
index 0970c67dd..000000000
--- a/qemu/tests/acpi-test-data/q35/SSDT
+++ /dev/null
Binary files differ
diff --git a/qemu/tests/acpi-test-data/q35/SSDT.bridge b/qemu/tests/acpi-test-data/q35/SSDT.bridge
deleted file mode 100644
index a77868861..000000000
--- a/qemu/tests/acpi-test-data/q35/SSDT.bridge
+++ /dev/null
Binary files differ
diff --git a/qemu/tests/ahci-test.c b/qemu/tests/ahci-test.c
index 87d769186..6869f7f46 100644
--- a/qemu/tests/ahci-test.c
+++ b/qemu/tests/ahci-test.c
@@ -22,9 +22,7 @@
* THE SOFTWARE.
*/
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
+#include "qemu/osdep.h"
#include <getopt.h>
#include <glib.h>
@@ -39,15 +37,17 @@
#include "hw/pci/pci_ids.h"
#include "hw/pci/pci_regs.h"
-/* Test-specific defines -- in MiB */
-#define TEST_IMAGE_SIZE_MB (200 * 1024)
-#define TEST_IMAGE_SECTORS ((TEST_IMAGE_SIZE_MB / AHCI_SECTOR_SIZE) \
- * 1024 * 1024)
+/* Test images sizes in MB */
+#define TEST_IMAGE_SIZE_MB_LARGE (200 * 1024)
+#define TEST_IMAGE_SIZE_MB_SMALL 64
/*** Globals ***/
static char tmp_path[] = "/tmp/qtest.XXXXXX";
static char debug_path[] = "/tmp/qtest-blkdebug.XXXXXX";
+static char mig_socket[] = "/tmp/qtest-migration.XXXXXX";
static bool ahci_pedantic;
+static const char *imgfmt;
+static unsigned test_image_size_mb;
/*** Function Declarations ***/
static void ahci_test_port_spec(AHCIQState *ahci, uint8_t port);
@@ -60,6 +60,11 @@ static void ahci_test_pmcap(AHCIQState *ahci, uint8_t offset);
/*** Utilities ***/
+static uint64_t mb_to_sectors(uint64_t image_size_mb)
+{
+ return (image_size_mb * 1024 * 1024) / AHCI_SECTOR_SIZE;
+}
+
static void string_bswap16(uint16_t *s, size_t bytes)
{
g_assert_cmphex((bytes & 1), ==, 0);
@@ -71,32 +76,6 @@ static void string_bswap16(uint16_t *s, size_t bytes)
}
}
-static void generate_pattern(void *buffer, size_t len, size_t cycle_len)
-{
- int i, j;
- unsigned char *tx = (unsigned char *)buffer;
- unsigned char p;
- size_t *sx;
-
- /* Write an indicative pattern that varies and is unique per-cycle */
- p = rand() % 256;
- for (i = j = 0; i < len; i++, j++) {
- tx[i] = p;
- if (j % cycle_len == 0) {
- p = rand() % 256;
- }
- }
-
- /* force uniqueness by writing an id per-cycle */
- for (i = 0; i < len / cycle_len; i++) {
- j = i * cycle_len;
- if (j + sizeof(*sx) <= len) {
- sx = (size_t *)&tx[j];
- *sx = i;
- }
- }
-}
-
/**
* Verify that the transfer did not corrupt our state at all.
*/
@@ -140,8 +119,11 @@ static void ahci_migrate(AHCIQState *from, AHCIQState *to, const char *uri)
{
QOSState *tmp = to->parent;
QPCIDevice *dev = to->dev;
+ char *uri_local = NULL;
+
if (uri == NULL) {
- uri = "tcp:127.0.0.1:1234";
+ uri_local = g_strdup_printf("%s%s", "unix:", mig_socket);
+ uri = uri_local;
}
/* context will be 'to' after completion. */
@@ -161,6 +143,7 @@ static void ahci_migrate(AHCIQState *from, AHCIQState *to, const char *uri)
from->dev = dev;
verify_state(to);
+ g_free(uri_local);
}
/*** Test Setup & Teardown ***/
@@ -196,11 +179,11 @@ static AHCIQState *ahci_boot(const char *cli, ...)
va_end(ap);
} else {
cli = "-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s"
- ",format=qcow2"
+ ",format=%s"
" -M q35 "
"-device ide-hd,drive=drive0 "
"-global ide-hd.ver=%s";
- s = ahci_boot(cli, tmp_path, "testdisk", "version");
+ s = ahci_boot(cli, tmp_path, "testdisk", imgfmt, "version");
}
return s;
@@ -230,6 +213,7 @@ static AHCIQState *ahci_boot_and_enable(const char *cli, ...)
va_list ap;
uint16_t buff[256];
uint8_t port;
+ uint8_t hello;
if (cli) {
va_start(ap, cli);
@@ -244,7 +228,12 @@ static AHCIQState *ahci_boot_and_enable(const char *cli, ...)
/* Initialize test device */
port = ahci_port_select(ahci);
ahci_port_clear(ahci, port);
- ahci_io(ahci, port, CMD_IDENTIFY, &buff, sizeof(buff), 0);
+ if (is_atapi(ahci, port)) {
+ hello = CMD_PACKET_ID;
+ } else {
+ hello = CMD_IDENTIFY;
+ }
+ ahci_io(ahci, port, hello, &buff, sizeof(buff), 0);
return ahci;
}
@@ -899,18 +888,12 @@ static void ahci_test_io_rw_simple(AHCIQState *ahci, unsigned bufsize,
static uint8_t ahci_test_nondata(AHCIQState *ahci, uint8_t ide_cmd)
{
uint8_t port;
- AHCICommand *cmd;
/* Sanitize */
port = ahci_port_select(ahci);
ahci_port_clear(ahci, port);
- /* Issue Command */
- cmd = ahci_command_create(ide_cmd);
- ahci_command_commit(ahci, cmd, port);
- ahci_command_issue(ahci, cmd);
- ahci_command_verify(ahci, cmd);
- ahci_command_free(cmd);
+ ahci_io(ahci, port, ide_cmd, NULL, 0, 0);
return port;
}
@@ -926,7 +909,7 @@ static void ahci_test_max(AHCIQState *ahci)
uint64_t nsect;
uint8_t port;
uint8_t cmd;
- uint64_t config_sect = TEST_IMAGE_SECTORS - 1;
+ uint64_t config_sect = mb_to_sectors(test_image_size_mb) - 1;
if (config_sect > 0xFFFFFF) {
cmd = CMD_READ_MAX_EXT;
@@ -1060,14 +1043,14 @@ static void test_dma_fragmented(void)
ahci_command_commit(ahci, cmd, px);
ahci_command_issue(ahci, cmd);
ahci_command_verify(ahci, cmd);
- g_free(cmd);
+ ahci_command_free(cmd);
cmd = ahci_command_create(CMD_READ_DMA);
ahci_command_adjust(cmd, 0, ptr, bufsize, 32);
ahci_command_commit(ahci, cmd, px);
ahci_command_issue(ahci, cmd);
ahci_command_verify(ahci, cmd);
- g_free(cmd);
+ ahci_command_free(cmd);
/* Read back the guest's receive buffer into local memory */
bufread(ptr, rx, bufsize);
@@ -1095,33 +1078,23 @@ static void test_flush_retry(void)
AHCIQState *ahci;
AHCICommand *cmd;
uint8_t port;
- const char *s;
prepare_blkdebug_script(debug_path, "flush_to_disk");
ahci = ahci_boot_and_enable("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
- "format=qcow2,cache=writeback,"
+ "format=%s,cache=writeback,"
"rerror=stop,werror=stop "
"-M q35 "
"-device ide-hd,drive=drive0 ",
debug_path,
- tmp_path);
+ tmp_path, imgfmt);
/* Issue Flush Command and wait for error */
port = ahci_port_select(ahci);
ahci_port_clear(ahci, port);
- cmd = ahci_command_create(CMD_FLUSH_CACHE);
- ahci_command_commit(ahci, cmd, port);
- ahci_command_issue_async(ahci, cmd);
- qmp_eventwait("STOP");
- /* Complete the command */
- s = "{'execute':'cont' }";
- qmp_async(s);
- qmp_eventwait("RESUME");
- ahci_command_wait(ahci, cmd);
- ahci_command_verify(ahci, cmd);
+ cmd = ahci_guest_io_halt(ahci, port, CMD_FLUSH_CACHE, 0, 0, 0);
+ ahci_guest_io_resume(ahci, cmd);
- ahci_command_free(cmd);
ahci_shutdown(ahci);
}
@@ -1131,18 +1104,19 @@ static void test_flush_retry(void)
static void test_migrate_sanity(void)
{
AHCIQState *src, *dst;
- const char *uri = "tcp:127.0.0.1:1234";
+ char *uri = g_strdup_printf("unix:%s", mig_socket);
src = ahci_boot("-m 1024 -M q35 "
- "-hda %s ", tmp_path);
+ "-drive if=ide,file=%s,format=%s ", tmp_path, imgfmt);
dst = ahci_boot("-m 1024 -M q35 "
- "-hda %s "
- "-incoming %s", tmp_path, uri);
+ "-drive if=ide,file=%s,format=%s "
+ "-incoming %s", tmp_path, imgfmt, uri);
ahci_migrate(src, dst, uri);
ahci_shutdown(src);
ahci_shutdown(dst);
+ g_free(uri);
}
/**
@@ -1155,14 +1129,14 @@ static void ahci_migrate_simple(uint8_t cmd_read, uint8_t cmd_write)
size_t bufsize = 4096;
unsigned char *tx = g_malloc(bufsize);
unsigned char *rx = g_malloc0(bufsize);
- unsigned i;
- const char *uri = "tcp:127.0.0.1:1234";
+ char *uri = g_strdup_printf("unix:%s", mig_socket);
src = ahci_boot_and_enable("-m 1024 -M q35 "
- "-hda %s ", tmp_path);
+ "-drive if=ide,format=%s,file=%s ",
+ imgfmt, tmp_path);
dst = ahci_boot("-m 1024 -M q35 "
- "-hda %s "
- "-incoming %s", tmp_path, uri);
+ "-drive if=ide,format=%s,file=%s "
+ "-incoming %s", imgfmt, tmp_path, uri);
set_context(src->parent);
@@ -1171,9 +1145,7 @@ static void ahci_migrate_simple(uint8_t cmd_read, uint8_t cmd_write)
ahci_port_clear(src, px);
/* create pattern */
- for (i = 0; i < bufsize; i++) {
- tx[i] = (bufsize - i);
- }
+ generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
/* Write, migrate, then read. */
ahci_io(src, px, cmd_write, tx, bufsize, 0);
@@ -1187,6 +1159,7 @@ static void ahci_migrate_simple(uint8_t cmd_read, uint8_t cmd_write)
ahci_shutdown(dst);
g_free(rx);
g_free(tx);
+ g_free(uri);
}
static void test_migrate_dma(void)
@@ -1213,29 +1186,25 @@ static void ahci_halted_io_test(uint8_t cmd_read, uint8_t cmd_write)
size_t bufsize = 4096;
unsigned char *tx = g_malloc(bufsize);
unsigned char *rx = g_malloc0(bufsize);
- unsigned i;
uint64_t ptr;
AHCICommand *cmd;
prepare_blkdebug_script(debug_path, "write_aio");
ahci = ahci_boot_and_enable("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
- "format=qcow2,cache=writeback,"
+ "format=%s,cache=writeback,"
"rerror=stop,werror=stop "
"-M q35 "
"-device ide-hd,drive=drive0 ",
debug_path,
- tmp_path);
+ tmp_path, imgfmt);
/* Initialize and prepare */
port = ahci_port_select(ahci);
ahci_port_clear(ahci, port);
- for (i = 0; i < bufsize; i++) {
- tx[i] = (bufsize - i);
- }
-
/* create DMA source buffer and write pattern */
+ generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
ptr = ahci_alloc(ahci, bufsize);
g_assert(ptr);
memwrite(ptr, tx, bufsize);
@@ -1282,38 +1251,34 @@ static void ahci_migrate_halted_io(uint8_t cmd_read, uint8_t cmd_write)
size_t bufsize = 4096;
unsigned char *tx = g_malloc(bufsize);
unsigned char *rx = g_malloc0(bufsize);
- unsigned i;
uint64_t ptr;
AHCICommand *cmd;
- const char *uri = "tcp:127.0.0.1:1234";
+ char *uri = g_strdup_printf("unix:%s", mig_socket);
prepare_blkdebug_script(debug_path, "write_aio");
src = ahci_boot_and_enable("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
- "format=qcow2,cache=writeback,"
+ "format=%s,cache=writeback,"
"rerror=stop,werror=stop "
"-M q35 "
"-device ide-hd,drive=drive0 ",
debug_path,
- tmp_path);
+ tmp_path, imgfmt);
dst = ahci_boot("-drive file=%s,if=none,id=drive0,"
- "format=qcow2,cache=writeback,"
+ "format=%s,cache=writeback,"
"rerror=stop,werror=stop "
"-M q35 "
"-device ide-hd,drive=drive0 "
"-incoming %s",
- tmp_path, uri);
+ tmp_path, imgfmt, uri);
set_context(src->parent);
/* Initialize and prepare */
port = ahci_port_select(src);
ahci_port_clear(src, port);
-
- for (i = 0; i < bufsize; i++) {
- tx[i] = (bufsize - i);
- }
+ generate_pattern(tx, bufsize, AHCI_SECTOR_SIZE);
/* create DMA source buffer and write pattern */
ptr = ahci_alloc(src, bufsize);
@@ -1338,6 +1303,7 @@ static void ahci_migrate_halted_io(uint8_t cmd_read, uint8_t cmd_write)
ahci_shutdown(dst);
g_free(rx);
g_free(tx);
+ g_free(uri);
}
static void test_migrate_halted_dma(void)
@@ -1359,20 +1325,22 @@ static void test_flush_migrate(void)
AHCICommand *cmd;
uint8_t px;
const char *s;
- const char *uri = "tcp:127.0.0.1:1234";
+ char *uri = g_strdup_printf("unix:%s", mig_socket);
prepare_blkdebug_script(debug_path, "flush_to_disk");
src = ahci_boot_and_enable("-drive file=blkdebug:%s:%s,if=none,id=drive0,"
- "cache=writeback,rerror=stop,werror=stop "
+ "cache=writeback,rerror=stop,werror=stop,"
+ "format=%s "
"-M q35 "
"-device ide-hd,drive=drive0 ",
- debug_path, tmp_path);
+ debug_path, tmp_path, imgfmt);
dst = ahci_boot("-drive file=%s,if=none,id=drive0,"
- "cache=writeback,rerror=stop,werror=stop "
+ "cache=writeback,rerror=stop,werror=stop,"
+ "format=%s "
"-M q35 "
"-device ide-hd,drive=drive0 "
- "-incoming %s", tmp_path, uri);
+ "-incoming %s", tmp_path, imgfmt, uri);
set_context(src->parent);
@@ -1397,6 +1365,7 @@ static void test_flush_migrate(void)
ahci_command_free(cmd);
ahci_shutdown(src);
ahci_shutdown(dst);
+ g_free(uri);
}
static void test_max(void)
@@ -1442,6 +1411,98 @@ static void test_ncq_simple(void)
ahci_shutdown(ahci);
}
+static int prepare_iso(size_t size, unsigned char **buf, char **name)
+{
+ char cdrom_path[] = "/tmp/qtest.iso.XXXXXX";
+ unsigned char *patt;
+ ssize_t ret;
+ int fd = mkstemp(cdrom_path);
+
+ g_assert(buf);
+ g_assert(name);
+ patt = g_malloc(size);
+
+ /* Generate a pattern and build a CDROM image to read from */
+ generate_pattern(patt, size, ATAPI_SECTOR_SIZE);
+ ret = write(fd, patt, size);
+ g_assert(ret == size);
+
+ *name = g_strdup(cdrom_path);
+ *buf = patt;
+ return fd;
+}
+
+static void remove_iso(int fd, char *name)
+{
+ unlink(name);
+ g_free(name);
+ close(fd);
+}
+
+static int ahci_cb_cmp_buff(AHCIQState *ahci, AHCICommand *cmd,
+ const AHCIOpts *opts)
+{
+ unsigned char *tx = opts->opaque;
+ unsigned char *rx = g_malloc0(opts->size);
+
+ bufread(opts->buffer, rx, opts->size);
+ g_assert_cmphex(memcmp(tx, rx, opts->size), ==, 0);
+ g_free(rx);
+
+ return 0;
+}
+
+static void ahci_test_cdrom(int nsectors, bool dma)
+{
+ AHCIQState *ahci;
+ unsigned char *tx;
+ char *iso;
+ int fd;
+ AHCIOpts opts = {
+ .size = (ATAPI_SECTOR_SIZE * nsectors),
+ .atapi = true,
+ .atapi_dma = dma,
+ .post_cb = ahci_cb_cmp_buff,
+ };
+
+ /* Prepare ISO and fill 'tx' buffer */
+ fd = prepare_iso(1024 * 1024, &tx, &iso);
+ opts.opaque = tx;
+
+ /* Standard startup wonkery, but use ide-cd and our special iso file */
+ ahci = ahci_boot_and_enable("-drive if=none,id=drive0,file=%s,format=raw "
+ "-M q35 "
+ "-device ide-cd,drive=drive0 ", iso);
+
+ /* Build & Send AHCI command */
+ ahci_exec(ahci, ahci_port_select(ahci), CMD_ATAPI_READ_10, &opts);
+
+ /* Cleanup */
+ g_free(tx);
+ ahci_shutdown(ahci);
+ remove_iso(fd, iso);
+}
+
+static void test_cdrom_dma(void)
+{
+ ahci_test_cdrom(1, true);
+}
+
+static void test_cdrom_dma_multi(void)
+{
+ ahci_test_cdrom(3, true);
+}
+
+static void test_cdrom_pio(void)
+{
+ ahci_test_cdrom(1, false);
+}
+
+static void test_cdrom_pio_multi(void)
+{
+ ahci_test_cdrom(3, false);
+}
+
/******************************************************************************/
/* AHCI I/O Test Matrix Definitions */
@@ -1513,7 +1574,7 @@ static uint64_t offset_sector(enum OffsetType ofst,
return 1;
case OFFSET_HIGH:
ceil = (addr_type == ADDR_MODE_LBA28) ? 0xfffffff : 0xffffffffffff;
- ceil = MIN(ceil, TEST_IMAGE_SECTORS - 1);
+ ceil = MIN(ceil, mb_to_sectors(test_image_size_mb) - 1);
nsectors = buffsize / AHCI_SECTOR_SIZE;
return ceil - nsectors + 1;
default:
@@ -1595,8 +1656,9 @@ static void create_ahci_io_test(enum IOMode type, enum AddrMode addr,
enum BuffLen len, enum OffsetType offset)
{
char *name;
- AHCIIOTestOptions *opts = g_malloc(sizeof(AHCIIOTestOptions));
+ AHCIIOTestOptions *opts;
+ opts = g_malloc(sizeof(AHCIIOTestOptions));
opts->length = len;
opts->address_type = addr;
opts->io_type = type;
@@ -1608,6 +1670,13 @@ static void create_ahci_io_test(enum IOMode type, enum AddrMode addr,
buff_len_str[len],
offset_str[offset]);
+ if ((addr == ADDR_MODE_LBA48) && (offset == OFFSET_HIGH) &&
+ (mb_to_sectors(test_image_size_mb) <= 0xFFFFFFF)) {
+ g_test_message("%s: skipped; test image too small", name);
+ g_free(name);
+ return;
+ }
+
qtest_add_data_func(name, opts, test_io_interface);
g_free(name);
}
@@ -1654,15 +1723,33 @@ int main(int argc, char **argv)
return 0;
}
- /* Create a temporary qcow2 image */
- close(mkstemp(tmp_path));
- mkqcow2(tmp_path, TEST_IMAGE_SIZE_MB);
+ /* Create a temporary image */
+ fd = mkstemp(tmp_path);
+ g_assert(fd >= 0);
+ if (have_qemu_img()) {
+ imgfmt = "qcow2";
+ test_image_size_mb = TEST_IMAGE_SIZE_MB_LARGE;
+ mkqcow2(tmp_path, TEST_IMAGE_SIZE_MB_LARGE);
+ } else {
+ g_test_message("QTEST_QEMU_IMG not set or qemu-img missing; "
+ "skipping LBA48 high-sector tests");
+ imgfmt = "raw";
+ test_image_size_mb = TEST_IMAGE_SIZE_MB_SMALL;
+ ret = ftruncate(fd, test_image_size_mb * 1024 * 1024);
+ g_assert(ret == 0);
+ }
+ close(fd);
/* Create temporary blkdebug instructions */
fd = mkstemp(debug_path);
g_assert(fd >= 0);
close(fd);
+ /* Reserve a hollow file to use as a socket for migration tests */
+ fd = mkstemp(mig_socket);
+ g_assert(fd >= 0);
+ close(fd);
+
/* Run the tests */
qtest_add_func("/ahci/sanity", test_sanity);
qtest_add_func("/ahci/pci_spec", test_pci_spec);
@@ -1700,11 +1787,17 @@ int main(int argc, char **argv)
qtest_add_func("/ahci/io/ncq/retry", test_halted_ncq);
qtest_add_func("/ahci/migrate/ncq/halted", test_migrate_halted_ncq);
+ qtest_add_func("/ahci/cdrom/dma/single", test_cdrom_dma);
+ qtest_add_func("/ahci/cdrom/dma/multi", test_cdrom_dma_multi);
+ qtest_add_func("/ahci/cdrom/pio/single", test_cdrom_pio);
+ qtest_add_func("/ahci/cdrom/pio/multi", test_cdrom_pio_multi);
+
ret = g_test_run();
/* Cleanup */
unlink(tmp_path);
unlink(debug_path);
+ unlink(mig_socket);
return ret;
}
diff --git a/qemu/tests/bios-tables-test.c b/qemu/tests/bios-tables-test.c
index 0de1742d7..03528140c 100644
--- a/qemu/tests/bios-tables-test.c
+++ b/qemu/tests/bios-tables-test.c
@@ -10,16 +10,15 @@
* See the COPYING file in the top-level directory.
*/
-#include <string.h>
-#include <stdio.h>
+#include "qemu/osdep.h"
#include <glib.h>
#include <glib/gstdio.h>
#include "qemu-common.h"
#include "libqtest.h"
-#include "qemu/compiler.h"
#include "hw/acpi/acpi-defs.h"
-#include "hw/i386/smbios.h"
+#include "hw/smbios/smbios.h"
#include "qemu/bitmap.h"
+#include "boot-sector.h"
#define MACHINE_PC "pc"
#define MACHINE_Q35 "q35"
@@ -50,16 +49,9 @@ typedef struct {
int rsdt_tables_nr;
GArray *tables;
uint32_t smbios_ep_addr;
- struct smbios_entry_point smbios_ep_table;
+ struct smbios_21_entry_point smbios_ep_table;
} test_data;
-#define LOW(x) ((x) & 0xff)
-#define HIGH(x) ((x) >> 8)
-
-#define SIGNATURE 0xdead
-#define SIGNATURE_OFFSET 0x10
-#define BOOT_SECTOR_ADDRESS 0x7c00
-
#define ACPI_READ_FIELD(field, addr) \
do { \
switch (sizeof(field)) { \
@@ -119,35 +111,6 @@ typedef struct {
g_assert_cmpstr(ACPI_ASSERT_CMP_str, ==, expected); \
} while (0)
-/* Boot sector code: write SIGNATURE into memory,
- * then halt.
- * Q35 machine requires a minimum 0x7e000 bytes disk.
- * (bug or feature?)
- */
-static uint8_t boot_sector[0x7e000] = {
- /* 7c00: mov $0xdead,%ax */
- [0x00] = 0xb8,
- [0x01] = LOW(SIGNATURE),
- [0x02] = HIGH(SIGNATURE),
- /* 7c03: mov %ax,0x7c10 */
- [0x03] = 0xa3,
- [0x04] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
- [0x05] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
- /* 7c06: cli */
- [0x06] = 0xfa,
- /* 7c07: hlt */
- [0x07] = 0xf4,
- /* 7c08: jmp 0x7c07=0x7c0a-3 */
- [0x08] = 0xeb,
- [0x09] = LOW(-3),
- /* We mov 0xdead here: set value to make debugging easier */
- [SIGNATURE_OFFSET] = LOW(0xface),
- [SIGNATURE_OFFSET + 1] = HIGH(0xface),
- /* End of boot sector marker */
- [0x1FE] = 0x55,
- [0x1FF] = 0xAA,
-};
-
static const char *disk = "tests/acpi-test-disk.raw";
static const char *data_dir = "tests/acpi-test-data";
#ifdef CONFIG_IASL
@@ -161,31 +124,23 @@ static void free_test_data(test_data *data)
AcpiSdtTable *temp;
int i;
- if (data->rsdt_tables_addr) {
- g_free(data->rsdt_tables_addr);
- }
+ g_free(data->rsdt_tables_addr);
for (i = 0; i < data->tables->len; ++i) {
temp = &g_array_index(data->tables, AcpiSdtTable, i);
- if (temp->aml) {
- g_free(temp->aml);
+ g_free(temp->aml);
+ if (temp->aml_file &&
+ !temp->tmp_files_retain &&
+ g_strstr_len(temp->aml_file, -1, "aml-")) {
+ unlink(temp->aml_file);
}
- if (temp->aml_file) {
- if (!temp->tmp_files_retain &&
- g_strstr_len(temp->aml_file, -1, "aml-")) {
- unlink(temp->aml_file);
- }
- g_free(temp->aml_file);
- }
- if (temp->asl) {
- g_free(temp->asl);
- }
- if (temp->asl_file) {
- if (!temp->tmp_files_retain) {
- unlink(temp->asl_file);
- }
- g_free(temp->asl_file);
+ g_free(temp->aml_file);
+ g_free(temp->asl);
+ if (temp->asl_file &&
+ !temp->tmp_files_retain) {
+ unlink(temp->asl_file);
}
+ g_free(temp->asl_file);
}
g_array_free(data->tables, false);
@@ -420,9 +375,7 @@ static void dump_aml_files(test_data *data, bool rebuild)
close(fd);
- if (aml_file) {
- g_free(aml_file);
- }
+ g_free(aml_file);
}
}
@@ -479,7 +432,7 @@ static bool load_asl(GArray *sdts, AcpiSdtTable *sdt)
#define COMMENT_END "*/"
#define DEF_BLOCK "DefinitionBlock ("
-#define BLOCK_NAME_END ".aml"
+#define BLOCK_NAME_END ","
static GString *normalize_asl(gchar *asl_code)
{
@@ -590,6 +543,22 @@ static void test_acpi_asl(test_data *data)
(gchar *)&signature,
sdt->asl_file, sdt->aml_file,
exp_sdt->asl_file, exp_sdt->aml_file);
+ if (getenv("V")) {
+ const char *diff_cmd = getenv("DIFF");
+ if (diff_cmd) {
+ int ret G_GNUC_UNUSED;
+ char *diff = g_strdup_printf("%s %s %s", diff_cmd,
+ exp_sdt->asl_file, sdt->asl_file);
+ ret = system(diff) ;
+ g_free(diff);
+ } else {
+ fprintf(stderr, "acpi-test: Warning. not showing "
+ "difference since no diff utility is specified. "
+ "Set 'DIFF' environment variable to a preferred "
+ "diff utility and run 'make V=1 check' again to "
+ "see ASL difference.");
+ }
+ }
}
}
g_string_free(asl, true);
@@ -601,7 +570,7 @@ static void test_acpi_asl(test_data *data)
static bool smbios_ep_table_ok(test_data *data)
{
- struct smbios_entry_point *ep_table = &data->smbios_ep_table;
+ struct smbios_21_entry_point *ep_table = &data->smbios_ep_table;
uint32_t addr = data->smbios_ep_addr;
ACPI_READ_ARRAY(ep_table->anchor_string, addr);
@@ -681,7 +650,7 @@ static inline bool smbios_single_instance(uint8_t type)
static void test_smbios_structs(test_data *data)
{
DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 };
- struct smbios_entry_point *ep_table = &data->smbios_ep_table;
+ struct smbios_21_entry_point *ep_table = &data->smbios_ep_table;
uint32_t addr = ep_table->structure_table_address;
int i, len, max_len = 0;
uint8_t type, prv, crt;
@@ -733,10 +702,6 @@ static void test_smbios_structs(test_data *data)
static void test_acpi_one(const char *params, test_data *data)
{
char *args;
- uint8_t signature_low;
- uint8_t signature_high;
- uint16_t signature;
- int i;
args = g_strdup_printf("-net none -display none %s "
"-drive id=hd0,if=none,file=%s,format=raw "
@@ -745,24 +710,7 @@ static void test_acpi_one(const char *params, test_data *data)
qtest_start(args);
- /* Wait at most 1 minute */
-#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
-#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
-
- /* Poll until code has run and modified memory. Once it has we know BIOS
- * initialization is done. TODO: check that IP reached the halt
- * instruction.
- */
- for (i = 0; i < TEST_CYCLES; ++i) {
- signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
- signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
- signature = (signature_high << 8) | signature_low;
- if (signature == SIGNATURE) {
- break;
- }
- g_usleep(TEST_DELAY);
- }
- g_assert_cmphex(signature, ==, SIGNATURE);
+ boot_sector_test();
test_acpi_rsdp_address(data);
test_acpi_rsdp_table(data);
@@ -836,15 +784,11 @@ static void test_acpi_q35_tcg_bridge(void)
int main(int argc, char *argv[])
{
const char *arch = qtest_get_arch();
- FILE *f = fopen(disk, "w");
int ret;
- if (!f) {
- fprintf(stderr, "Couldn't open \"%s\": %s", disk, strerror(errno));
- return 1;
- }
- fwrite(boot_sector, 1, sizeof boot_sector, f);
- fclose(f);
+ ret = boot_sector_init(disk);
+ if(ret)
+ return ret;
g_test_init(&argc, &argv, NULL);
@@ -855,6 +799,6 @@ int main(int argc, char *argv[])
qtest_add_func("acpi/q35/tcg/bridge", test_acpi_q35_tcg_bridge);
}
ret = g_test_run();
- unlink(disk);
+ boot_sector_cleanup(disk);
return ret;
}
diff --git a/qemu/tests/boot-order-test.c b/qemu/tests/boot-order-test.c
index 360a6911e..a6d8bd5cb 100644
--- a/qemu/tests/boot-order-test.c
+++ b/qemu/tests/boot-order-test.c
@@ -10,14 +10,12 @@
* See the COPYING file in the top-level directory.
*/
-#include <string.h>
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqos/fw_cfg.h"
#include "libqtest.h"
-#define NO_QEMU_PROTOS
-#include "hw/nvram/fw_cfg.h"
-#undef NO_QEMU_PROTOS
+#include "hw/nvram/fw_cfg_keys.h"
typedef struct {
const char *args;
diff --git a/qemu/tests/boot-sector.c b/qemu/tests/boot-sector.c
new file mode 100644
index 000000000..3ffe2987f
--- /dev/null
+++ b/qemu/tests/boot-sector.c
@@ -0,0 +1,118 @@
+/*
+ * QEMU boot sector testing helpers.
+ *
+ * Copyright (c) 2016 Red Hat Inc.
+ *
+ * Authors:
+ * Michael S. Tsirkin <mst@redhat.com>
+ * Victor Kaplansky <victork@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "boot-sector.h"
+#include "qemu-common.h"
+#include "libqtest.h"
+
+#define LOW(x) ((x) & 0xff)
+#define HIGH(x) ((x) >> 8)
+
+#define SIGNATURE 0xdead
+#define SIGNATURE_OFFSET 0x10
+#define BOOT_SECTOR_ADDRESS 0x7c00
+
+/* Boot sector code: write SIGNATURE into memory,
+ * then halt.
+ * Q35 machine requires a minimum 0x7e000 bytes disk.
+ * (bug or feature?)
+ */
+static uint8_t boot_sector[0x7e000] = {
+ /* The first sector will be placed at RAM address 00007C00, and
+ * the BIOS transfers control to 00007C00
+ */
+
+ /* Data Segment register should be initialized, since pxe
+ * boot loader can leave it dirty.
+ */
+
+ /* 7c00: move $0000,%ax */
+ [0x00] = 0xb8,
+ [0x01] = 0x00,
+ [0x02] = 0x00,
+ /* 7c03: move %ax,%ds */
+ [0x03] = 0x8e,
+ [0x04] = 0xd8,
+
+ /* 7c05: mov $0xdead,%ax */
+ [0x05] = 0xb8,
+ [0x06] = LOW(SIGNATURE),
+ [0x07] = HIGH(SIGNATURE),
+ /* 7c08: mov %ax,0x7c10 */
+ [0x08] = 0xa3,
+ [0x09] = LOW(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
+ [0x0a] = HIGH(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET),
+
+ /* 7c0b cli */
+ [0x0b] = 0xfa,
+ /* 7c0c: hlt */
+ [0x0c] = 0xf4,
+ /* 7c0e: jmp 0x7c07=0x7c0f-3 */
+ [0x0d] = 0xeb,
+ [0x0e] = LOW(-3),
+ /* We mov 0xdead here: set value to make debugging easier */
+ [SIGNATURE_OFFSET] = LOW(0xface),
+ [SIGNATURE_OFFSET + 1] = HIGH(0xface),
+ /* End of boot sector marker */
+ [0x1FE] = 0x55,
+ [0x1FF] = 0xAA,
+};
+
+/* Create boot disk file. */
+int boot_sector_init(const char *fname)
+{
+ FILE *f = fopen(fname, "w");
+
+ if (!f) {
+ fprintf(stderr, "Couldn't open \"%s\": %s", fname, strerror(errno));
+ return 1;
+ }
+ fwrite(boot_sector, 1, sizeof boot_sector, f);
+ fclose(f);
+ return 0;
+}
+
+/* Loop until signature in memory is OK. */
+void boot_sector_test(void)
+{
+ uint8_t signature_low;
+ uint8_t signature_high;
+ uint16_t signature;
+ int i;
+
+ /* Wait at most 1 minute */
+#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
+#define TEST_CYCLES MAX((60 * G_USEC_PER_SEC / TEST_DELAY), 1)
+
+ /* Poll until code has run and modified memory. Once it has we know BIOS
+ * initialization is done. TODO: check that IP reached the halt
+ * instruction.
+ */
+ for (i = 0; i < TEST_CYCLES; ++i) {
+ signature_low = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET);
+ signature_high = readb(BOOT_SECTOR_ADDRESS + SIGNATURE_OFFSET + 1);
+ signature = (signature_high << 8) | signature_low;
+ if (signature == SIGNATURE) {
+ break;
+ }
+ g_usleep(TEST_DELAY);
+ }
+
+ g_assert_cmphex(signature, ==, SIGNATURE);
+}
+
+/* unlink boot disk file. */
+void boot_sector_cleanup(const char *fname)
+{
+ unlink(fname);
+}
diff --git a/qemu/tests/boot-sector.h b/qemu/tests/boot-sector.h
new file mode 100644
index 000000000..38be0290e
--- /dev/null
+++ b/qemu/tests/boot-sector.h
@@ -0,0 +1,26 @@
+/*
+ * QEMU boot sector testing helpers.
+ *
+ * Copyright (c) 2016 Red Hat Inc.
+ *
+ * Authors:
+ * Michael S. Tsirkin <mst@redhat.com>
+ * Victor Kaplansky <victork@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef TEST_BOOT_SECTOR
+#define TEST_BOOT_SECTOR
+
+/* Create boot disk file. */
+int boot_sector_init(const char *fname);
+
+/* Loop until signature in memory is OK. */
+void boot_sector_test(void);
+
+/* unlink boot disk file. */
+void boot_sector_cleanup(const char *fname);
+
+#endif /* TEST_BOOT_SECTOR */
diff --git a/qemu/tests/check-block.sh b/qemu/tests/check-block.sh
index b9d9c6a9f..a37797a49 100755
--- a/qemu/tests/check-block.sh
+++ b/qemu/tests/check-block.sh
@@ -9,7 +9,7 @@ if [ ! -x $QEMU_PROG ]; then
exit 1
fi
-cd $SRC_PATH/tests/qemu-iotests
+cd tests/qemu-iotests
ret=0
./check -T -nocache -raw || ret=1
diff --git a/qemu/tests/check-qdict.c b/qemu/tests/check-qdict.c
index a136f2add..a43056c5d 100644
--- a/qemu/tests/check-qdict.c
+++ b/qemu/tests/check-qdict.c
@@ -9,6 +9,7 @@
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qapi/qmp/qint.h"
diff --git a/qemu/tests/check-qfloat.c b/qemu/tests/check-qfloat.c
index 6404ac8df..3102608f5 100644
--- a/qemu/tests/check-qfloat.c
+++ b/qemu/tests/check-qfloat.c
@@ -10,6 +10,7 @@
* See the COPYING.LIB file in the top-level directory.
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qapi/qmp/qfloat.h"
diff --git a/qemu/tests/check-qint.c b/qemu/tests/check-qint.c
index 86868844a..c86f7dfa3 100644
--- a/qemu/tests/check-qint.c
+++ b/qemu/tests/check-qint.c
@@ -9,6 +9,7 @@
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qapi/qmp/qint.h"
diff --git a/qemu/tests/check-qjson.c b/qemu/tests/check-qjson.c
index 1cfffa593..99de6f525 100644
--- a/qemu/tests/check-qjson.c
+++ b/qemu/tests/check-qjson.c
@@ -10,6 +10,7 @@
* See the COPYING.LIB file in the top-level directory.
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qapi/qmp/qstring.h"
@@ -1484,6 +1485,30 @@ static void unterminated_literal(void)
g_assert(obj == NULL);
}
+static char *make_nest(char *buf, size_t cnt)
+{
+ memset(buf, '[', cnt - 1);
+ buf[cnt - 1] = '{';
+ buf[cnt] = '}';
+ memset(buf + cnt + 1, ']', cnt - 1);
+ buf[2 * cnt] = 0;
+ return buf;
+}
+
+static void limits_nesting(void)
+{
+ enum { max_nesting = 1024 }; /* see qobject/json-streamer.c */
+ char buf[2 * (max_nesting + 1) + 1];
+ QObject *obj;
+
+ obj = qobject_from_json(make_nest(buf, max_nesting));
+ g_assert(obj != NULL);
+ qobject_decref(obj);
+
+ obj = qobject_from_json(make_nest(buf, max_nesting + 1));
+ g_assert(obj == NULL);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
@@ -1519,6 +1544,7 @@ int main(int argc, char **argv)
g_test_add_func("/errors/invalid_array_comma", invalid_array_comma);
g_test_add_func("/errors/invalid_dict_comma", invalid_dict_comma);
g_test_add_func("/errors/unterminated/literal", unterminated_literal);
+ g_test_add_func("/errors/limits/nesting", limits_nesting);
return g_test_run();
}
diff --git a/qemu/tests/check-qlist.c b/qemu/tests/check-qlist.c
index b9c05d43f..f231d5fa9 100644
--- a/qemu/tests/check-qlist.c
+++ b/qemu/tests/check-qlist.c
@@ -9,6 +9,7 @@
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qapi/qmp/qint.h"
diff --git a/qemu/tests/check-qom-interface.c b/qemu/tests/check-qom-interface.c
index f06380ef1..09354deb7 100644
--- a/qemu/tests/check-qom-interface.c
+++ b/qemu/tests/check-qom-interface.c
@@ -9,6 +9,7 @@
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qom/object.h"
diff --git a/qemu/tests/check-qom-proplist.c b/qemu/tests/check-qom-proplist.c
index 7400b1fce..ffffd872f 100644
--- a/qemu/tests/check-qom-proplist.c
+++ b/qemu/tests/check-qom-proplist.c
@@ -18,8 +18,10 @@
* Author: Daniel P. Berrange <berrange@redhat.com>
*/
+#include "qemu/osdep.h"
#include <glib.h>
+#include "qapi/error.h"
#include "qom/object.h"
#include "qemu/module.h"
@@ -123,18 +125,28 @@ static void dummy_init(Object *obj)
dummy_get_bv,
dummy_set_bv,
NULL);
- object_property_add_str(obj, "sv",
- dummy_get_sv,
- dummy_set_sv,
- NULL);
- object_property_add_enum(obj, "av",
- "DummyAnimal",
- dummy_animal_map,
- dummy_get_av,
- dummy_set_av,
- NULL);
}
+
+static void dummy_class_init(ObjectClass *cls, void *data)
+{
+ object_class_property_add_bool(cls, "bv",
+ dummy_get_bv,
+ dummy_set_bv,
+ NULL);
+ object_class_property_add_str(cls, "sv",
+ dummy_get_sv,
+ dummy_set_sv,
+ NULL);
+ object_class_property_add_enum(cls, "av",
+ "DummyAnimal",
+ dummy_animal_map,
+ dummy_get_av,
+ dummy_set_av,
+ NULL);
+}
+
+
static void dummy_finalize(Object *obj)
{
DummyObject *dobj = DUMMY_OBJECT(obj);
@@ -150,8 +162,151 @@ static const TypeInfo dummy_info = {
.instance_init = dummy_init,
.instance_finalize = dummy_finalize,
.class_size = sizeof(DummyObjectClass),
+ .class_init = dummy_class_init,
+};
+
+
+/*
+ * The following 3 object classes are used to
+ * simulate the kind of relationships seen in
+ * qdev, which result in complex object
+ * property destruction ordering.
+ *
+ * DummyDev has a 'bus' child to a DummyBus
+ * DummyBus has a 'backend' child to a DummyBackend
+ * DummyDev has a 'backend' link to DummyBackend
+ *
+ * When DummyDev is finalized, it unparents the
+ * DummyBackend, which unparents the DummyDev
+ * which deletes the 'backend' link from DummyDev
+ * to DummyBackend. This illustrates that the
+ * object_property_del_all() method needs to
+ * cope with the list of properties being changed
+ * while it iterates over them.
+ */
+typedef struct DummyDev DummyDev;
+typedef struct DummyDevClass DummyDevClass;
+typedef struct DummyBus DummyBus;
+typedef struct DummyBusClass DummyBusClass;
+typedef struct DummyBackend DummyBackend;
+typedef struct DummyBackendClass DummyBackendClass;
+
+#define TYPE_DUMMY_DEV "qemu-dummy-dev"
+#define TYPE_DUMMY_BUS "qemu-dummy-bus"
+#define TYPE_DUMMY_BACKEND "qemu-dummy-backend"
+
+#define DUMMY_DEV(obj) \
+ OBJECT_CHECK(DummyDev, (obj), TYPE_DUMMY_DEV)
+#define DUMMY_BUS(obj) \
+ OBJECT_CHECK(DummyBus, (obj), TYPE_DUMMY_BUS)
+#define DUMMY_BACKEND(obj) \
+ OBJECT_CHECK(DummyBackend, (obj), TYPE_DUMMY_BACKEND)
+
+struct DummyDev {
+ Object parent_obj;
+
+ DummyBus *bus;
+};
+
+struct DummyDevClass {
+ ObjectClass parent_class;
+};
+
+struct DummyBus {
+ Object parent_obj;
+
+ DummyBackend *backend;
+};
+
+struct DummyBusClass {
+ ObjectClass parent_class;
+};
+
+struct DummyBackend {
+ Object parent_obj;
+};
+
+struct DummyBackendClass {
+ ObjectClass parent_class;
+};
+
+
+static void dummy_dev_init(Object *obj)
+{
+ DummyDev *dev = DUMMY_DEV(obj);
+ DummyBus *bus = DUMMY_BUS(object_new(TYPE_DUMMY_BUS));
+ DummyBackend *backend = DUMMY_BACKEND(object_new(TYPE_DUMMY_BACKEND));
+
+ object_property_add_child(obj, "bus", OBJECT(bus), NULL);
+ dev->bus = bus;
+ object_property_add_child(OBJECT(bus), "backend", OBJECT(backend), NULL);
+ bus->backend = backend;
+
+ object_property_add_link(obj, "backend", TYPE_DUMMY_BACKEND,
+ (Object **)&bus->backend, NULL, 0, NULL);
+}
+
+static void dummy_dev_unparent(Object *obj)
+{
+ DummyDev *dev = DUMMY_DEV(obj);
+ object_unparent(OBJECT(dev->bus));
+}
+
+static void dummy_dev_class_init(ObjectClass *klass, void *opaque)
+{
+ klass->unparent = dummy_dev_unparent;
+}
+
+
+static void dummy_bus_init(Object *obj)
+{
+}
+
+static void dummy_bus_unparent(Object *obj)
+{
+ DummyBus *bus = DUMMY_BUS(obj);
+ object_property_del(obj->parent, "backend", NULL);
+ object_unparent(OBJECT(bus->backend));
+}
+
+static void dummy_bus_class_init(ObjectClass *klass, void *opaque)
+{
+ klass->unparent = dummy_bus_unparent;
+}
+
+static void dummy_backend_init(Object *obj)
+{
+}
+
+
+static const TypeInfo dummy_dev_info = {
+ .name = TYPE_DUMMY_DEV,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(DummyDev),
+ .instance_init = dummy_dev_init,
+ .class_size = sizeof(DummyDevClass),
+ .class_init = dummy_dev_class_init,
+};
+
+static const TypeInfo dummy_bus_info = {
+ .name = TYPE_DUMMY_BUS,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(DummyBus),
+ .instance_init = dummy_bus_init,
+ .class_size = sizeof(DummyBusClass),
+ .class_init = dummy_bus_class_init,
+};
+
+static const TypeInfo dummy_backend_info = {
+ .name = TYPE_DUMMY_BACKEND,
+ .parent = TYPE_OBJECT,
+ .instance_size = sizeof(DummyBackend),
+ .instance_init = dummy_backend_init,
+ .class_size = sizeof(DummyBackendClass),
};
+
+
static void test_dummy_createv(void)
{
Error *err = NULL;
@@ -283,20 +438,82 @@ static void test_dummy_getenum(void)
&err);
g_assert(err != NULL);
error_free(err);
+
+ object_unparent(OBJECT(dobj));
}
+static void test_dummy_iterator(void)
+{
+ Object *parent = object_get_objects_root();
+ DummyObject *dobj = DUMMY_OBJECT(
+ object_new_with_props(TYPE_DUMMY,
+ parent,
+ "dummy0",
+ &error_abort,
+ "bv", "yes",
+ "sv", "Hiss hiss hiss",
+ "av", "platypus",
+ NULL));
+
+ ObjectProperty *prop;
+ ObjectPropertyIterator iter;
+ bool seenbv = false, seensv = false, seenav = false, seentype;
+
+ object_property_iter_init(&iter, OBJECT(dobj));
+ while ((prop = object_property_iter_next(&iter))) {
+ if (g_str_equal(prop->name, "bv")) {
+ seenbv = true;
+ } else if (g_str_equal(prop->name, "sv")) {
+ seensv = true;
+ } else if (g_str_equal(prop->name, "av")) {
+ seenav = true;
+ } else if (g_str_equal(prop->name, "type")) {
+ /* This prop comes from the base Object class */
+ seentype = true;
+ } else {
+ g_printerr("Found prop '%s'\n", prop->name);
+ g_assert_not_reached();
+ }
+ }
+ g_assert(seenbv);
+ g_assert(seenav);
+ g_assert(seensv);
+ g_assert(seentype);
+
+ object_unparent(OBJECT(dobj));
+}
+
+
+static void test_dummy_delchild(void)
+{
+ Object *parent = object_get_objects_root();
+ DummyDev *dev = DUMMY_DEV(
+ object_new_with_props(TYPE_DUMMY_DEV,
+ parent,
+ "dev0",
+ &error_abort,
+ NULL));
+
+ object_unparent(OBJECT(dev));
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
module_call_init(MODULE_INIT_QOM);
type_register_static(&dummy_info);
+ type_register_static(&dummy_dev_info);
+ type_register_static(&dummy_bus_info);
+ type_register_static(&dummy_backend_info);
g_test_add_func("/qom/proplist/createlist", test_dummy_createlist);
g_test_add_func("/qom/proplist/createv", test_dummy_createv);
g_test_add_func("/qom/proplist/badenum", test_dummy_badenum);
g_test_add_func("/qom/proplist/getenum", test_dummy_getenum);
+ g_test_add_func("/qom/proplist/iterator", test_dummy_iterator);
+ g_test_add_func("/qom/proplist/delchild", test_dummy_delchild);
return g_test_run();
}
diff --git a/qemu/tests/check-qstring.c b/qemu/tests/check-qstring.c
index 95dc9e3e7..9877b42c8 100644
--- a/qemu/tests/check-qstring.c
+++ b/qemu/tests/check-qstring.c
@@ -9,6 +9,7 @@
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qapi/qmp/qstring.h"
diff --git a/qemu/tests/crypto-tls-x509-helpers.c b/qemu/tests/crypto-tls-x509-helpers.c
new file mode 100644
index 000000000..64073d3bd
--- /dev/null
+++ b/qemu/tests/crypto-tls-x509-helpers.c
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#include "qemu/osdep.h"
+
+#include "crypto-tls-x509-helpers.h"
+#include "qemu/sockets.h"
+
+#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
+
+/*
+ * This stores some static data that is needed when
+ * encoding extensions in the x509 certs
+ */
+ASN1_TYPE pkix_asn1;
+
+/*
+ * To avoid consuming random entropy to generate keys,
+ * here's one we prepared earlier :-)
+ */
+gnutls_x509_privkey_t privkey;
+# define PRIVATE_KEY \
+ "-----BEGIN PRIVATE KEY-----\n" \
+ "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBALVcr\n" \
+ "BL40Tm6yq88FBhJNw1aaoCjmtg0l4dWQZ/e9Fimx4ARxFpT+ji4FE\n" \
+ "Cgl9s/SGqC+1nvlkm9ViSo0j7MKDbnDB+VRHDvMAzQhA2X7e8M0n9\n" \
+ "rPolUY2lIVC83q0BBaOBkCj2RSmT2xTEbbC2xLukSrg2WP/ihVOxc\n" \
+ "kXRuyFtzAgMBAAECgYB7slBexDwXrtItAMIH6m/U+LUpNe0Xx48OL\n" \
+ "IOn4a4whNgO/o84uIwygUK27ZGFZT0kAGAk8CdF9hA6ArcbQ62s1H\n" \
+ "myxrUbF9/mrLsQw1NEqpuUk9Ay2Tx5U/wPx35S3W/X2AvR/ZpTnCn\n" \
+ "2q/7ym9fyiSoj86drD7BTvmKXlOnOwQJBAPOFMp4mMa9NGpGuEssO\n" \
+ "m3Uwbp6lhcP0cA9MK+iOmeANpoKWfBdk5O34VbmeXnGYWEkrnX+9J\n" \
+ "bM4wVhnnBWtgBMCQQC+qAEmvwcfhauERKYznMVUVksyeuhxhCe7EK\n" \
+ "mPh+U2+g0WwdKvGDgO0PPt1gq0ILEjspMDeMHVdTwkaVBo/uMhAkA\n" \
+ "Z5SsZyCP2aTOPFDypXRdI4eqRcjaEPOUBq27r3uYb/jeboVb2weLa\n" \
+ "L1MmVuHiIHoa5clswPdWVI2y0em2IGoDAkBPSp/v9VKJEZabk9Frd\n" \
+ "a+7u4fanrM9QrEjY3KhduslSilXZZSxrWjjAJPyPiqFb3M8XXA26W\n" \
+ "nz1KYGnqYKhLcBAkB7dt57n9xfrhDpuyVEv+Uv1D3VVAhZlsaZ5Pp\n" \
+ "dcrhrkJn2sa/+O8OKvdrPSeeu/N5WwYhJf61+CPoenMp7IFci\n" \
+ "-----END PRIVATE KEY-----\n"
+
+/*
+ * This loads the private key we defined earlier
+ */
+static gnutls_x509_privkey_t test_tls_load_key(void)
+{
+ gnutls_x509_privkey_t key;
+ const gnutls_datum_t data = { (unsigned char *)PRIVATE_KEY,
+ strlen(PRIVATE_KEY) };
+ int err;
+
+ err = gnutls_x509_privkey_init(&key);
+ if (err < 0) {
+ g_critical("Failed to init key %s", gnutls_strerror(err));
+ abort();
+ }
+
+ err = gnutls_x509_privkey_import(key, &data,
+ GNUTLS_X509_FMT_PEM);
+ if (err < 0) {
+ if (err != GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR &&
+ err != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ g_critical("Failed to import key %s", gnutls_strerror(err));
+ abort();
+ }
+
+ err = gnutls_x509_privkey_import_pkcs8(
+ key, &data, GNUTLS_X509_FMT_PEM, NULL, 0);
+ if (err < 0) {
+ g_critical("Failed to import PKCS8 key %s", gnutls_strerror(err));
+ abort();
+ }
+ }
+
+ return key;
+}
+
+
+void test_tls_init(const char *keyfile)
+{
+ gnutls_global_init();
+
+ if (asn1_array2tree(pkix_asn1_tab, &pkix_asn1, NULL) != ASN1_SUCCESS) {
+ abort();
+ }
+
+ privkey = test_tls_load_key();
+ if (!g_file_set_contents(keyfile, PRIVATE_KEY, -1, NULL)) {
+ abort();
+ }
+}
+
+
+void test_tls_cleanup(const char *keyfile)
+{
+ asn1_delete_structure(&pkix_asn1);
+ unlink(keyfile);
+}
+
+/*
+ * Turns an ASN1 object into a DER encoded byte array
+ */
+static void test_tls_der_encode(ASN1_TYPE src,
+ const char *src_name,
+ gnutls_datum_t *res)
+{
+ int size;
+ char *data = NULL;
+
+ size = 0;
+ asn1_der_coding(src, src_name, NULL, &size, NULL);
+
+ data = g_new0(char, size);
+
+ asn1_der_coding(src, src_name, data, &size, NULL);
+
+ res->data = (unsigned char *)data;
+ res->size = size;
+}
+
+
+static void
+test_tls_get_ipaddr(const char *addrstr,
+ char **data,
+ int *datalen)
+{
+ struct addrinfo *res;
+ struct addrinfo hints;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+ g_assert(getaddrinfo(addrstr, NULL, &hints, &res) == 0);
+
+ *datalen = res->ai_addrlen;
+ *data = g_new(char, *datalen);
+ memcpy(*data, res->ai_addr, *datalen);
+ freeaddrinfo(res);
+}
+
+/*
+ * This is a fairly lame x509 certificate generator.
+ *
+ * Do not copy/use this code for generating real certificates
+ * since it leaves out many things that you would want in
+ * certificates for real world usage.
+ *
+ * This is good enough only for doing tests of the QEMU
+ * TLS certificate code
+ */
+void
+test_tls_generate_cert(QCryptoTLSTestCertReq *req,
+ gnutls_x509_crt_t ca)
+{
+ gnutls_x509_crt_t crt;
+ int err;
+ static char buffer[1024 * 1024];
+ size_t size = sizeof(buffer);
+ char serial[5] = { 1, 2, 3, 4, 0 };
+ gnutls_datum_t der;
+ time_t start = time(NULL) + (60 * 60 * req->start_offset);
+ time_t expire = time(NULL) + (60 * 60 * (req->expire_offset
+ ? req->expire_offset : 24));
+
+ /*
+ * Prepare our new certificate object
+ */
+ err = gnutls_x509_crt_init(&crt);
+ if (err < 0) {
+ g_critical("Failed to initialize certificate %s", gnutls_strerror(err));
+ abort();
+ }
+ err = gnutls_x509_crt_set_key(crt, privkey);
+ if (err < 0) {
+ g_critical("Failed to set certificate key %s", gnutls_strerror(err));
+ abort();
+ }
+
+ /*
+ * A v3 certificate is required in order to be able
+ * set any of the basic constraints, key purpose and
+ * key usage data
+ */
+ gnutls_x509_crt_set_version(crt, 3);
+
+ if (req->country) {
+ err = gnutls_x509_crt_set_dn_by_oid(
+ crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
+ req->country, strlen(req->country));
+ if (err < 0) {
+ g_critical("Failed to set certificate country name %s",
+ gnutls_strerror(err));
+ abort();
+ }
+ }
+ if (req->cn) {
+ err = gnutls_x509_crt_set_dn_by_oid(
+ crt, GNUTLS_OID_X520_COMMON_NAME, 0,
+ req->cn, strlen(req->cn));
+ if (err < 0) {
+ g_critical("Failed to set certificate common name %s",
+ gnutls_strerror(err));
+ abort();
+ }
+ }
+
+ /*
+ * Setup the subject altnames, which are used
+ * for hostname checks in live sessions
+ */
+ if (req->altname1) {
+ err = gnutls_x509_crt_set_subject_alt_name(
+ crt, GNUTLS_SAN_DNSNAME,
+ req->altname1,
+ strlen(req->altname1),
+ GNUTLS_FSAN_APPEND);
+ if (err < 0) {
+ g_critical("Failed to set certificate alt name %s",
+ gnutls_strerror(err));
+ abort();
+ }
+ }
+ if (req->altname2) {
+ err = gnutls_x509_crt_set_subject_alt_name(
+ crt, GNUTLS_SAN_DNSNAME,
+ req->altname2,
+ strlen(req->altname2),
+ GNUTLS_FSAN_APPEND);
+ if (err < 0) {
+ g_critical("Failed to set certificate %s alt name",
+ gnutls_strerror(err));
+ abort();
+ }
+ }
+
+ /*
+ * IP address need to be put into the cert in their
+ * raw byte form, not strings, hence this is a little
+ * more complicated
+ */
+ if (req->ipaddr1) {
+ char *data;
+ int len;
+
+ test_tls_get_ipaddr(req->ipaddr1, &data, &len);
+
+ err = gnutls_x509_crt_set_subject_alt_name(
+ crt, GNUTLS_SAN_IPADDRESS,
+ data, len, GNUTLS_FSAN_APPEND);
+ if (err < 0) {
+ g_critical("Failed to set certificate alt name %s",
+ gnutls_strerror(err));
+ abort();
+ }
+ g_free(data);
+ }
+ if (req->ipaddr2) {
+ char *data;
+ int len;
+
+ test_tls_get_ipaddr(req->ipaddr2, &data, &len);
+
+ err = gnutls_x509_crt_set_subject_alt_name(
+ crt, GNUTLS_SAN_IPADDRESS,
+ data, len, GNUTLS_FSAN_APPEND);
+ if (err < 0) {
+ g_critical("Failed to set certificate alt name %s",
+ gnutls_strerror(err));
+ abort();
+ }
+ g_free(data);
+ }
+
+
+ /*
+ * Basic constraints are used to decide if the cert
+ * is for a CA or not. We can't use the convenient
+ * gnutls API for setting this, since it hardcodes
+ * the 'critical' field which we want control over
+ */
+ if (req->basicConstraintsEnable) {
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+
+ asn1_create_element(pkix_asn1, "PKIX1.BasicConstraints", &ext);
+ asn1_write_value(ext, "cA",
+ req->basicConstraintsIsCA ? "TRUE" : "FALSE", 1);
+ asn1_write_value(ext, "pathLenConstraint", NULL, 0);
+ test_tls_der_encode(ext, "", &der);
+ err = gnutls_x509_crt_set_extension_by_oid(
+ crt, "2.5.29.19",
+ der.data, der.size,
+ req->basicConstraintsCritical);
+ if (err < 0) {
+ g_critical("Failed to set certificate basic constraints %s",
+ gnutls_strerror(err));
+ g_free(der.data);
+ abort();
+ }
+ asn1_delete_structure(&ext);
+ g_free(der.data);
+ }
+
+ /*
+ * Next up the key usage extension. Again we can't
+ * use the gnutls API since it hardcodes the extension
+ * to be 'critical'
+ */
+ if (req->keyUsageEnable) {
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+ char str[2];
+
+ str[0] = req->keyUsageValue & 0xff;
+ str[1] = (req->keyUsageValue >> 8) & 0xff;
+
+ asn1_create_element(pkix_asn1, "PKIX1.KeyUsage", &ext);
+ asn1_write_value(ext, "", str, 9);
+ test_tls_der_encode(ext, "", &der);
+ err = gnutls_x509_crt_set_extension_by_oid(
+ crt, "2.5.29.15",
+ der.data, der.size,
+ req->keyUsageCritical);
+ if (err < 0) {
+ g_critical("Failed to set certificate key usage %s",
+ gnutls_strerror(err));
+ g_free(der.data);
+ abort();
+ }
+ asn1_delete_structure(&ext);
+ g_free(der.data);
+ }
+
+ /*
+ * Finally the key purpose extension. This time
+ * gnutls has the opposite problem, always hardcoding
+ * it to be non-critical. So once again we have to
+ * set this the hard way building up ASN1 data ourselves
+ */
+ if (req->keyPurposeEnable) {
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+
+ asn1_create_element(pkix_asn1, "PKIX1.ExtKeyUsageSyntax", &ext);
+ if (req->keyPurposeOID1) {
+ asn1_write_value(ext, "", "NEW", 1);
+ asn1_write_value(ext, "?LAST", req->keyPurposeOID1, 1);
+ }
+ if (req->keyPurposeOID2) {
+ asn1_write_value(ext, "", "NEW", 1);
+ asn1_write_value(ext, "?LAST", req->keyPurposeOID2, 1);
+ }
+ test_tls_der_encode(ext, "", &der);
+ err = gnutls_x509_crt_set_extension_by_oid(
+ crt, "2.5.29.37",
+ der.data, der.size,
+ req->keyPurposeCritical);
+ if (err < 0) {
+ g_critical("Failed to set certificate key purpose %s",
+ gnutls_strerror(err));
+ g_free(der.data);
+ abort();
+ }
+ asn1_delete_structure(&ext);
+ g_free(der.data);
+ }
+
+ /*
+ * Any old serial number will do, so lets pick 5
+ */
+ err = gnutls_x509_crt_set_serial(crt, serial, 5);
+ if (err < 0) {
+ g_critical("Failed to set certificate serial %s",
+ gnutls_strerror(err));
+ abort();
+ }
+
+ err = gnutls_x509_crt_set_activation_time(crt, start);
+ if (err < 0) {
+ g_critical("Failed to set certificate activation %s",
+ gnutls_strerror(err));
+ abort();
+ }
+ err = gnutls_x509_crt_set_expiration_time(crt, expire);
+ if (err < 0) {
+ g_critical("Failed to set certificate expiration %s",
+ gnutls_strerror(err));
+ abort();
+ }
+
+
+ /*
+ * If no 'ca' is set then we are self signing
+ * the cert. This is done for the root CA certs
+ */
+ err = gnutls_x509_crt_sign(crt, ca ? ca : crt, privkey);
+ if (err < 0) {
+ g_critical("Failed to sign certificate %s",
+ gnutls_strerror(err));
+ abort();
+ }
+
+ /*
+ * Finally write the new cert out to disk
+ */
+ err = gnutls_x509_crt_export(
+ crt, GNUTLS_X509_FMT_PEM, buffer, &size);
+ if (err < 0) {
+ g_critical("Failed to export certificate %s: %d",
+ gnutls_strerror(err), err);
+ abort();
+ }
+
+ if (!g_file_set_contents(req->filename, buffer, -1, NULL)) {
+ g_critical("Failed to write certificate %s",
+ req->filename);
+ abort();
+ }
+
+ req->crt = crt;
+}
+
+
+void test_tls_write_cert_chain(const char *filename,
+ gnutls_x509_crt_t *certs,
+ size_t ncerts)
+{
+ size_t i;
+ size_t capacity = 1024, offset = 0;
+ char *buffer = g_new0(char, capacity);
+ int err;
+
+ for (i = 0; i < ncerts; i++) {
+ size_t len = capacity - offset;
+ retry:
+ err = gnutls_x509_crt_export(certs[i], GNUTLS_X509_FMT_PEM,
+ buffer + offset, &len);
+ if (err < 0) {
+ if (err == GNUTLS_E_SHORT_MEMORY_BUFFER) {
+ buffer = g_renew(char, buffer, offset + len);
+ capacity = offset + len;
+ goto retry;
+ }
+ g_critical("Failed to export certificate chain %s: %d",
+ gnutls_strerror(err), err);
+ abort();
+ }
+ offset += len;
+ }
+
+ if (!g_file_set_contents(filename, buffer, offset, NULL)) {
+ abort();
+ }
+ g_free(buffer);
+}
+
+
+void test_tls_discard_cert(QCryptoTLSTestCertReq *req)
+{
+ if (!req->crt) {
+ return;
+ }
+
+ gnutls_x509_crt_deinit(req->crt);
+ req->crt = NULL;
+
+ if (getenv("QEMU_TEST_DEBUG_CERTS") == NULL) {
+ unlink(req->filename);
+ }
+}
+
+#endif /* QCRYPTO_HAVE_TLS_TEST_SUPPORT */
diff --git a/qemu/tests/crypto-tls-x509-helpers.h b/qemu/tests/crypto-tls-x509-helpers.h
new file mode 100644
index 000000000..356b49cd5
--- /dev/null
+++ b/qemu/tests/crypto-tls-x509-helpers.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+
+#if !(defined WIN32) && \
+ defined(CONFIG_TASN1) && \
+ defined(LIBGNUTLS_VERSION_NUMBER) && \
+ (LIBGNUTLS_VERSION_NUMBER >= 0x020600)
+# define QCRYPTO_HAVE_TLS_TEST_SUPPORT
+#endif
+
+#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
+# include <libtasn1.h>
+
+# include "qemu-common.h"
+
+/*
+ * This contains parameter about how to generate
+ * certificates.
+ */
+typedef struct QCryptoTLSTestCertReq QCryptoTLSTestCertReq;
+struct QCryptoTLSTestCertReq {
+ gnutls_x509_crt_t crt;
+
+ const char *filename;
+
+ /* Identifying information */
+ const char *country;
+ const char *cn;
+ const char *altname1;
+ const char *altname2;
+ const char *ipaddr1;
+ const char *ipaddr2;
+
+ /* Basic constraints */
+ bool basicConstraintsEnable;
+ bool basicConstraintsCritical;
+ bool basicConstraintsIsCA;
+
+ /* Key usage */
+ bool keyUsageEnable;
+ bool keyUsageCritical;
+ int keyUsageValue;
+
+ /* Key purpose (aka Extended key usage) */
+ bool keyPurposeEnable;
+ bool keyPurposeCritical;
+ const char *keyPurposeOID1;
+ const char *keyPurposeOID2;
+
+ /* zero for current time, or non-zero for hours from now */
+ int start_offset;
+ /* zero for 24 hours from now, or non-zero for hours from now */
+ int expire_offset;
+};
+
+void test_tls_generate_cert(QCryptoTLSTestCertReq *req,
+ gnutls_x509_crt_t ca);
+void test_tls_write_cert_chain(const char *filename,
+ gnutls_x509_crt_t *certs,
+ size_t ncerts);
+void test_tls_discard_cert(QCryptoTLSTestCertReq *req);
+
+void test_tls_init(const char *keyfile);
+void test_tls_cleanup(const char *keyfile);
+
+# define TLS_CERT_REQ(varname, cavarname, \
+ country, commonname, \
+ altname1, altname2, \
+ ipaddr1, ipaddr2, \
+ basicconsenable, basicconscritical, basicconsca, \
+ keyusageenable, keyusagecritical, keyusagevalue, \
+ keypurposeenable, keypurposecritical, \
+ keypurposeoid1, keypurposeoid2, \
+ startoffset, endoffset) \
+ static QCryptoTLSTestCertReq varname = { \
+ NULL, WORKDIR #varname "-ctx.pem", \
+ country, commonname, altname1, altname2, \
+ ipaddr1, ipaddr2, \
+ basicconsenable, basicconscritical, basicconsca, \
+ keyusageenable, keyusagecritical, keyusagevalue, \
+ keypurposeenable, keypurposecritical, \
+ keypurposeoid1, keypurposeoid2, \
+ startoffset, endoffset \
+ }; \
+ test_tls_generate_cert(&varname, cavarname.crt)
+
+# define TLS_ROOT_REQ(varname, \
+ country, commonname, \
+ altname1, altname2, \
+ ipaddr1, ipaddr2, \
+ basicconsenable, basicconscritical, basicconsca, \
+ keyusageenable, keyusagecritical, keyusagevalue, \
+ keypurposeenable, keypurposecritical, \
+ keypurposeoid1, keypurposeoid2, \
+ startoffset, endoffset) \
+ static QCryptoTLSTestCertReq varname = { \
+ NULL, WORKDIR #varname "-ctx.pem", \
+ country, commonname, altname1, altname2, \
+ ipaddr1, ipaddr2, \
+ basicconsenable, basicconscritical, basicconsca, \
+ keyusageenable, keyusagecritical, keyusagevalue, \
+ keypurposeenable, keypurposecritical, \
+ keypurposeoid1, keypurposeoid2, \
+ startoffset, endoffset \
+ }; \
+ test_tls_generate_cert(&varname, NULL)
+
+extern const ASN1_ARRAY_TYPE pkix_asn1_tab[];
+
+#endif /* QCRYPTO_HAVE_TLS_TEST_SUPPORT */
diff --git a/qemu/tests/device-introspect-test.c b/qemu/tests/device-introspect-test.c
new file mode 100644
index 000000000..447792601
--- /dev/null
+++ b/qemu/tests/device-introspect-test.c
@@ -0,0 +1,124 @@
+/*
+ * Device introspection test cases
+ *
+ * Copyright (c) 2015 Red Hat Inc.
+ *
+ * Authors:
+ * Markus Armbruster <armbru@redhat.com>,
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+/*
+ * Covers QMP device-list-properties and HMP device_add help. We
+ * currently don't check that their output makes sense, only that QEMU
+ * survives. Useful since we've had an astounding number of crash
+ * bugs around here.
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+#include "qemu-common.h"
+#include "qapi/qmp/qstring.h"
+#include "libqtest.h"
+
+const char common_args[] = "-nodefaults -machine none";
+
+static QList *device_type_list(bool abstract)
+{
+ QDict *resp;
+ QList *ret;
+
+ resp = qmp("{'execute': 'qom-list-types',"
+ " 'arguments': {'implements': 'device', 'abstract': %i}}",
+ abstract);
+ g_assert(qdict_haskey(resp, "return"));
+ ret = qdict_get_qlist(resp, "return");
+ QINCREF(ret);
+ QDECREF(resp);
+ return ret;
+}
+
+static void test_one_device(const char *type)
+{
+ QDict *resp;
+ char *help, *qom_tree;
+
+ resp = qmp("{'execute': 'device-list-properties',"
+ " 'arguments': {'typename': %s}}",
+ type);
+ QDECREF(resp);
+
+ help = hmp("device_add \"%s,help\"", type);
+ g_free(help);
+
+ /*
+ * Some devices leave dangling pointers in QOM behind.
+ * "info qom-tree" has a good chance at crashing then
+ */
+ qom_tree = hmp("info qom-tree");
+ g_free(qom_tree);
+}
+
+static void test_device_intro_list(void)
+{
+ QList *types;
+ char *help;
+
+ qtest_start(common_args);
+
+ types = device_type_list(true);
+ QDECREF(types);
+
+ help = hmp("device_add help");
+ g_free(help);
+
+ qtest_end();
+}
+
+static void test_device_intro_none(void)
+{
+ qtest_start(common_args);
+ test_one_device("nonexistent");
+ qtest_end();
+}
+
+static void test_device_intro_abstract(void)
+{
+ qtest_start(common_args);
+ test_one_device("device");
+ qtest_end();
+}
+
+static void test_device_intro_concrete(void)
+{
+ QList *types;
+ QListEntry *entry;
+ const char *type;
+
+ qtest_start(common_args);
+ types = device_type_list(false);
+
+ QLIST_FOREACH_ENTRY(types, entry) {
+ type = qdict_get_try_str(qobject_to_qdict(qlist_entry_obj(entry)),
+ "name");
+ g_assert(type);
+ test_one_device(type);
+ }
+
+ QDECREF(types);
+ qtest_end();
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_func("device/introspect/list", test_device_intro_list);
+ qtest_add_func("device/introspect/none", test_device_intro_none);
+ qtest_add_func("device/introspect/abstract", test_device_intro_abstract);
+ qtest_add_func("device/introspect/concrete", test_device_intro_concrete);
+
+ return g_test_run();
+}
diff --git a/qemu/tests/display-vga-test.c b/qemu/tests/display-vga-test.c
index 7694344ea..5706d338a 100644
--- a/qemu/tests/display-vga-test.c
+++ b/qemu/tests/display-vga-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
static void pci_cirrus(void)
{
diff --git a/qemu/tests/drive_del-test.c b/qemu/tests/drive_del-test.c
index 8951f6f61..fe03236f3 100644
--- a/qemu/tests/drive_del-test.c
+++ b/qemu/tests/drive_del-test.c
@@ -10,34 +10,24 @@
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
static void drive_add(void)
{
- QDict *response;
+ char *resp = hmp("drive_add 0 if=none,id=drive0");
- response = qmp("{'execute': 'human-monitor-command',"
- " 'arguments': {"
- " 'command-line': 'drive_add 0 if=none,id=drive0'"
- "}}");
- g_assert(response);
- g_assert_cmpstr(qdict_get_try_str(response, "return"), ==, "OK\r\n");
- QDECREF(response);
+ g_assert_cmpstr(resp, ==, "OK\r\n");
+ g_free(resp);
}
static void drive_del(void)
{
- QDict *response;
+ char *resp = hmp("drive_del drive0");
- response = qmp("{'execute': 'human-monitor-command',"
- " 'arguments': {"
- " 'command-line': 'drive_del drive0'"
- "}}");
- g_assert(response);
- g_assert_cmpstr(qdict_get_try_str(response, "return"), ==, "");
- QDECREF(response);
+ g_assert_cmpstr(resp, ==, "");
+ g_free(resp);
}
static void device_del(void)
diff --git a/qemu/tests/ds1338-test.c b/qemu/tests/ds1338-test.c
new file mode 100644
index 000000000..279241584
--- /dev/null
+++ b/qemu/tests/ds1338-test.c
@@ -0,0 +1,79 @@
+/*
+ * QTest testcase for the DS1338 RTC
+ *
+ * Copyright (c) 2013 Jean-Christophe Dubois
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "libqos/i2c.h"
+
+#include <glib.h>
+
+#define IMX25_I2C_0_BASE 0x43F80000
+
+#define DS1338_ADDR 0x68
+
+static I2CAdapter *i2c;
+static uint8_t addr;
+
+static inline uint8_t bcd2bin(uint8_t x)
+{
+ return ((x) & 0x0f) + ((x) >> 4) * 10;
+}
+
+static void send_and_receive(void)
+{
+ uint8_t cmd[1];
+ uint8_t resp[7];
+ time_t now = time(NULL);
+ struct tm *tm_ptr = gmtime(&now);
+
+ /* reset the index in the RTC memory */
+ cmd[0] = 0;
+ i2c_send(i2c, addr, cmd, 1);
+
+ /* retrieve the date */
+ i2c_recv(i2c, addr, resp, 7);
+
+ /* check retrieved time againt local time */
+ g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday);
+ g_assert_cmpuint(bcd2bin(resp[5]), == , 1 + tm_ptr->tm_mon);
+ g_assert_cmpuint(2000 + bcd2bin(resp[6]), == , 1900 + tm_ptr->tm_year);
+}
+
+int main(int argc, char **argv)
+{
+ QTestState *s = NULL;
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+
+ s = qtest_start("-display none -machine imx25-pdk");
+ i2c = imx_i2c_create(IMX25_I2C_0_BASE);
+ addr = DS1338_ADDR;
+
+ qtest_add_func("/ds1338/tx-rx", send_and_receive);
+
+ ret = g_test_run();
+
+ if (s) {
+ qtest_quit(s);
+ }
+ g_free(i2c);
+
+ return ret;
+}
diff --git a/qemu/tests/e1000-test.c b/qemu/tests/e1000-test.c
index 7ca6d7e72..a42b3810c 100644
--- a/qemu/tests/e1000-test.c
+++ b/qemu/tests/e1000-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void test_device(gconstpointer data)
diff --git a/qemu/tests/eepro100-test.c b/qemu/tests/eepro100-test.c
index 8bfaccdcb..e17eed0b7 100644
--- a/qemu/tests/eepro100-test.c
+++ b/qemu/tests/eepro100-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
static void test_device(gconstpointer data)
{
diff --git a/qemu/tests/endianness-test.c b/qemu/tests/endianness-test.c
index 2054338e1..cc5bccd88 100644
--- a/qemu/tests/endianness-test.c
+++ b/qemu/tests/endianness-test.c
@@ -11,11 +11,8 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
#include "libqtest.h"
#include "qemu/bswap.h"
diff --git a/qemu/tests/es1370-test.c b/qemu/tests/es1370-test.c
index cc23fb5c6..824dc31c6 100644
--- a/qemu/tests/es1370-test.c
+++ b/qemu/tests/es1370-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void nop(void)
diff --git a/qemu/tests/fdc-test.c b/qemu/tests/fdc-test.c
index 416394fc7..53df1d0d8 100644
--- a/qemu/tests/fdc-test.c
+++ b/qemu/tests/fdc-test.c
@@ -22,9 +22,7 @@
* THE SOFTWARE.
*/
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
+#include "qemu/osdep.h"
#include <glib.h>
@@ -267,7 +265,7 @@ static void test_cmos(void)
uint8_t cmos;
cmos = cmos_read(CMOS_FLOPPY);
- g_assert(cmos == 0x40);
+ g_assert(cmos == 0x40 || cmos == 0x50);
}
static void test_no_media_on_start(void)
@@ -304,9 +302,6 @@ static void test_media_insert(void)
qmp_discard_response("{'execute':'change', 'arguments':{"
" 'device':'floppy0', 'target': %s, 'arg': 'raw' }}",
test_image);
- qmp_discard_response(""); /* ignore event
- (FIXME open -> open transition?!) */
- qmp_discard_response(""); /* ignore event */
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
@@ -337,7 +332,6 @@ static void test_media_change(void)
* reset the bit. */
qmp_discard_response("{'execute':'eject', 'arguments':{"
" 'device':'floppy0' }}");
- qmp_discard_response(""); /* ignore event */
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
diff --git a/qemu/tests/fw_cfg-test.c b/qemu/tests/fw_cfg-test.c
index 9be78e956..b4392c2d3 100644
--- a/qemu/tests/fw_cfg-test.c
+++ b/qemu/tests/fw_cfg-test.c
@@ -10,12 +10,11 @@
* See the COPYING file in the top-level directory.
*/
-#include <string.h>
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqtest.h"
-#define NO_QEMU_PROTOS
-#include "hw/nvram/fw_cfg.h"
+#include "hw/nvram/fw_cfg_keys.h"
#include "libqos/fw_cfg.h"
static uint64_t ram_size = 128 << 20;
@@ -37,7 +36,9 @@ static void test_fw_cfg_signature(void)
static void test_fw_cfg_id(void)
{
- g_assert_cmpint(qfw_cfg_get_u32(fw_cfg, FW_CFG_ID), ==, 1);
+ uint32_t id = qfw_cfg_get_u32(fw_cfg, FW_CFG_ID);
+ g_assert((id == 1) ||
+ (id == 3));
}
static void test_fw_cfg_uuid(void)
diff --git a/qemu/tests/guest-debug/test-gdbstub.py b/qemu/tests/guest-debug/test-gdbstub.py
new file mode 100644
index 000000000..31ba6c943
--- /dev/null
+++ b/qemu/tests/guest-debug/test-gdbstub.py
@@ -0,0 +1,176 @@
+#
+# This script needs to be run on startup
+# qemu -kernel ${KERNEL} -s -S
+# and then:
+# gdb ${KERNEL}.vmlinux -x ${QEMU_SRC}/tests/guest-debug/test-gdbstub.py
+
+import gdb
+
+failcount = 0
+
+
+def report(cond, msg):
+ "Report success/fail of test"
+ if cond:
+ print ("PASS: %s" % (msg))
+ else:
+ print ("FAIL: %s" % (msg))
+ failcount += 1
+
+
+def check_step():
+ "Step an instruction, check it moved."
+ start_pc = gdb.parse_and_eval('$pc')
+ gdb.execute("si")
+ end_pc = gdb.parse_and_eval('$pc')
+
+ return not (start_pc == end_pc)
+
+
+def check_break(sym_name):
+ "Setup breakpoint, continue and check we stopped."
+ sym, ok = gdb.lookup_symbol(sym_name)
+ bp = gdb.Breakpoint(sym_name)
+
+ gdb.execute("c")
+
+ # hopefully we came back
+ end_pc = gdb.parse_and_eval('$pc')
+ print ("%s == %s %d" % (end_pc, sym.value(), bp.hit_count))
+ bp.delete()
+
+ # can we test we hit bp?
+ return end_pc == sym.value()
+
+
+# We need to do hbreak manually as the python interface doesn't export it
+def check_hbreak(sym_name):
+ "Setup hardware breakpoint, continue and check we stopped."
+ sym, ok = gdb.lookup_symbol(sym_name)
+ gdb.execute("hbreak %s" % (sym_name))
+ gdb.execute("c")
+
+ # hopefully we came back
+ end_pc = gdb.parse_and_eval('$pc')
+ print ("%s == %s" % (end_pc, sym.value()))
+
+ if end_pc == sym.value():
+ gdb.execute("d 1")
+ return True
+ else:
+ return False
+
+
+class WatchPoint(gdb.Breakpoint):
+
+ def get_wpstr(self, sym_name):
+ "Setup sym and wp_str for given symbol."
+ self.sym, ok = gdb.lookup_symbol(sym_name)
+ wp_addr = gdb.parse_and_eval(sym_name).address
+ self.wp_str = '*(%(type)s)(&%(address)s)' % dict(
+ type = wp_addr.type, address = sym_name)
+
+ return(self.wp_str)
+
+ def __init__(self, sym_name, type):
+ wp_str = self.get_wpstr(sym_name)
+ super(WatchPoint, self).__init__(wp_str, gdb.BP_WATCHPOINT, type)
+
+ def stop(self):
+ end_pc = gdb.parse_and_eval('$pc')
+ print ("HIT WP @ %s" % (end_pc))
+ return True
+
+
+def do_one_watch(sym, wtype, text):
+
+ wp = WatchPoint(sym, wtype)
+ gdb.execute("c")
+ report_str = "%s for %s (%s)" % (text, sym, wp.sym.value())
+
+ if wp.hit_count > 0:
+ report(True, report_str)
+ wp.delete()
+ else:
+ report(False, report_str)
+
+
+def check_watches(sym_name):
+ "Watch a symbol for any access."
+
+ # Should hit for any read
+ do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
+
+ # Again should hit for reads
+ do_one_watch(sym_name, gdb.WP_READ, "rwatch")
+
+ # Finally when it is written
+ do_one_watch(sym_name, gdb.WP_WRITE, "watch")
+
+
+class CatchBreakpoint(gdb.Breakpoint):
+ def __init__(self, sym_name):
+ super(CatchBreakpoint, self).__init__(sym_name)
+ self.sym, ok = gdb.lookup_symbol(sym_name)
+
+ def stop(self):
+ end_pc = gdb.parse_and_eval('$pc')
+ print ("CB: %s == %s" % (end_pc, self.sym.value()))
+ if end_pc == self.sym.value():
+ report(False, "Hit final catchpoint")
+
+
+def run_test():
+ "Run throught the tests one by one"
+
+ print ("Checking we can step the first few instructions")
+ step_ok = 0
+ for i in range(3):
+ if check_step():
+ step_ok += 1
+
+ report(step_ok == 3, "single step in boot code")
+
+ print ("Checking HW breakpoint works")
+ break_ok = check_hbreak("kernel_init")
+ report(break_ok, "hbreak @ kernel_init")
+
+ # Can't set this up until we are in the kernel proper
+ # if we make it to run_init_process we've over-run and
+ # one of the tests failed
+ print ("Setup catch-all for run_init_process")
+ cbp = CatchBreakpoint("run_init_process")
+ cpb2 = CatchBreakpoint("try_to_run_init_process")
+
+ print ("Checking Normal breakpoint works")
+ break_ok = check_break("wait_for_completion")
+ report(break_ok, "break @ wait_for_completion")
+
+ print ("Checking watchpoint works")
+ check_watches("system_state")
+
+#
+# This runs as the script it sourced (via -x)
+#
+
+try:
+ print ("Connecting to remote")
+ gdb.execute("target remote localhost:1234")
+
+ # These are not very useful in scripts
+ gdb.execute("set pagination off")
+ gdb.execute("set confirm off")
+
+ # Run the actual tests
+ run_test()
+
+except:
+ print ("GDB Exception: %s" % (sys.exc_info()[0]))
+ failcount += 1
+ import code
+ code.InteractiveConsole(locals=globals()).interact()
+ raise
+
+# Finally kill the inferior and exit gdb with a count of failures
+gdb.execute("kill")
+exit(failcount)
diff --git a/qemu/tests/hd-geo-test.c b/qemu/tests/hd-geo-test.c
index 00afc209e..c8e669ac2 100644
--- a/qemu/tests/hd-geo-test.c
+++ b/qemu/tests/hd-geo-test.c
@@ -15,10 +15,8 @@
* Improvements welcome.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
#include "qemu-common.h"
#include "libqtest.h"
@@ -206,13 +204,13 @@ static int setup_ide(int argc, char *argv[], int argv_sz,
{
char *s1, *s2, *s3;
- s1 = g_strdup_printf("-drive id=drive%d,if=%s,format=raw",
+ s1 = g_strdup_printf("-drive id=drive%d,if=%s",
ide_idx, dev ? "none" : "ide");
s2 = dev ? g_strdup("") : g_strdup_printf(",index=%d", ide_idx);
if (img_secs[img_idx] >= 0) {
setup_mbr(img_idx, mbr);
- s3 = g_strdup_printf(",file=%s", img_file_name[img_idx]);
+ s3 = g_strdup_printf(",format=raw,file=%s", img_file_name[img_idx]);
} else {
s3 = g_strdup(",media=cdrom");
}
diff --git a/qemu/tests/i440fx-test.c b/qemu/tests/i440fx-test.c
index d0bc8de25..05029e90b 100644
--- a/qemu/tests/i440fx-test.c
+++ b/qemu/tests/i440fx-test.c
@@ -12,13 +12,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <errno.h>
#include <sys/mman.h>
-#include <stdlib.h>
#include "libqtest.h"
#include "libqos/pci.h"
@@ -27,8 +23,6 @@
#define BROKEN 1
-#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
-
typedef struct TestData
{
int num_cpus;
@@ -191,7 +185,7 @@ static void write_area(uint32_t start, uint32_t end, uint8_t value)
uint32_t size = end - start + 1;
uint8_t *data;
- data = g_malloc0(size);
+ data = g_malloc(size);
memset(data, value, size);
memwrite(start, data, size);
diff --git a/qemu/tests/i82801b11-test.c b/qemu/tests/i82801b11-test.c
index 78d9ce0e6..c3b5ebbca 100644
--- a/qemu/tests/i82801b11-test.c
+++ b/qemu/tests/i82801b11-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void nop(void)
diff --git a/qemu/tests/ide-test.c b/qemu/tests/ide-test.c
index 4a07e3a9d..0d9ab4df9 100644
--- a/qemu/tests/ide-test.c
+++ b/qemu/tests/ide-test.c
@@ -22,9 +22,7 @@
* THE SOFTWARE.
*/
-#include <stdint.h>
-#include <string.h>
-#include <stdio.h>
+#include "qemu/osdep.h"
#include <glib.h>
@@ -45,8 +43,15 @@
#define IDE_BASE 0x1f0
#define IDE_PRIMARY_IRQ 14
+#define ATAPI_BLOCK_SIZE 2048
+
+/* How many bytes to receive via ATAPI PIO at one time.
+ * Must be less than 0xFFFF. */
+#define BYTE_COUNT_LIMIT 5120
+
enum {
reg_data = 0x0,
+ reg_feature = 0x1,
reg_nsectors = 0x2,
reg_lba_low = 0x3,
reg_lba_middle = 0x4,
@@ -80,6 +85,7 @@ enum {
CMD_WRITE_DMA = 0xca,
CMD_FLUSH_CACHE = 0xe7,
CMD_IDENTIFY = 0xec,
+ CMD_PACKET = 0xa0,
CMDF_ABORT = 0x100,
CMDF_NO_BM = 0x200,
@@ -172,7 +178,8 @@ typedef struct PrdtEntry {
#define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
- PrdtEntry *prdt, int prdt_entries)
+ PrdtEntry *prdt, int prdt_entries,
+ void(*post_exec)(uint64_t sector, int nb_sectors))
{
QPCIDevice *dev;
uint16_t bmdma_base;
@@ -189,6 +196,9 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
switch (cmd) {
case CMD_READ_DMA:
+ case CMD_PACKET:
+ /* Assuming we only test data reads w/ ATAPI, otherwise we need to know
+ * the SCSI command being sent in the packet, too. */
from_dev = true;
break;
case CMD_WRITE_DMA:
@@ -217,14 +227,22 @@ static int send_dma_request(int cmd, uint64_t sector, int nb_sectors,
outl(bmdma_base + bmreg_prdt, guest_prdt);
/* ATA DMA command */
- outb(IDE_BASE + reg_nsectors, nb_sectors);
-
- outb(IDE_BASE + reg_lba_low, sector & 0xff);
- outb(IDE_BASE + reg_lba_middle, (sector >> 8) & 0xff);
- outb(IDE_BASE + reg_lba_high, (sector >> 16) & 0xff);
+ if (cmd == CMD_PACKET) {
+ /* Enables ATAPI DMA; otherwise PIO is attempted */
+ outb(IDE_BASE + reg_feature, 0x01);
+ } else {
+ outb(IDE_BASE + reg_nsectors, nb_sectors);
+ outb(IDE_BASE + reg_lba_low, sector & 0xff);
+ outb(IDE_BASE + reg_lba_middle, (sector >> 8) & 0xff);
+ outb(IDE_BASE + reg_lba_high, (sector >> 16) & 0xff);
+ }
outb(IDE_BASE + reg_command, cmd);
+ if (post_exec) {
+ post_exec(sector, nb_sectors);
+ }
+
/* Start DMA transfer */
outb(bmdma_base + bmreg_cmd, BM_CMD_START | (from_dev ? BM_CMD_WRITE : 0));
@@ -278,7 +296,8 @@ static void test_bmdma_simple_rw(void)
memset(buf, 0x55, len);
memwrite(guest_buf, buf, len);
- status = send_dma_request(CMD_WRITE_DMA, 0, 1, prdt, ARRAY_SIZE(prdt));
+ status = send_dma_request(CMD_WRITE_DMA, 0, 1, prdt,
+ ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, BM_STS_INTR);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
@@ -286,14 +305,15 @@ static void test_bmdma_simple_rw(void)
memset(buf, 0xaa, len);
memwrite(guest_buf, buf, len);
- status = send_dma_request(CMD_WRITE_DMA, 1, 1, prdt, ARRAY_SIZE(prdt));
+ status = send_dma_request(CMD_WRITE_DMA, 1, 1, prdt,
+ ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, BM_STS_INTR);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
/* Read and verify 0x55 pattern in sector 0 */
memset(cmpbuf, 0x55, len);
- status = send_dma_request(CMD_READ_DMA, 0, 1, prdt, ARRAY_SIZE(prdt));
+ status = send_dma_request(CMD_READ_DMA, 0, 1, prdt, ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, BM_STS_INTR);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
@@ -303,7 +323,7 @@ static void test_bmdma_simple_rw(void)
/* Read and verify 0xaa pattern in sector 1 */
memset(cmpbuf, 0xaa, len);
- status = send_dma_request(CMD_READ_DMA, 1, 1, prdt, ARRAY_SIZE(prdt));
+ status = send_dma_request(CMD_READ_DMA, 1, 1, prdt, ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, BM_STS_INTR);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
@@ -328,13 +348,13 @@ static void test_bmdma_short_prdt(void)
/* Normal request */
status = send_dma_request(CMD_READ_DMA, 0, 1,
- prdt, ARRAY_SIZE(prdt));
+ prdt, ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, 0);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
/* Abort the request before it completes */
status = send_dma_request(CMD_READ_DMA | CMDF_ABORT, 0, 1,
- prdt, ARRAY_SIZE(prdt));
+ prdt, ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, 0);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
}
@@ -353,13 +373,13 @@ static void test_bmdma_one_sector_short_prdt(void)
/* Normal request */
status = send_dma_request(CMD_READ_DMA, 0, 2,
- prdt, ARRAY_SIZE(prdt));
+ prdt, ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, 0);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
/* Abort the request before it completes */
status = send_dma_request(CMD_READ_DMA | CMDF_ABORT, 0, 2,
- prdt, ARRAY_SIZE(prdt));
+ prdt, ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, 0);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
}
@@ -377,13 +397,13 @@ static void test_bmdma_long_prdt(void)
/* Normal request */
status = send_dma_request(CMD_READ_DMA, 0, 1,
- prdt, ARRAY_SIZE(prdt));
+ prdt, ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, BM_STS_ACTIVE | BM_STS_INTR);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
/* Abort the request before it completes */
status = send_dma_request(CMD_READ_DMA | CMDF_ABORT, 0, 1,
- prdt, ARRAY_SIZE(prdt));
+ prdt, ARRAY_SIZE(prdt), NULL);
g_assert_cmphex(status, ==, BM_STS_INTR);
assert_bit_clear(inb(IDE_BASE + reg_status), DF | ERR);
}
@@ -399,7 +419,7 @@ static void test_bmdma_no_busmaster(void)
PrdtEntry prdt[4096] = { };
status = send_dma_request(CMD_READ_DMA | CMDF_NO_BM, 0, 512,
- prdt, ARRAY_SIZE(prdt));
+ prdt, ARRAY_SIZE(prdt), NULL);
/* Not entirely clear what the expected result is, but this is what we get
* in practice. At least we want to be aware of any changes. */
@@ -488,9 +508,7 @@ static void test_flush(void)
tmp_path);
/* Delay the completion of the flush request until we explicitly do it */
- qmp_discard_response("{'execute':'human-monitor-command', 'arguments': {"
- " 'command-line':"
- " 'qemu-io ide0-hd0 \"break flush_to_os A\"'} }");
+ g_free(hmp("qemu-io ide0-hd0 \"break flush_to_os A\""));
/* FLUSH CACHE command on device 0*/
outb(IDE_BASE + reg_device, 0);
@@ -502,9 +520,7 @@ static void test_flush(void)
assert_bit_clear(data, DF | ERR | DRQ);
/* Complete the command */
- qmp_discard_response("{'execute':'human-monitor-command', 'arguments': {"
- " 'command-line':"
- " 'qemu-io ide0-hd0 \"resume A\"'} }");
+ g_free(hmp("qemu-io ide0-hd0 \"resume A\""));
/* Check registers */
data = inb(IDE_BASE + reg_device);
@@ -575,16 +591,215 @@ static void test_flush_nodev(void)
ide_test_quit();
}
-static void test_pci_retry_flush(const char *machine)
+static void test_pci_retry_flush(void)
{
test_retry_flush("pc");
}
-static void test_isa_retry_flush(const char *machine)
+static void test_isa_retry_flush(void)
{
test_retry_flush("isapc");
}
+typedef struct Read10CDB {
+ uint8_t opcode;
+ uint8_t flags;
+ uint32_t lba;
+ uint8_t reserved;
+ uint16_t nblocks;
+ uint8_t control;
+ uint16_t padding;
+} __attribute__((__packed__)) Read10CDB;
+
+static void send_scsi_cdb_read10(uint64_t lba, int nblocks)
+{
+ Read10CDB pkt = { .padding = 0 };
+ int i;
+
+ g_assert_cmpint(lba, <=, UINT32_MAX);
+ g_assert_cmpint(nblocks, <=, UINT16_MAX);
+ g_assert_cmpint(nblocks, >=, 0);
+
+ /* Construct SCSI CDB packet */
+ pkt.opcode = 0x28;
+ pkt.lba = cpu_to_be32(lba);
+ pkt.nblocks = cpu_to_be16(nblocks);
+
+ /* Send Packet */
+ for (i = 0; i < sizeof(Read10CDB)/2; i++) {
+ outw(IDE_BASE + reg_data, cpu_to_le16(((uint16_t *)&pkt)[i]));
+ }
+}
+
+static void nsleep(int64_t nsecs)
+{
+ const struct timespec val = { .tv_nsec = nsecs };
+ nanosleep(&val, NULL);
+ clock_set(nsecs);
+}
+
+static uint8_t ide_wait_clear(uint8_t flag)
+{
+ uint8_t data;
+ time_t st;
+
+ /* Wait with a 5 second timeout */
+ time(&st);
+ while (true) {
+ data = inb(IDE_BASE + reg_status);
+ if (!(data & flag)) {
+ return data;
+ }
+ if (difftime(time(NULL), st) > 5.0) {
+ break;
+ }
+ nsleep(400);
+ }
+ g_assert_not_reached();
+}
+
+static void ide_wait_intr(int irq)
+{
+ time_t st;
+ bool intr;
+
+ time(&st);
+ while (true) {
+ intr = get_irq(irq);
+ if (intr) {
+ return;
+ }
+ if (difftime(time(NULL), st) > 5.0) {
+ break;
+ }
+ nsleep(400);
+ }
+
+ g_assert_not_reached();
+}
+
+static void cdrom_pio_impl(int nblocks)
+{
+ FILE *fh;
+ int patt_blocks = MAX(16, nblocks);
+ size_t patt_len = ATAPI_BLOCK_SIZE * patt_blocks;
+ char *pattern = g_malloc(patt_len);
+ size_t rxsize = ATAPI_BLOCK_SIZE * nblocks;
+ uint16_t *rx = g_malloc0(rxsize);
+ int i, j;
+ uint8_t data;
+ uint16_t limit;
+
+ /* Prepopulate the CDROM with an interesting pattern */
+ generate_pattern(pattern, patt_len, ATAPI_BLOCK_SIZE);
+ fh = fopen(tmp_path, "w+");
+ fwrite(pattern, ATAPI_BLOCK_SIZE, patt_blocks, fh);
+ fclose(fh);
+
+ ide_test_start("-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 "
+ "-device ide-cd,drive=sr0,bus=ide.0", tmp_path);
+ qtest_irq_intercept_in(global_qtest, "ioapic");
+
+ /* PACKET command on device 0 */
+ outb(IDE_BASE + reg_device, 0);
+ outb(IDE_BASE + reg_lba_middle, BYTE_COUNT_LIMIT & 0xFF);
+ outb(IDE_BASE + reg_lba_high, (BYTE_COUNT_LIMIT >> 8 & 0xFF));
+ outb(IDE_BASE + reg_command, CMD_PACKET);
+ /* HP0: Check_Status_A State */
+ nsleep(400);
+ data = ide_wait_clear(BSY);
+ /* HP1: Send_Packet State */
+ assert_bit_set(data, DRQ | DRDY);
+ assert_bit_clear(data, ERR | DF | BSY);
+
+ /* SCSI CDB (READ10) -- read n*2048 bytes from block 0 */
+ send_scsi_cdb_read10(0, nblocks);
+
+ /* Read data back: occurs in bursts of 'BYTE_COUNT_LIMIT' bytes.
+ * If BYTE_COUNT_LIMIT is odd, we transfer BYTE_COUNT_LIMIT - 1 bytes.
+ * We allow an odd limit only when the remaining transfer size is
+ * less than BYTE_COUNT_LIMIT. However, SCSI's read10 command can only
+ * request n blocks, so our request size is always even.
+ * For this reason, we assume there is never a hanging byte to fetch. */
+ g_assert(!(rxsize & 1));
+ limit = BYTE_COUNT_LIMIT & ~1;
+ for (i = 0; i < DIV_ROUND_UP(rxsize, limit); i++) {
+ size_t offset = i * (limit / 2);
+ size_t rem = (rxsize / 2) - offset;
+
+ /* HP3: INTRQ_Wait */
+ ide_wait_intr(IDE_PRIMARY_IRQ);
+
+ /* HP2: Check_Status_B (and clear IRQ) */
+ data = ide_wait_clear(BSY);
+ assert_bit_set(data, DRQ | DRDY);
+ assert_bit_clear(data, ERR | DF | BSY);
+
+ /* HP4: Transfer_Data */
+ for (j = 0; j < MIN((limit / 2), rem); j++) {
+ rx[offset + j] = le16_to_cpu(inw(IDE_BASE + reg_data));
+ }
+ }
+
+ /* Check for final completion IRQ */
+ ide_wait_intr(IDE_PRIMARY_IRQ);
+
+ /* Sanity check final state */
+ data = ide_wait_clear(DRQ);
+ assert_bit_set(data, DRDY);
+ assert_bit_clear(data, DRQ | ERR | DF | BSY);
+
+ g_assert_cmpint(memcmp(pattern, rx, rxsize), ==, 0);
+ g_free(pattern);
+ g_free(rx);
+ test_bmdma_teardown();
+}
+
+static void test_cdrom_pio(void)
+{
+ cdrom_pio_impl(1);
+}
+
+static void test_cdrom_pio_large(void)
+{
+ /* Test a few loops of the PIO DRQ mechanism. */
+ cdrom_pio_impl(BYTE_COUNT_LIMIT * 4 / ATAPI_BLOCK_SIZE);
+}
+
+
+static void test_cdrom_dma(void)
+{
+ static const size_t len = ATAPI_BLOCK_SIZE;
+ char *pattern = g_malloc(ATAPI_BLOCK_SIZE * 16);
+ char *rx = g_malloc0(len);
+ uintptr_t guest_buf;
+ PrdtEntry prdt[1];
+ FILE *fh;
+
+ ide_test_start("-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 "
+ "-device ide-cd,drive=sr0,bus=ide.0", tmp_path);
+ qtest_irq_intercept_in(global_qtest, "ioapic");
+
+ guest_buf = guest_alloc(guest_malloc, len);
+ prdt[0].addr = cpu_to_le32(guest_buf);
+ prdt[0].size = cpu_to_le32(len | PRDT_EOT);
+
+ generate_pattern(pattern, ATAPI_BLOCK_SIZE * 16, ATAPI_BLOCK_SIZE);
+ fh = fopen(tmp_path, "w+");
+ fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh);
+ fclose(fh);
+
+ send_dma_request(CMD_PACKET, 0, 1, prdt, 1, send_scsi_cdb_read10);
+
+ /* Read back data from guest memory into local qtest memory */
+ memread(guest_buf, rx, len);
+ g_assert_cmpint(memcmp(pattern, rx, len), ==, 0);
+
+ g_free(pattern);
+ g_free(rx);
+ test_bmdma_teardown();
+}
+
int main(int argc, char **argv)
{
const char *arch = qtest_get_arch();
@@ -628,6 +843,10 @@ int main(int argc, char **argv)
qtest_add_func("/ide/flush/retry_pci", test_pci_retry_flush);
qtest_add_func("/ide/flush/retry_isa", test_isa_retry_flush);
+ qtest_add_func("/ide/cdrom/pio", test_cdrom_pio);
+ qtest_add_func("/ide/cdrom/pio_large", test_cdrom_pio_large);
+ qtest_add_func("/ide/cdrom/dma", test_cdrom_dma);
+
ret = g_test_run();
/* Cleanup */
diff --git a/qemu/tests/image-fuzzer/runner.py b/qemu/tests/image-fuzzer/runner.py
index 0a8743ef4..96a1c11b2 100755
--- a/qemu/tests/image-fuzzer/runner.py
+++ b/qemu/tests/image-fuzzer/runner.py
@@ -157,7 +157,7 @@ class TestEnv(object):
try:
os.makedirs(self.current_dir)
- except OSError, e:
+ except OSError as e:
print >>sys.stderr, \
"Error: The working directory '%s' cannot be used. Reason: %s"\
% (self.work_dir, e[1])
@@ -244,7 +244,7 @@ class TestEnv(object):
temp_log = StringIO.StringIO()
try:
retcode = run_app(temp_log, current_cmd)
- except OSError, e:
+ except OSError as e:
multilog("%sError: Start of '%s' failed. Reason: %s\n\n"
% (test_summary, os.path.basename(current_cmd[0]),
e[1]),
@@ -301,7 +301,7 @@ if __name__ == '__main__':
JSON:
'--command' accepts a JSON array of commands. Each command presents
- an application under test with all its paramaters as a list of strings,
+ an application under test with all its parameters as a list of strings,
e.g. ["qemu-io", "$test_img", "-c", "write $off $len"].
Supported application aliases: 'qemu-img' and 'qemu-io'.
@@ -356,7 +356,7 @@ if __name__ == '__main__':
opts, args = getopt.gnu_getopt(sys.argv[1:], 'c:hs:kvd:',
['command=', 'help', 'seed=', 'config=',
'keep_passed', 'verbose', 'duration='])
- except getopt.error, e:
+ except getopt.error as e:
print >>sys.stderr, \
"Error: %s\n\nTry 'runner.py --help' for more information" % e
sys.exit(1)
@@ -374,7 +374,7 @@ if __name__ == '__main__':
elif opt in ('-c', '--command'):
try:
command = json.loads(arg)
- except (TypeError, ValueError, NameError), e:
+ except (TypeError, ValueError, NameError) as e:
print >>sys.stderr, \
"Error: JSON array of test commands cannot be loaded.\n" \
"Reason: %s" % e
@@ -390,7 +390,7 @@ if __name__ == '__main__':
elif opt == '--config':
try:
config = json.loads(arg)
- except (TypeError, ValueError, NameError), e:
+ except (TypeError, ValueError, NameError) as e:
print >>sys.stderr, \
"Error: JSON array with the fuzzer configuration cannot" \
" be loaded\nReason: %s" % e
@@ -414,7 +414,7 @@ if __name__ == '__main__':
try:
image_generator = __import__(generator_name)
- except ImportError, e:
+ except ImportError as e:
print >>sys.stderr, \
"Error: The image generator '%s' cannot be imported.\n" \
"Reason: %s" % (generator_name, e)
diff --git a/qemu/tests/intel-hda-test.c b/qemu/tests/intel-hda-test.c
index d89b407dc..1be6add9b 100644
--- a/qemu/tests/intel-hda-test.c
+++ b/qemu/tests/intel-hda-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
#define HDA_ID "hda0"
#define CODEC_DEVICES " -device hda-output,bus=" HDA_ID ".0" \
diff --git a/qemu/tests/io-channel-helpers.c b/qemu/tests/io-channel-helpers.c
new file mode 100644
index 000000000..05e5579cf
--- /dev/null
+++ b/qemu/tests/io-channel-helpers.c
@@ -0,0 +1,248 @@
+/*
+ * QEMU I/O channel test helpers
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "io-channel-helpers.h"
+#include "qapi/error.h"
+
+struct QIOChannelTest {
+ QIOChannel *src;
+ QIOChannel *dst;
+ bool blocking;
+ size_t len;
+ size_t niov;
+ char *input;
+ struct iovec *inputv;
+ char *output;
+ struct iovec *outputv;
+ Error *writeerr;
+ Error *readerr;
+};
+
+
+static void test_skip_iovec(struct iovec **iov,
+ size_t *niov,
+ size_t skip,
+ struct iovec *old)
+{
+ size_t offset = 0;
+ size_t i;
+
+ for (i = 0; i < *niov; i++) {
+ if (skip < (*iov)[i].iov_len) {
+ old->iov_len = (*iov)[i].iov_len;
+ old->iov_base = (*iov)[i].iov_base;
+
+ (*iov)[i].iov_len -= skip;
+ (*iov)[i].iov_base += skip;
+ break;
+ } else {
+ skip -= (*iov)[i].iov_len;
+
+ if (i == 0 && old->iov_base) {
+ (*iov)[i].iov_len = old->iov_len;
+ (*iov)[i].iov_base = old->iov_base;
+ old->iov_len = 0;
+ old->iov_base = NULL;
+ }
+
+ offset++;
+ }
+ }
+
+ *iov = *iov + offset;
+ *niov -= offset;
+}
+
+
+/* This thread sends all data using iovecs */
+static gpointer test_io_thread_writer(gpointer opaque)
+{
+ QIOChannelTest *data = opaque;
+ struct iovec *iov = data->inputv;
+ size_t niov = data->niov;
+ struct iovec old = { 0 };
+
+ qio_channel_set_blocking(data->src, data->blocking, NULL);
+
+ while (niov) {
+ ssize_t ret;
+ ret = qio_channel_writev(data->src,
+ iov,
+ niov,
+ &data->writeerr);
+ if (ret == QIO_CHANNEL_ERR_BLOCK) {
+ if (data->blocking) {
+ error_setg(&data->writeerr,
+ "Unexpected I/O blocking");
+ break;
+ } else {
+ qio_channel_wait(data->src,
+ G_IO_OUT);
+ continue;
+ }
+ } else if (ret < 0) {
+ break;
+ } else if (ret == 0) {
+ error_setg(&data->writeerr,
+ "Unexpected zero length write");
+ break;
+ }
+
+ test_skip_iovec(&iov, &niov, ret, &old);
+ }
+
+ return NULL;
+}
+
+
+/* This thread receives all data using iovecs */
+static gpointer test_io_thread_reader(gpointer opaque)
+{
+ QIOChannelTest *data = opaque;
+ struct iovec *iov = data->outputv;
+ size_t niov = data->niov;
+ struct iovec old = { 0 };
+
+ qio_channel_set_blocking(data->dst, data->blocking, NULL);
+
+ while (niov) {
+ ssize_t ret;
+
+ ret = qio_channel_readv(data->dst,
+ iov,
+ niov,
+ &data->readerr);
+
+ if (ret == QIO_CHANNEL_ERR_BLOCK) {
+ if (data->blocking) {
+ error_setg(&data->readerr,
+ "Unexpected I/O blocking");
+ break;
+ } else {
+ qio_channel_wait(data->dst,
+ G_IO_IN);
+ continue;
+ }
+ } else if (ret < 0) {
+ break;
+ } else if (ret == 0) {
+ break;
+ }
+
+ test_skip_iovec(&iov, &niov, ret, &old);
+ }
+
+ return NULL;
+}
+
+
+QIOChannelTest *qio_channel_test_new(void)
+{
+ QIOChannelTest *data = g_new0(QIOChannelTest, 1);
+ size_t i;
+ size_t offset;
+
+
+ /* We'll send 1 MB of data */
+#define CHUNK_COUNT 250
+#define CHUNK_LEN 4194
+
+ data->len = CHUNK_COUNT * CHUNK_LEN;
+ data->input = g_new0(char, data->len);
+ data->output = g_new0(gchar, data->len);
+
+ /* Fill input with a pattern */
+ for (i = 0; i < data->len; i += CHUNK_LEN) {
+ memset(data->input + i, (i / CHUNK_LEN), CHUNK_LEN);
+ }
+
+ /* We'll split the data across a bunch of IO vecs */
+ data->niov = CHUNK_COUNT;
+ data->inputv = g_new0(struct iovec, data->niov);
+ data->outputv = g_new0(struct iovec, data->niov);
+
+ for (i = 0, offset = 0; i < data->niov; i++, offset += CHUNK_LEN) {
+ data->inputv[i].iov_base = data->input + offset;
+ data->outputv[i].iov_base = data->output + offset;
+ data->inputv[i].iov_len = CHUNK_LEN;
+ data->outputv[i].iov_len = CHUNK_LEN;
+ }
+
+ return data;
+}
+
+void qio_channel_test_run_threads(QIOChannelTest *test,
+ bool blocking,
+ QIOChannel *src,
+ QIOChannel *dst)
+{
+ GThread *reader, *writer;
+
+ test->src = src;
+ test->dst = dst;
+ test->blocking = blocking;
+
+ reader = g_thread_new("reader",
+ test_io_thread_reader,
+ test);
+ writer = g_thread_new("writer",
+ test_io_thread_writer,
+ test);
+
+ g_thread_join(reader);
+ g_thread_join(writer);
+
+ test->dst = test->src = NULL;
+}
+
+
+void qio_channel_test_run_writer(QIOChannelTest *test,
+ QIOChannel *src)
+{
+ test->src = src;
+ test_io_thread_writer(test);
+ test->src = NULL;
+}
+
+
+void qio_channel_test_run_reader(QIOChannelTest *test,
+ QIOChannel *dst)
+{
+ test->dst = dst;
+ test_io_thread_reader(test);
+ test->dst = NULL;
+}
+
+
+void qio_channel_test_validate(QIOChannelTest *test)
+{
+ g_assert(test->readerr == NULL);
+ g_assert(test->writeerr == NULL);
+ g_assert_cmpint(memcmp(test->input,
+ test->output,
+ test->len), ==, 0);
+
+ g_free(test->inputv);
+ g_free(test->outputv);
+ g_free(test->input);
+ g_free(test->output);
+ g_free(test);
+}
diff --git a/qemu/tests/io-channel-helpers.h b/qemu/tests/io-channel-helpers.h
new file mode 100644
index 000000000..fedc64fd5
--- /dev/null
+++ b/qemu/tests/io-channel-helpers.h
@@ -0,0 +1,42 @@
+/*
+ * QEMU I/O channel test helpers
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "io/channel.h"
+
+#ifndef TEST_IO_CHANNEL_HELPERS
+#define TEST_IO_CHANNEL_HELPERS
+
+typedef struct QIOChannelTest QIOChannelTest;
+
+QIOChannelTest *qio_channel_test_new(void);
+
+void qio_channel_test_run_threads(QIOChannelTest *test,
+ bool blocking,
+ QIOChannel *src,
+ QIOChannel *dst);
+
+void qio_channel_test_run_writer(QIOChannelTest *test,
+ QIOChannel *src);
+void qio_channel_test_run_reader(QIOChannelTest *test,
+ QIOChannel *dst);
+
+void qio_channel_test_validate(QIOChannelTest *test);
+
+#endif /* TEST_IO_CHANNEL_HELPERS */
diff --git a/qemu/tests/ioh3420-test.c b/qemu/tests/ioh3420-test.c
index c991a5f87..93eb2f750 100644
--- a/qemu/tests/ioh3420-test.c
+++ b/qemu/tests/ioh3420-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void nop(void)
diff --git a/qemu/tests/ipmi-bt-test.c b/qemu/tests/ipmi-bt-test.c
new file mode 100644
index 000000000..812907fb7
--- /dev/null
+++ b/qemu/tests/ipmi-bt-test.c
@@ -0,0 +1,433 @@
+/*
+ * IPMI BT test cases, using the external interface for checking
+ *
+ * Copyright (c) 2012 Corey Minyard <cminyard@mvista.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include <glib.h>
+
+#include "libqtest.h"
+#include "qemu-common.h"
+
+#define IPMI_IRQ 5
+
+#define IPMI_BT_BASE 0xe4
+
+#define IPMI_BT_CTLREG_CLR_WR_PTR 0
+#define IPMI_BT_CTLREG_CLR_RD_PTR 1
+#define IPMI_BT_CTLREG_H2B_ATN 2
+#define IPMI_BT_CTLREG_B2H_ATN 3
+#define IPMI_BT_CTLREG_SMS_ATN 4
+#define IPMI_BT_CTLREG_H_BUSY 6
+#define IPMI_BT_CTLREG_B_BUSY 7
+
+#define IPMI_BT_CTLREG_GET(b) ((bt_get_ctrlreg() >> (b)) & 1)
+#define IPMI_BT_CTLREG_GET_H2B_ATN() IPMI_BT_CTLREG_GET(IPMI_BT_CTLREG_H2B_ATN)
+#define IPMI_BT_CTLREG_GET_B2H_ATN() IPMI_BT_CTLREG_GET(IPMI_BT_CTLREG_B2H_ATN)
+#define IPMI_BT_CTLREG_GET_SMS_ATN() IPMI_BT_CTLREG_GET(IPMI_BT_CTLREG_SMS_ATN)
+#define IPMI_BT_CTLREG_GET_H_BUSY() IPMI_BT_CTLREG_GET(IPMI_BT_CTLREG_H_BUSY)
+#define IPMI_BT_CTLREG_GET_B_BUSY() IPMI_BT_CTLREG_GET(IPMI_BT_CTLREG_B_BUSY)
+
+#define IPMI_BT_CTLREG_SET(b) bt_write_ctrlreg(1 << (b))
+#define IPMI_BT_CTLREG_SET_CLR_WR_PTR() IPMI_BT_CTLREG_SET( \
+ IPMI_BT_CTLREG_CLR_WR_PTR)
+#define IPMI_BT_CTLREG_SET_CLR_RD_PTR() IPMI_BT_CTLREG_SET( \
+ IPMI_BT_CTLREG_CLR_RD_PTR)
+#define IPMI_BT_CTLREG_SET_H2B_ATN() IPMI_BT_CTLREG_SET(IPMI_BT_CTLREG_H2B_ATN)
+#define IPMI_BT_CTLREG_SET_B2H_ATN() IPMI_BT_CTLREG_SET(IPMI_BT_CTLREG_B2H_ATN)
+#define IPMI_BT_CTLREG_SET_SMS_ATN() IPMI_BT_CTLREG_SET(IPMI_BT_CTLREG_SMS_ATN)
+#define IPMI_BT_CTLREG_SET_H_BUSY() IPMI_BT_CTLREG_SET(IPMI_BT_CTLREG_H_BUSY)
+
+static int bt_ints_enabled;
+
+static uint8_t bt_get_ctrlreg(void)
+{
+ return inb(IPMI_BT_BASE);
+}
+
+static void bt_write_ctrlreg(uint8_t val)
+{
+ outb(IPMI_BT_BASE, val);
+}
+
+static uint8_t bt_get_buf(void)
+{
+ return inb(IPMI_BT_BASE + 1);
+}
+
+static void bt_write_buf(uint8_t val)
+{
+ outb(IPMI_BT_BASE + 1, val);
+}
+
+static uint8_t bt_get_irqreg(void)
+{
+ return inb(IPMI_BT_BASE + 2);
+}
+
+static void bt_write_irqreg(uint8_t val)
+{
+ outb(IPMI_BT_BASE + 2, val);
+}
+
+static void bt_wait_b_busy(void)
+{
+ unsigned int count = 1000;
+ while (IPMI_BT_CTLREG_GET_B_BUSY() != 0) {
+ g_assert(--count != 0);
+ }
+}
+
+static void bt_wait_b2h_atn(void)
+{
+ unsigned int count = 1000;
+ while (IPMI_BT_CTLREG_GET_B2H_ATN() == 0) {
+ g_assert(--count != 0);
+ }
+}
+
+
+static int emu_lfd;
+static int emu_fd;
+static in_port_t emu_port;
+static uint8_t inbuf[100];
+static unsigned int inbuf_len;
+static unsigned int inbuf_pos;
+static int last_was_aa;
+
+static void read_emu_data(void)
+{
+ fd_set readfds;
+ int rv;
+ struct timeval tv;
+
+ FD_ZERO(&readfds);
+ FD_SET(emu_fd, &readfds);
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+ rv = select(emu_fd + 1, &readfds, NULL, NULL, &tv);
+ if (rv == -1) {
+ perror("select");
+ }
+ g_assert(rv == 1);
+ rv = read(emu_fd, inbuf, sizeof(inbuf));
+ if (rv == -1) {
+ perror("read");
+ }
+ g_assert(rv > 0);
+ inbuf_len = rv;
+ inbuf_pos = 0;
+}
+
+static void write_emu_msg(uint8_t *msg, unsigned int len)
+{
+ int rv;
+
+#ifdef DEBUG_TEST
+ {
+ unsigned int i;
+ printf("sending:");
+ for (i = 0; i < len; i++) {
+ printf(" %2.2x", msg[i]);
+ }
+ printf("\n");
+ }
+#endif
+ rv = write(emu_fd, msg, len);
+ g_assert(rv == len);
+}
+
+static void get_emu_msg(uint8_t *msg, unsigned int *len)
+{
+ unsigned int outpos = 0;
+
+ for (;;) {
+ while (inbuf_pos < inbuf_len) {
+ uint8_t ch = inbuf[inbuf_pos++];
+
+ g_assert(outpos < *len);
+ if (last_was_aa) {
+ assert(ch & 0x10);
+ msg[outpos++] = ch & ~0x10;
+ last_was_aa = 0;
+ } else if (ch == 0xaa) {
+ last_was_aa = 1;
+ } else {
+ msg[outpos++] = ch;
+ if ((ch == 0xa0) || (ch == 0xa1)) {
+ /* Message complete */
+ *len = outpos;
+ goto done;
+ }
+ }
+ }
+ read_emu_data();
+ }
+ done:
+#ifdef DEBUG_TEST
+ {
+ unsigned int i;
+ printf("Msg:");
+ for (i = 0; i < outpos; i++) {
+ printf(" %2.2x", msg[i]);
+ }
+ printf("\n");
+ }
+#endif
+ return;
+}
+
+static uint8_t
+ipmb_checksum(const unsigned char *data, int size, unsigned char start)
+{
+ unsigned char csum = start;
+
+ for (; size > 0; size--, data++) {
+ csum += *data;
+ }
+ return csum;
+}
+
+static uint8_t get_dev_id_cmd[] = { 0x18, 0x01 };
+static uint8_t get_dev_id_rsp[] = { 0x1c, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x02, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+static uint8_t set_bmc_globals_cmd[] = { 0x18, 0x2e, 0x0f };
+static uint8_t set_bmc_globals_rsp[] = { 0x1c, 0x2e, 0x00 };
+static uint8_t enable_irq_cmd[] = { 0x05, 0xa1 };
+
+static void emu_msg_handler(void)
+{
+ uint8_t msg[100];
+ unsigned int msg_len = sizeof(msg);
+
+ get_emu_msg(msg, &msg_len);
+ g_assert(msg_len >= 5);
+ g_assert(msg[msg_len - 1] == 0xa0);
+ msg_len--;
+ g_assert(ipmb_checksum(msg, msg_len, 0) == 0);
+ msg_len--;
+ if ((msg[1] == get_dev_id_cmd[0]) && (msg[2] == get_dev_id_cmd[1])) {
+ memcpy(msg + 1, get_dev_id_rsp, sizeof(get_dev_id_rsp));
+ msg_len = sizeof(get_dev_id_rsp) + 1;
+ msg[msg_len] = -ipmb_checksum(msg, msg_len, 0);
+ msg_len++;
+ msg[msg_len++] = 0xa0;
+ write_emu_msg(msg, msg_len);
+ } else if ((msg[1] == set_bmc_globals_cmd[0]) &&
+ (msg[2] == set_bmc_globals_cmd[1])) {
+ memcpy(msg + 1, set_bmc_globals_rsp, sizeof(set_bmc_globals_rsp));
+ msg_len = sizeof(set_bmc_globals_rsp) + 1;
+ msg[msg_len] = -ipmb_checksum(msg, msg_len, 0);
+ msg_len++;
+ msg[msg_len++] = 0xa0;
+ write_emu_msg(msg, msg_len);
+ write_emu_msg(enable_irq_cmd, sizeof(enable_irq_cmd));
+ } else {
+ g_assert(0);
+ }
+}
+
+static void bt_cmd(uint8_t *cmd, unsigned int cmd_len,
+ uint8_t *rsp, unsigned int *rsp_len)
+{
+ unsigned int i, len, j = 0;
+ uint8_t seq = 5;
+
+ /* Should be idle */
+ g_assert(bt_get_ctrlreg() == 0);
+
+ bt_wait_b_busy();
+ IPMI_BT_CTLREG_SET_CLR_WR_PTR();
+ bt_write_buf(cmd_len + 1);
+ bt_write_buf(cmd[0]);
+ bt_write_buf(seq);
+ for (i = 1; i < cmd_len; i++) {
+ bt_write_buf(cmd[i]);
+ }
+ IPMI_BT_CTLREG_SET_H2B_ATN();
+
+ emu_msg_handler(); /* We should get a message on the socket here. */
+
+ bt_wait_b2h_atn();
+ if (bt_ints_enabled) {
+ g_assert((bt_get_irqreg() & 0x02) == 0x02);
+ g_assert(get_irq(IPMI_IRQ));
+ bt_write_irqreg(0x03);
+ } else {
+ g_assert(!get_irq(IPMI_IRQ));
+ }
+ IPMI_BT_CTLREG_SET_H_BUSY();
+ IPMI_BT_CTLREG_SET_B2H_ATN();
+ IPMI_BT_CTLREG_SET_CLR_RD_PTR();
+ len = bt_get_buf();
+ g_assert(len >= 4);
+ rsp[0] = bt_get_buf();
+ assert(bt_get_buf() == seq);
+ len--;
+ for (j = 1; j < len; j++) {
+ rsp[j] = bt_get_buf();
+ }
+ IPMI_BT_CTLREG_SET_H_BUSY();
+ *rsp_len = j;
+}
+
+
+/*
+ * We should get a connect request and a short message with capabilities.
+ */
+static void test_connect(void)
+{
+ fd_set readfds;
+ int rv;
+ int val;
+ struct timeval tv;
+ uint8_t msg[100];
+ unsigned int msglen;
+ static uint8_t exp1[] = { 0xff, 0x01, 0xa1 }; /* A protocol version */
+ static uint8_t exp2[] = { 0x08, 0x1f, 0xa1 }; /* A capabilities cmd */
+
+ FD_ZERO(&readfds);
+ FD_SET(emu_lfd, &readfds);
+ tv.tv_sec = 10;
+ tv.tv_usec = 0;
+ rv = select(emu_lfd + 1, &readfds, NULL, NULL, &tv);
+ g_assert(rv == 1);
+ emu_fd = accept(emu_lfd, NULL, 0);
+ if (emu_fd < 0) {
+ perror("accept");
+ }
+ g_assert(emu_fd >= 0);
+
+ val = 1;
+ rv = setsockopt(emu_fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
+ g_assert(rv != -1);
+
+ /* Report our version */
+ write_emu_msg(exp1, sizeof(exp1));
+
+ /* Validate that we get the info we expect. */
+ msglen = sizeof(msg);
+ get_emu_msg(msg, &msglen);
+ g_assert(msglen == sizeof(exp1));
+ g_assert(memcmp(msg, exp1, msglen) == 0);
+ msglen = sizeof(msg);
+ get_emu_msg(msg, &msglen);
+ g_assert(msglen == sizeof(exp2));
+ g_assert(memcmp(msg, exp2, msglen) == 0);
+}
+
+/*
+ * Send a get_device_id to do a basic test.
+ */
+static void test_bt_base(void)
+{
+ uint8_t rsp[20];
+ unsigned int rsplen = sizeof(rsp);
+
+ bt_cmd(get_dev_id_cmd, sizeof(get_dev_id_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(get_dev_id_rsp));
+ g_assert(memcmp(get_dev_id_rsp, rsp, rsplen) == 0);
+}
+
+/*
+ * Enable IRQs for the interface.
+ */
+static void test_enable_irq(void)
+{
+ uint8_t rsp[20];
+ unsigned int rsplen = sizeof(rsp);
+
+ bt_cmd(set_bmc_globals_cmd, sizeof(set_bmc_globals_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(set_bmc_globals_rsp));
+ g_assert(memcmp(set_bmc_globals_rsp, rsp, rsplen) == 0);
+ bt_write_irqreg(0x01);
+ bt_ints_enabled = 1;
+}
+
+/*
+ * Create a local TCP socket with any port, then save off the port we got.
+ */
+static void open_socket(void)
+{
+ struct sockaddr_in myaddr;
+ socklen_t addrlen;
+
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ myaddr.sin_port = 0;
+ emu_lfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (emu_lfd == -1) {
+ perror("socket");
+ exit(1);
+ }
+ if (bind(emu_lfd, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) {
+ perror("bind");
+ exit(1);
+ }
+ addrlen = sizeof(myaddr);
+ if (getsockname(emu_lfd, (struct sockaddr *) &myaddr , &addrlen) == -1) {
+ perror("getsockname");
+ exit(1);
+ }
+ emu_port = ntohs(myaddr.sin_port);
+ assert(listen(emu_lfd, 1) != -1);
+}
+
+int main(int argc, char **argv)
+{
+ const char *arch = qtest_get_arch();
+ char *cmdline;
+ int ret;
+
+ /* Check architecture */
+ if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
+ g_test_message("Skipping test for non-x86\n");
+ return 0;
+ }
+
+ open_socket();
+
+ /* Run the tests */
+ g_test_init(&argc, &argv, NULL);
+
+ cmdline = g_strdup_printf("-vnc none"
+ " -chardev socket,id=ipmi0,host=localhost,port=%d,reconnect=10"
+ " -device ipmi-bmc-extern,chardev=ipmi0,id=bmc0"
+ " -device isa-ipmi-bt,bmc=bmc0", emu_port);
+ qtest_start(cmdline);
+ qtest_irq_intercept_in(global_qtest, "ioapic");
+ qtest_add_func("/ipmi/extern/connect", test_connect);
+ qtest_add_func("/ipmi/extern/bt_base", test_bt_base);
+ qtest_add_func("/ipmi/extern/bt_enable_irq", test_enable_irq);
+ qtest_add_func("/ipmi/extern/bt_base_irq", test_bt_base);
+ ret = g_test_run();
+ qtest_quit(global_qtest);
+
+ return ret;
+}
diff --git a/qemu/tests/ipmi-kcs-test.c b/qemu/tests/ipmi-kcs-test.c
new file mode 100644
index 000000000..42c4b974c
--- /dev/null
+++ b/qemu/tests/ipmi-kcs-test.c
@@ -0,0 +1,293 @@
+/*
+ * IPMI KCS test cases, using the local interface.
+ *
+ * Copyright (c) 2012 Corey Minyard <cminyard@mvista.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+
+#include <glib.h>
+
+#include "libqtest.h"
+
+#define IPMI_IRQ 5
+
+#define IPMI_KCS_BASE 0xca2
+
+#define IPMI_KCS_STATUS_ABORT 0x60
+#define IPMI_KCS_CMD_WRITE_START 0x61
+#define IPMI_KCS_CMD_WRITE_END 0x62
+#define IPMI_KCS_CMD_READ 0x68
+
+#define IPMI_KCS_ABORTED_BY_CMD 0x01
+
+#define IPMI_KCS_CMDREG_GET_STATE() ((kcs_get_cmdreg() >> 6) & 3)
+#define IPMI_KCS_STATE_IDLE 0
+#define IPMI_KCS_STATE_READ 1
+#define IPMI_KCS_STATE_WRITE 2
+#define IPMI_KCS_STATE_ERROR 3
+#define IPMI_KCS_CMDREG_GET_CD() ((kcs_get_cmdreg() >> 3) & 1)
+#define IPMI_KCS_CMDREG_GET_ATN() ((kcs_get_cmdreg() >> 2) & 1)
+#define IPMI_KCS_CMDREG_GET_IBF() ((kcs_get_cmdreg() >> 1) & 1)
+#define IPMI_KCS_CMDREG_GET_OBF() ((kcs_get_cmdreg() >> 0) & 1)
+
+static int kcs_ints_enabled;
+
+static uint8_t kcs_get_cmdreg(void)
+{
+ return inb(IPMI_KCS_BASE + 1);
+}
+
+static void kcs_write_cmdreg(uint8_t val)
+{
+ outb(IPMI_KCS_BASE + 1, val);
+}
+
+static uint8_t kcs_get_datareg(void)
+{
+ return inb(IPMI_KCS_BASE);
+}
+
+static void kcs_write_datareg(uint8_t val)
+{
+ outb(IPMI_KCS_BASE, val);
+}
+
+static void kcs_wait_ibf(void)
+{
+ unsigned int count = 1000;
+ while (IPMI_KCS_CMDREG_GET_IBF() != 0) {
+ g_assert(--count != 0);
+ }
+}
+
+static void kcs_wait_obf(void)
+{
+ unsigned int count = 1000;
+ while (IPMI_KCS_CMDREG_GET_OBF() == 0) {
+ g_assert(--count != 0);
+ }
+}
+
+static void kcs_clear_obf(void)
+{
+ if (kcs_ints_enabled) {
+ g_assert(get_irq(IPMI_IRQ));
+ } else {
+ g_assert(!get_irq(IPMI_IRQ));
+ }
+ g_assert(IPMI_KCS_CMDREG_GET_OBF() == 1);
+ kcs_get_datareg();
+ g_assert(IPMI_KCS_CMDREG_GET_OBF() == 0);
+ g_assert(!get_irq(IPMI_IRQ));
+}
+
+static void kcs_check_state(uint8_t state)
+{
+ g_assert(IPMI_KCS_CMDREG_GET_STATE() == state);
+}
+
+static void kcs_cmd(uint8_t *cmd, unsigned int cmd_len,
+ uint8_t *rsp, unsigned int *rsp_len)
+{
+ unsigned int i, j = 0;
+
+ /* Should be idle */
+ g_assert(kcs_get_cmdreg() == 0);
+
+ kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_START);
+ kcs_wait_ibf();
+ kcs_check_state(IPMI_KCS_STATE_WRITE);
+ kcs_clear_obf();
+ for (i = 0; i < cmd_len; i++) {
+ kcs_write_datareg(cmd[i]);
+ kcs_wait_ibf();
+ kcs_check_state(IPMI_KCS_STATE_WRITE);
+ kcs_clear_obf();
+ }
+ kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_END);
+ kcs_wait_ibf();
+ kcs_check_state(IPMI_KCS_STATE_WRITE);
+ kcs_clear_obf();
+ kcs_write_datareg(0);
+ next_read_byte:
+ kcs_wait_ibf();
+ switch (IPMI_KCS_CMDREG_GET_STATE()) {
+ case IPMI_KCS_STATE_READ:
+ kcs_wait_obf();
+ g_assert(j < *rsp_len);
+ rsp[j++] = kcs_get_datareg();
+ kcs_write_datareg(IPMI_KCS_CMD_READ);
+ goto next_read_byte;
+ break;
+
+ case IPMI_KCS_STATE_IDLE:
+ kcs_wait_obf();
+ kcs_get_datareg();
+ break;
+
+ default:
+ g_assert(0);
+ }
+ *rsp_len = j;
+}
+
+static void kcs_abort(uint8_t *cmd, unsigned int cmd_len,
+ uint8_t *rsp, unsigned int *rsp_len)
+{
+ unsigned int i, j = 0;
+ unsigned int retries = 4;
+
+ /* Should be idle */
+ g_assert(kcs_get_cmdreg() == 0);
+
+ kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_START);
+ kcs_wait_ibf();
+ kcs_check_state(IPMI_KCS_STATE_WRITE);
+ kcs_clear_obf();
+ for (i = 0; i < cmd_len; i++) {
+ kcs_write_datareg(cmd[i]);
+ kcs_wait_ibf();
+ kcs_check_state(IPMI_KCS_STATE_WRITE);
+ kcs_clear_obf();
+ }
+ kcs_write_cmdreg(IPMI_KCS_CMD_WRITE_END);
+ kcs_wait_ibf();
+ kcs_check_state(IPMI_KCS_STATE_WRITE);
+ kcs_clear_obf();
+ kcs_write_datareg(0);
+ kcs_wait_ibf();
+ switch (IPMI_KCS_CMDREG_GET_STATE()) {
+ case IPMI_KCS_STATE_READ:
+ kcs_wait_obf();
+ g_assert(j < *rsp_len);
+ rsp[j++] = kcs_get_datareg();
+ kcs_write_datareg(IPMI_KCS_CMD_READ);
+ break;
+
+ default:
+ g_assert(0);
+ }
+
+ /* Start the abort here */
+ retry_abort:
+ g_assert(retries > 0);
+
+ kcs_wait_ibf();
+ kcs_write_cmdreg(IPMI_KCS_STATUS_ABORT);
+ kcs_wait_ibf();
+ kcs_clear_obf();
+ kcs_write_datareg(0);
+ kcs_wait_ibf();
+ if (IPMI_KCS_CMDREG_GET_STATE() != IPMI_KCS_STATE_READ) {
+ retries--;
+ goto retry_abort;
+ }
+ kcs_wait_obf();
+ rsp[0] = kcs_get_datareg();
+ kcs_write_datareg(IPMI_KCS_CMD_READ);
+ kcs_wait_ibf();
+ if (IPMI_KCS_CMDREG_GET_STATE() != IPMI_KCS_STATE_IDLE) {
+ retries--;
+ goto retry_abort;
+ }
+ kcs_wait_obf();
+ kcs_clear_obf();
+
+ *rsp_len = j;
+}
+
+
+static uint8_t get_dev_id_cmd[] = { 0x18, 0x01 };
+static uint8_t get_dev_id_rsp[] = { 0x1c, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x02, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+/*
+ * Send a get_device_id to do a basic test.
+ */
+static void test_kcs_base(void)
+{
+ uint8_t rsp[20];
+ unsigned int rsplen = sizeof(rsp);
+
+ kcs_cmd(get_dev_id_cmd, sizeof(get_dev_id_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(get_dev_id_rsp));
+ g_assert(memcmp(get_dev_id_rsp, rsp, rsplen) == 0);
+}
+
+/*
+ * Abort a kcs operation while reading
+ */
+static void test_kcs_abort(void)
+{
+ uint8_t rsp[20];
+ unsigned int rsplen = sizeof(rsp);
+
+ kcs_abort(get_dev_id_cmd, sizeof(get_dev_id_cmd), rsp, &rsplen);
+ g_assert(rsp[0] == IPMI_KCS_ABORTED_BY_CMD);
+}
+
+static uint8_t set_bmc_globals_cmd[] = { 0x18, 0x2e, 0x0f };
+static uint8_t set_bmc_globals_rsp[] = { 0x1c, 0x2e, 0x00 };
+
+/*
+ * Enable interrupts
+ */
+static void test_enable_irq(void)
+{
+ uint8_t rsp[20];
+ unsigned int rsplen = sizeof(rsp);
+
+ kcs_cmd(set_bmc_globals_cmd, sizeof(set_bmc_globals_cmd), rsp, &rsplen);
+ g_assert(rsplen == sizeof(set_bmc_globals_rsp));
+ g_assert(memcmp(set_bmc_globals_rsp, rsp, rsplen) == 0);
+ kcs_ints_enabled = 1;
+}
+
+int main(int argc, char **argv)
+{
+ const char *arch = qtest_get_arch();
+ char *cmdline;
+ int ret;
+
+ /* Check architecture */
+ if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) {
+ g_test_message("Skipping test for non-x86\n");
+ return 0;
+ }
+
+ /* Run the tests */
+ g_test_init(&argc, &argv, NULL);
+
+ cmdline = g_strdup_printf("-vnc none -device ipmi-bmc-sim,id=bmc0"
+ " -device isa-ipmi-kcs,bmc=bmc0");
+ qtest_start(cmdline);
+ qtest_irq_intercept_in(global_qtest, "ioapic");
+ qtest_add_func("/ipmi/local/kcs_base", test_kcs_base);
+ qtest_add_func("/ipmi/local/kcs_abort", test_kcs_abort);
+ qtest_add_func("/ipmi/local/kcs_enable_irq", test_enable_irq);
+ qtest_add_func("/ipmi/local/kcs_base_irq", test_kcs_base);
+ qtest_add_func("/ipmi/local/kcs_abort_irq", test_kcs_abort);
+ ret = g_test_run();
+ qtest_quit(global_qtest);
+
+ return ret;
+}
diff --git a/qemu/tests/ipoctal232-test.c b/qemu/tests/ipoctal232-test.c
index 3ac1714b4..846aaf571 100644
--- a/qemu/tests/ipoctal232-test.c
+++ b/qemu/tests/ipoctal232-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void nop(void)
diff --git a/qemu/tests/ivshmem-test.c b/qemu/tests/ivshmem-test.c
new file mode 100644
index 000000000..c027ff1e0
--- /dev/null
+++ b/qemu/tests/ivshmem-test.c
@@ -0,0 +1,518 @@
+/*
+ * QTest testcase for ivshmem
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <sys/mman.h>
+#include "contrib/ivshmem-server/ivshmem-server.h"
+#include "libqos/pci-pc.h"
+#include "libqtest.h"
+#include "qemu-common.h"
+
+#define TMPSHMSIZE (1 << 20)
+static char *tmpshm;
+static void *tmpshmem;
+static char *tmpdir;
+static char *tmpserver;
+
+static void save_fn(QPCIDevice *dev, int devfn, void *data)
+{
+ QPCIDevice **pdev = (QPCIDevice **) data;
+
+ *pdev = dev;
+}
+
+static QPCIDevice *get_device(QPCIBus *pcibus)
+{
+ QPCIDevice *dev;
+
+ dev = NULL;
+ qpci_device_foreach(pcibus, 0x1af4, 0x1110, save_fn, &dev);
+ g_assert(dev != NULL);
+
+ return dev;
+}
+
+typedef struct _IVState {
+ QTestState *qtest;
+ void *reg_base, *mem_base;
+ QPCIBus *pcibus;
+ QPCIDevice *dev;
+} IVState;
+
+enum Reg {
+ INTRMASK = 0,
+ INTRSTATUS = 4,
+ IVPOSITION = 8,
+ DOORBELL = 12,
+};
+
+static const char* reg2str(enum Reg reg) {
+ switch (reg) {
+ case INTRMASK:
+ return "IntrMask";
+ case INTRSTATUS:
+ return "IntrStatus";
+ case IVPOSITION:
+ return "IVPosition";
+ case DOORBELL:
+ return "DoorBell";
+ default:
+ return NULL;
+ }
+}
+
+static inline unsigned in_reg(IVState *s, enum Reg reg)
+{
+ const char *name = reg2str(reg);
+ QTestState *qtest = global_qtest;
+ unsigned res;
+
+ global_qtest = s->qtest;
+ res = qpci_io_readl(s->dev, s->reg_base + reg);
+ g_test_message("*%s -> %x\n", name, res);
+ global_qtest = qtest;
+
+ return res;
+}
+
+static inline void out_reg(IVState *s, enum Reg reg, unsigned v)
+{
+ const char *name = reg2str(reg);
+ QTestState *qtest = global_qtest;
+
+ global_qtest = s->qtest;
+ g_test_message("%x -> *%s\n", v, name);
+ qpci_io_writel(s->dev, s->reg_base + reg, v);
+ global_qtest = qtest;
+}
+
+static void cleanup_vm(IVState *s)
+{
+ g_free(s->dev);
+ qpci_free_pc(s->pcibus);
+ qtest_quit(s->qtest);
+}
+
+static void setup_vm_cmd(IVState *s, const char *cmd, bool msix)
+{
+ uint64_t barsize;
+
+ s->qtest = qtest_start(cmd);
+ s->pcibus = qpci_init_pc();
+ s->dev = get_device(s->pcibus);
+
+ s->reg_base = qpci_iomap(s->dev, 0, &barsize);
+ g_assert_nonnull(s->reg_base);
+ g_assert_cmpuint(barsize, ==, 256);
+
+ if (msix) {
+ qpci_msix_enable(s->dev);
+ }
+
+ s->mem_base = qpci_iomap(s->dev, 2, &barsize);
+ g_assert_nonnull(s->mem_base);
+ g_assert_cmpuint(barsize, ==, TMPSHMSIZE);
+
+ qpci_device_enable(s->dev);
+}
+
+static void setup_vm(IVState *s)
+{
+ char *cmd = g_strdup_printf("-object memory-backend-file"
+ ",id=mb1,size=1M,share,mem-path=/dev/shm%s"
+ " -device ivshmem-plain,memdev=mb1", tmpshm);
+
+ setup_vm_cmd(s, cmd, false);
+
+ g_free(cmd);
+}
+
+static void test_ivshmem_single(void)
+{
+ IVState state, *s;
+ uint32_t data[1024];
+ int i;
+
+ setup_vm(&state);
+ s = &state;
+
+ /* initial state of readable registers */
+ g_assert_cmpuint(in_reg(s, INTRMASK), ==, 0);
+ g_assert_cmpuint(in_reg(s, INTRSTATUS), ==, 0);
+ g_assert_cmpuint(in_reg(s, IVPOSITION), ==, 0);
+
+ /* trigger interrupt via registers */
+ out_reg(s, INTRMASK, 0xffffffff);
+ g_assert_cmpuint(in_reg(s, INTRMASK), ==, 0xffffffff);
+ out_reg(s, INTRSTATUS, 1);
+ /* check interrupt status */
+ g_assert_cmpuint(in_reg(s, INTRSTATUS), ==, 1);
+ /* reading clears */
+ g_assert_cmpuint(in_reg(s, INTRSTATUS), ==, 0);
+ /* TODO intercept actual interrupt (needs qtest work) */
+
+ /* invalid register access */
+ out_reg(s, IVPOSITION, 1);
+ in_reg(s, DOORBELL);
+
+ /* ring the (non-functional) doorbell */
+ out_reg(s, DOORBELL, 8 << 16);
+
+ /* write shared memory */
+ for (i = 0; i < G_N_ELEMENTS(data); i++) {
+ data[i] = i;
+ }
+ qtest_memwrite(s->qtest, (uintptr_t)s->mem_base, data, sizeof(data));
+
+ /* verify write */
+ for (i = 0; i < G_N_ELEMENTS(data); i++) {
+ g_assert_cmpuint(((uint32_t *)tmpshmem)[i], ==, i);
+ }
+
+ /* read it back and verify read */
+ memset(data, 0, sizeof(data));
+ qtest_memread(s->qtest, (uintptr_t)s->mem_base, data, sizeof(data));
+ for (i = 0; i < G_N_ELEMENTS(data); i++) {
+ g_assert_cmpuint(data[i], ==, i);
+ }
+
+ cleanup_vm(s);
+}
+
+static void test_ivshmem_pair(void)
+{
+ IVState state1, state2, *s1, *s2;
+ char *data;
+ int i;
+
+ setup_vm(&state1);
+ s1 = &state1;
+ setup_vm(&state2);
+ s2 = &state2;
+
+ data = g_malloc0(TMPSHMSIZE);
+
+ /* host write, guest 1 & 2 read */
+ memset(tmpshmem, 0x42, TMPSHMSIZE);
+ qtest_memread(s1->qtest, (uintptr_t)s1->mem_base, data, TMPSHMSIZE);
+ for (i = 0; i < TMPSHMSIZE; i++) {
+ g_assert_cmpuint(data[i], ==, 0x42);
+ }
+ qtest_memread(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
+ for (i = 0; i < TMPSHMSIZE; i++) {
+ g_assert_cmpuint(data[i], ==, 0x42);
+ }
+
+ /* guest 1 write, guest 2 read */
+ memset(data, 0x43, TMPSHMSIZE);
+ qtest_memwrite(s1->qtest, (uintptr_t)s1->mem_base, data, TMPSHMSIZE);
+ memset(data, 0, TMPSHMSIZE);
+ qtest_memread(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
+ for (i = 0; i < TMPSHMSIZE; i++) {
+ g_assert_cmpuint(data[i], ==, 0x43);
+ }
+
+ /* guest 2 write, guest 1 read */
+ memset(data, 0x44, TMPSHMSIZE);
+ qtest_memwrite(s2->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
+ memset(data, 0, TMPSHMSIZE);
+ qtest_memread(s1->qtest, (uintptr_t)s2->mem_base, data, TMPSHMSIZE);
+ for (i = 0; i < TMPSHMSIZE; i++) {
+ g_assert_cmpuint(data[i], ==, 0x44);
+ }
+
+ cleanup_vm(s1);
+ cleanup_vm(s2);
+ g_free(data);
+}
+
+typedef struct ServerThread {
+ GThread *thread;
+ IvshmemServer *server;
+ int pipe[2]; /* to handle quit */
+} ServerThread;
+
+static void *server_thread(void *data)
+{
+ ServerThread *t = data;
+ IvshmemServer *server = t->server;
+
+ while (true) {
+ fd_set fds;
+ int maxfd, ret;
+
+ FD_ZERO(&fds);
+ FD_SET(t->pipe[0], &fds);
+ maxfd = t->pipe[0] + 1;
+
+ ivshmem_server_get_fds(server, &fds, &maxfd);
+
+ ret = select(maxfd, &fds, NULL, NULL, NULL);
+
+ if (ret < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ g_critical("select error: %s\n", strerror(errno));
+ break;
+ }
+ if (ret == 0) {
+ continue;
+ }
+
+ if (FD_ISSET(t->pipe[0], &fds)) {
+ break;
+ }
+
+ if (ivshmem_server_handle_fds(server, &fds, maxfd) < 0) {
+ g_critical("ivshmem_server_handle_fds() failed\n");
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+static void setup_vm_with_server(IVState *s, int nvectors, bool msi)
+{
+ char *cmd = g_strdup_printf("-chardev socket,id=chr0,path=%s,nowait "
+ "-device ivshmem%s,chardev=chr0,vectors=%d",
+ tmpserver,
+ msi ? "-doorbell" : ",size=1M,msi=off",
+ nvectors);
+
+ setup_vm_cmd(s, cmd, msi);
+
+ g_free(cmd);
+}
+
+static void test_ivshmem_server(bool msi)
+{
+ IVState state1, state2, *s1, *s2;
+ ServerThread thread;
+ IvshmemServer server;
+ int ret, vm1, vm2;
+ int nvectors = 2;
+ guint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+
+ ret = ivshmem_server_init(&server, tmpserver, tmpshm, true,
+ TMPSHMSIZE, nvectors,
+ g_test_verbose());
+ g_assert_cmpint(ret, ==, 0);
+
+ ret = ivshmem_server_start(&server);
+ g_assert_cmpint(ret, ==, 0);
+
+ thread.server = &server;
+ ret = pipe(thread.pipe);
+ g_assert_cmpint(ret, ==, 0);
+ thread.thread = g_thread_new("ivshmem-server", server_thread, &thread);
+ g_assert(thread.thread != NULL);
+
+ setup_vm_with_server(&state1, nvectors, msi);
+ s1 = &state1;
+ setup_vm_with_server(&state2, nvectors, msi);
+ s2 = &state2;
+
+ /* check got different VM ids */
+ vm1 = in_reg(s1, IVPOSITION);
+ vm2 = in_reg(s2, IVPOSITION);
+ g_assert_cmpint(vm1, >=, 0);
+ g_assert_cmpint(vm2, >=, 0);
+ g_assert_cmpint(vm1, !=, vm2);
+
+ /* check number of MSI-X vectors */
+ global_qtest = s1->qtest;
+ if (msi) {
+ ret = qpci_msix_table_size(s1->dev);
+ g_assert_cmpuint(ret, ==, nvectors);
+ }
+
+ /* TODO test behavior before MSI-X is enabled */
+
+ /* ping vm2 -> vm1 on vector 0 */
+ if (msi) {
+ ret = qpci_msix_pending(s1->dev, 0);
+ g_assert_cmpuint(ret, ==, 0);
+ } else {
+ g_assert_cmpuint(in_reg(s1, INTRSTATUS), ==, 0);
+ }
+ out_reg(s2, DOORBELL, vm1 << 16);
+ do {
+ g_usleep(10000);
+ ret = msi ? qpci_msix_pending(s1->dev, 0) : in_reg(s1, INTRSTATUS);
+ } while (ret == 0 && g_get_monotonic_time() < end_time);
+ g_assert_cmpuint(ret, !=, 0);
+
+ /* ping vm1 -> vm2 on vector 1 */
+ global_qtest = s2->qtest;
+ if (msi) {
+ ret = qpci_msix_pending(s2->dev, 1);
+ g_assert_cmpuint(ret, ==, 0);
+ } else {
+ g_assert_cmpuint(in_reg(s2, INTRSTATUS), ==, 0);
+ }
+ out_reg(s1, DOORBELL, vm2 << 16 | 1);
+ do {
+ g_usleep(10000);
+ ret = msi ? qpci_msix_pending(s2->dev, 1) : in_reg(s2, INTRSTATUS);
+ } while (ret == 0 && g_get_monotonic_time() < end_time);
+ g_assert_cmpuint(ret, !=, 0);
+
+ cleanup_vm(s2);
+ cleanup_vm(s1);
+
+ if (qemu_write_full(thread.pipe[1], "q", 1) != 1) {
+ g_error("qemu_write_full: %s", g_strerror(errno));
+ }
+
+ g_thread_join(thread.thread);
+
+ ivshmem_server_close(&server);
+ close(thread.pipe[1]);
+ close(thread.pipe[0]);
+}
+
+static void test_ivshmem_server_msi(void)
+{
+ test_ivshmem_server(true);
+}
+
+static void test_ivshmem_server_irq(void)
+{
+ test_ivshmem_server(false);
+}
+
+#define PCI_SLOT_HP 0x06
+
+static void test_ivshmem_hotplug(void)
+{
+ gchar *opts;
+
+ qtest_start("");
+
+ opts = g_strdup_printf("'shm': '%s', 'size': '1M'", tmpshm);
+
+ qpci_plug_device_test("ivshmem", "iv1", PCI_SLOT_HP, opts);
+ qpci_unplug_acpi_device_test("iv1", PCI_SLOT_HP);
+
+ qtest_end();
+ g_free(opts);
+}
+
+static void test_ivshmem_memdev(void)
+{
+ IVState state;
+
+ /* just for the sake of checking memory-backend property */
+ setup_vm_cmd(&state, "-object memory-backend-ram,size=1M,id=mb1"
+ " -device ivshmem-plain,memdev=mb1", false);
+
+ cleanup_vm(&state);
+}
+
+static void cleanup(void)
+{
+ if (tmpshmem) {
+ munmap(tmpshmem, TMPSHMSIZE);
+ tmpshmem = NULL;
+ }
+
+ if (tmpshm) {
+ shm_unlink(tmpshm);
+ g_free(tmpshm);
+ tmpshm = NULL;
+ }
+
+ if (tmpserver) {
+ g_unlink(tmpserver);
+ g_free(tmpserver);
+ tmpserver = NULL;
+ }
+
+ if (tmpdir) {
+ g_rmdir(tmpdir);
+ tmpdir = NULL;
+ }
+}
+
+static void abrt_handler(void *data)
+{
+ cleanup();
+}
+
+static gchar *mktempshm(int size, int *fd)
+{
+ while (true) {
+ gchar *name;
+
+ name = g_strdup_printf("/qtest-%u-%u", getpid(), g_random_int());
+ *fd = shm_open(name, O_CREAT|O_RDWR|O_EXCL,
+ S_IRWXU|S_IRWXG|S_IRWXO);
+ if (*fd > 0) {
+ g_assert(ftruncate(*fd, size) == 0);
+ return name;
+ }
+
+ g_free(name);
+
+ if (errno != EEXIST) {
+ perror("shm_open");
+ return NULL;
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int ret, fd;
+ gchar dir[] = "/tmp/ivshmem-test.XXXXXX";
+
+#if !GLIB_CHECK_VERSION(2, 31, 0)
+ if (!g_thread_supported()) {
+ g_thread_init(NULL);
+ }
+#endif
+
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_abrt_handler(abrt_handler, NULL);
+ /* shm */
+ tmpshm = mktempshm(TMPSHMSIZE, &fd);
+ if (!tmpshm) {
+ return 0;
+ }
+ tmpshmem = mmap(0, TMPSHMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ g_assert(tmpshmem != MAP_FAILED);
+ /* server */
+ if (mkdtemp(dir) == NULL) {
+ g_error("mkdtemp: %s", g_strerror(errno));
+ }
+ tmpdir = dir;
+ tmpserver = g_strconcat(tmpdir, "/server", NULL);
+
+ qtest_add_func("/ivshmem/single", test_ivshmem_single);
+ qtest_add_func("/ivshmem/hotplug", test_ivshmem_hotplug);
+ qtest_add_func("/ivshmem/memdev", test_ivshmem_memdev);
+ if (g_test_slow()) {
+ qtest_add_func("/ivshmem/pair", test_ivshmem_pair);
+ qtest_add_func("/ivshmem/server-msi", test_ivshmem_server_msi);
+ qtest_add_func("/ivshmem/server-irq", test_ivshmem_server_irq);
+ }
+
+ ret = g_test_run();
+
+ cleanup();
+
+ return ret;
+}
diff --git a/qemu/tests/libqos/ahci.c b/qemu/tests/libqos/ahci.c
index cf66b3e32..ac6c155c8 100644
--- a/qemu/tests/libqos/ahci.c
+++ b/qemu/tests/libqos/ahci.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqtest.h"
@@ -74,7 +75,11 @@ AHCICommandProp ahci_command_properties[] = {
.lba48 = true, .write = true, .ncq = true },
{ .cmd = CMD_READ_MAX, .lba28 = true },
{ .cmd = CMD_READ_MAX_EXT, .lba48 = true },
- { .cmd = CMD_FLUSH_CACHE, .data = false }
+ { .cmd = CMD_FLUSH_CACHE, .data = false },
+ { .cmd = CMD_PACKET, .data = true, .size = 16,
+ .atapi = true, .pio = true },
+ { .cmd = CMD_PACKET_ID, .data = true, .pio = true,
+ .size = 512, .read = true }
};
struct AHCICommand {
@@ -90,7 +95,7 @@ struct AHCICommand {
/* Data to be transferred to the guest */
AHCICommandHeader header;
RegH2DFIS fis;
- void *atapi_cmd;
+ unsigned char *atapi_cmd;
};
/**
@@ -110,6 +115,11 @@ void ahci_free(AHCIQState *ahci, uint64_t addr)
qfree(ahci->parent, addr);
}
+bool is_atapi(AHCIQState *ahci, uint8_t port)
+{
+ return ahci_px_rreg(ahci, port, AHCI_PX_SIG) == AHCI_SIGNATURE_CDROM;
+}
+
/**
* Locate, verify, and return a handle to the AHCI device.
*/
@@ -592,6 +602,82 @@ inline unsigned size_to_prdtl(unsigned bytes, unsigned bytes_per_prd)
return (bytes + bytes_per_prd - 1) / bytes_per_prd;
}
+const AHCIOpts default_opts = { .size = 0 };
+
+/**
+ * ahci_exec: execute a given command on a specific
+ * AHCI port.
+ *
+ * @ahci: The device to send the command to
+ * @port: The port number of the SATA device we wish
+ * to have execute this command
+ * @op: The S/ATA command to execute, or if opts.atapi
+ * is true, the SCSI command code.
+ * @opts: Optional arguments to modify execution behavior.
+ */
+void ahci_exec(AHCIQState *ahci, uint8_t port,
+ uint8_t op, const AHCIOpts *opts_in)
+{
+ AHCICommand *cmd;
+ int rc;
+ AHCIOpts *opts;
+
+ opts = g_memdup((opts_in == NULL ? &default_opts : opts_in),
+ sizeof(AHCIOpts));
+
+ /* No guest buffer provided, create one. */
+ if (opts->size && !opts->buffer) {
+ opts->buffer = ahci_alloc(ahci, opts->size);
+ g_assert(opts->buffer);
+ qmemset(opts->buffer, 0x00, opts->size);
+ }
+
+ /* Command creation */
+ if (opts->atapi) {
+ cmd = ahci_atapi_command_create(op);
+ if (opts->atapi_dma) {
+ ahci_command_enable_atapi_dma(cmd);
+ }
+ } else {
+ cmd = ahci_command_create(op);
+ }
+ ahci_command_adjust(cmd, opts->lba, opts->buffer,
+ opts->size, opts->prd_size);
+
+ if (opts->pre_cb) {
+ rc = opts->pre_cb(ahci, cmd, opts);
+ g_assert_cmpint(rc, ==, 0);
+ }
+
+ /* Write command to memory and issue it */
+ ahci_command_commit(ahci, cmd, port);
+ ahci_command_issue_async(ahci, cmd);
+ if (opts->error) {
+ qmp_eventwait("STOP");
+ }
+ if (opts->mid_cb) {
+ rc = opts->mid_cb(ahci, cmd, opts);
+ g_assert_cmpint(rc, ==, 0);
+ }
+ if (opts->error) {
+ qmp_async("{'execute':'cont' }");
+ qmp_eventwait("RESUME");
+ }
+
+ /* Wait for command to complete and verify sanity */
+ ahci_command_wait(ahci, cmd);
+ ahci_command_verify(ahci, cmd);
+ if (opts->post_cb) {
+ rc = opts->post_cb(ahci, cmd, opts);
+ g_assert_cmpint(rc, ==, 0);
+ }
+ ahci_command_free(cmd);
+ if (opts->buffer != opts_in->buffer) {
+ ahci_free(ahci, opts->buffer);
+ }
+ g_free(opts);
+}
+
/* Issue a command, expecting it to fail and STOP the VM */
AHCICommand *ahci_guest_io_halt(AHCIQState *ahci, uint8_t port,
uint8_t ide_cmd, uint64_t buffer,
@@ -659,16 +745,16 @@ void ahci_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
props = ahci_command_find(ide_cmd);
g_assert(props);
ptr = ahci_alloc(ahci, bufsize);
- g_assert(ptr);
+ g_assert(!bufsize || ptr);
qmemset(ptr, 0x00, bufsize);
- if (props->write) {
+ if (bufsize && props->write) {
bufwrite(ptr, buffer, bufsize);
}
ahci_guest_io(ahci, port, ide_cmd, ptr, bufsize, sector);
- if (props->read) {
+ if (bufsize && props->read) {
bufread(ptr, buffer, bufsize);
}
@@ -731,6 +817,18 @@ static void command_table_init(AHCICommand *cmd)
memset(fis->aux, 0x00, ARRAY_SIZE(fis->aux));
}
+void ahci_command_enable_atapi_dma(AHCICommand *cmd)
+{
+ RegH2DFIS *fis = &(cmd->fis);
+ g_assert(cmd->props->atapi);
+ fis->feature_low |= 0x01;
+ cmd->interrupts &= ~AHCI_PX_IS_PSS;
+ cmd->props->dma = true;
+ cmd->props->pio = false;
+ /* BUG: We expect the DMA Setup interrupt for DMA commands */
+ /* cmd->interrupts |= AHCI_PX_IS_DSS; */
+}
+
AHCICommand *ahci_command_create(uint8_t command_name)
{
AHCICommandProp *props = ahci_command_find(command_name);
@@ -742,10 +840,10 @@ AHCICommand *ahci_command_create(uint8_t command_name)
g_assert(!(props->lba28 && props->lba48));
g_assert(!(props->read && props->write));
g_assert(!props->size || props->data);
- g_assert(!props->ncq || (props->ncq && props->lba48));
+ g_assert(!props->ncq || props->lba48);
/* Defaults and book-keeping */
- cmd->props = props;
+ cmd->props = g_memdup(props, sizeof(AHCICommandProp));
cmd->name = command_name;
cmd->xbytes = props->size;
cmd->prd_size = 4096;
@@ -767,8 +865,23 @@ AHCICommand *ahci_command_create(uint8_t command_name)
return cmd;
}
+AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd)
+{
+ AHCICommand *cmd = ahci_command_create(CMD_PACKET);
+ cmd->atapi_cmd = g_malloc0(16);
+ cmd->atapi_cmd[0] = scsi_cmd;
+ /* ATAPI needs a PIO transfer chunk size set inside of the LBA registers.
+ * The block/sector size is a natural default. */
+ cmd->fis.lba_lo[1] = ATAPI_SECTOR_SIZE >> 8 & 0xFF;
+ cmd->fis.lba_lo[2] = ATAPI_SECTOR_SIZE & 0xFF;
+
+ return cmd;
+}
+
void ahci_command_free(AHCICommand *cmd)
{
+ g_free(cmd->atapi_cmd);
+ g_free(cmd->props);
g_free(cmd);
}
@@ -782,10 +895,34 @@ void ahci_command_clr_flags(AHCICommand *cmd, uint16_t cmdh_flags)
cmd->header.flags &= ~cmdh_flags;
}
+static void ahci_atapi_command_set_offset(AHCICommand *cmd, uint64_t lba)
+{
+ unsigned char *cbd = cmd->atapi_cmd;
+ g_assert(cbd);
+
+ switch (cbd[0]) {
+ case CMD_ATAPI_READ_10:
+ g_assert_cmpuint(lba, <=, UINT32_MAX);
+ stl_be_p(&cbd[2], lba);
+ break;
+ default:
+ /* SCSI doesn't have uniform packet formats,
+ * so you have to add support for it manually. Sorry! */
+ g_assert_not_reached();
+ }
+}
+
void ahci_command_set_offset(AHCICommand *cmd, uint64_t lba_sect)
{
RegH2DFIS *fis = &(cmd->fis);
- if (cmd->props->lba28) {
+
+ if (cmd->props->atapi) {
+ ahci_atapi_command_set_offset(cmd, lba_sect);
+ return;
+ } else if (!cmd->props->data && !lba_sect) {
+ /* Not meaningful, ignore. */
+ return;
+ } else if (cmd->props->lba28) {
g_assert_cmphex(lba_sect, <=, 0xFFFFFFF);
} else if (cmd->props->lba48 || cmd->props->ncq) {
g_assert_cmphex(lba_sect, <=, 0xFFFFFFFFFFFF);
@@ -811,6 +948,24 @@ void ahci_command_set_buffer(AHCICommand *cmd, uint64_t buffer)
cmd->buffer = buffer;
}
+static void ahci_atapi_set_size(AHCICommand *cmd, uint64_t xbytes)
+{
+ unsigned char *cbd = cmd->atapi_cmd;
+ uint64_t nsectors = xbytes / 2048;
+ g_assert(cbd);
+
+ switch (cbd[0]) {
+ case CMD_ATAPI_READ_10:
+ g_assert_cmpuint(nsectors, <=, UINT16_MAX);
+ stw_be_p(&cbd[7], nsectors);
+ break;
+ default:
+ /* SCSI doesn't have uniform packet formats,
+ * so you have to add support for it manually. Sorry! */
+ g_assert_not_reached();
+ }
+}
+
void ahci_command_set_sizes(AHCICommand *cmd, uint64_t xbytes,
unsigned prd_size)
{
@@ -829,6 +984,8 @@ void ahci_command_set_sizes(AHCICommand *cmd, uint64_t xbytes,
NCQFIS *nfis = (NCQFIS *)&(cmd->fis);
nfis->sector_low = sect_count & 0xFF;
nfis->sector_hi = (sect_count >> 8) & 0xFF;
+ } else if (cmd->props->atapi) {
+ ahci_atapi_set_size(cmd, xbytes);
} else {
cmd->fis.count = sect_count;
}
@@ -877,9 +1034,14 @@ void ahci_command_commit(AHCIQState *ahci, AHCICommand *cmd, uint8_t port)
g_assert((table_ptr & 0x7F) == 0x00);
cmd->header.ctba = table_ptr;
- /* Commit the command header and command FIS */
+ /* Commit the command header (part of the Command List Buffer) */
ahci_set_command_header(ahci, port, cmd->slot, &(cmd->header));
+ /* Now, write the command table (FIS, ACMD, and PRDT) -- FIS first, */
ahci_write_fis(ahci, cmd);
+ /* Then ATAPI CMD, if needed */
+ if (cmd->props->atapi) {
+ memwrite(table_ptr + 0x40, cmd->atapi_cmd, 16);
+ }
/* Construct and write the PRDs to the command table */
g_assert_cmphex(prdtl, ==, cmd->header.prdtl);
diff --git a/qemu/tests/libqos/ahci.h b/qemu/tests/libqos/ahci.h
index cffc2c351..71dd7a6e5 100644
--- a/qemu/tests/libqos/ahci.h
+++ b/qemu/tests/libqos/ahci.h
@@ -25,9 +25,6 @@
* THE SOFTWARE.
*/
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdbool.h>
#include "libqos/libqos.h"
#include "libqos/pci.h"
#include "libqos/malloc-pc.h"
@@ -244,6 +241,10 @@
#define AHCI_VERSION_1_3 (0x00010300)
#define AHCI_SECTOR_SIZE (512)
+#define ATAPI_SECTOR_SIZE (2048)
+
+#define AHCI_SIGNATURE_CDROM (0xeb140101)
+#define AHCI_SIGNATURE_DISK (0x00000101)
/* FIS types */
enum {
@@ -277,11 +278,18 @@ enum {
CMD_READ_MAX_EXT = 0x27,
CMD_FLUSH_CACHE = 0xE7,
CMD_IDENTIFY = 0xEC,
+ CMD_PACKET = 0xA0,
+ CMD_PACKET_ID = 0xA1,
/* NCQ */
READ_FPDMA_QUEUED = 0x60,
WRITE_FPDMA_QUEUED = 0x61,
};
+/* ATAPI Commands */
+enum {
+ CMD_ATAPI_READ_10 = 0x28,
+};
+
/* AHCI Command Header Flags & Masks*/
#define CMDH_CFL (0x1F)
#define CMDH_ATAPI (0x20)
@@ -451,6 +459,21 @@ typedef struct PRD {
/* Opaque, defined within ahci.c */
typedef struct AHCICommand AHCICommand;
+/* Options to ahci_exec */
+typedef struct AHCIOpts {
+ size_t size;
+ unsigned prd_size;
+ uint64_t lba;
+ uint64_t buffer;
+ bool atapi;
+ bool atapi_dma;
+ bool error;
+ int (*pre_cb)(AHCIQState*, AHCICommand*, const struct AHCIOpts *);
+ int (*mid_cb)(AHCIQState*, AHCICommand*, const struct AHCIOpts *);
+ int (*post_cb)(AHCIQState*, AHCICommand*, const struct AHCIOpts *);
+ void *opaque;
+} AHCIOpts;
+
/*** Macro Utilities ***/
#define BITANY(data, mask) (((data) & (mask)) != 0)
#define BITSET(data, mask) (((data) & (mask)) == (mask))
@@ -527,14 +550,28 @@ static inline void ahci_px_clr(AHCIQState *ahci, uint8_t port,
/*** Prototypes ***/
uint64_t ahci_alloc(AHCIQState *ahci, size_t bytes);
void ahci_free(AHCIQState *ahci, uint64_t addr);
+void ahci_clean_mem(AHCIQState *ahci);
+
+/* Device management */
QPCIDevice *get_ahci_device(uint32_t *fingerprint);
void free_ahci_device(QPCIDevice *dev);
-void ahci_clean_mem(AHCIQState *ahci);
void ahci_pci_enable(AHCIQState *ahci);
void start_ahci_device(AHCIQState *ahci);
void ahci_hba_enable(AHCIQState *ahci);
+
+/* Port Management */
unsigned ahci_port_select(AHCIQState *ahci);
void ahci_port_clear(AHCIQState *ahci, uint8_t port);
+
+/* Command header / table management */
+unsigned ahci_pick_cmd(AHCIQState *ahci, uint8_t port);
+void ahci_get_command_header(AHCIQState *ahci, uint8_t port,
+ uint8_t slot, AHCICommandHeader *cmd);
+void ahci_set_command_header(AHCIQState *ahci, uint8_t port,
+ uint8_t slot, AHCICommandHeader *cmd);
+void ahci_destroy_command(AHCIQState *ahci, uint8_t port, uint8_t slot);
+
+/* AHCI sanity check routines */
void ahci_port_check_error(AHCIQState *ahci, uint8_t port);
void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t port,
uint32_t intr_mask);
@@ -543,14 +580,12 @@ void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t port, uint8_t slot);
void ahci_port_check_pio_sanity(AHCIQState *ahci, uint8_t port,
uint8_t slot, size_t buffsize);
void ahci_port_check_cmd_sanity(AHCIQState *ahci, AHCICommand *cmd);
-void ahci_get_command_header(AHCIQState *ahci, uint8_t port,
- uint8_t slot, AHCICommandHeader *cmd);
-void ahci_set_command_header(AHCIQState *ahci, uint8_t port,
- uint8_t slot, AHCICommandHeader *cmd);
-void ahci_destroy_command(AHCIQState *ahci, uint8_t port, uint8_t slot);
-void ahci_write_fis(AHCIQState *ahci, AHCICommand *cmd);
-unsigned ahci_pick_cmd(AHCIQState *ahci, uint8_t port);
+
+/* Misc */
+bool is_atapi(AHCIQState *ahci, uint8_t port);
unsigned size_to_prdtl(unsigned bytes, unsigned bytes_per_prd);
+
+/* Command: Macro level execution */
void ahci_guest_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
uint64_t gbuffer, size_t size, uint64_t sector);
AHCICommand *ahci_guest_io_halt(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
@@ -558,9 +593,12 @@ AHCICommand *ahci_guest_io_halt(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
void ahci_guest_io_resume(AHCIQState *ahci, AHCICommand *cmd);
void ahci_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd,
void *buffer, size_t bufsize, uint64_t sector);
+void ahci_exec(AHCIQState *ahci, uint8_t port,
+ uint8_t op, const AHCIOpts *opts);
-/* Command Lifecycle */
+/* Command: Fine-grained lifecycle */
AHCICommand *ahci_command_create(uint8_t command_name);
+AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd);
void ahci_command_commit(AHCIQState *ahci, AHCICommand *cmd, uint8_t port);
void ahci_command_issue(AHCIQState *ahci, AHCICommand *cmd);
void ahci_command_issue_async(AHCIQState *ahci, AHCICommand *cmd);
@@ -568,7 +606,7 @@ void ahci_command_wait(AHCIQState *ahci, AHCICommand *cmd);
void ahci_command_verify(AHCIQState *ahci, AHCICommand *cmd);
void ahci_command_free(AHCICommand *cmd);
-/* Command adjustments */
+/* Command: adjustments */
void ahci_command_set_flags(AHCICommand *cmd, uint16_t cmdh_flags);
void ahci_command_clr_flags(AHCICommand *cmd, uint16_t cmdh_flags);
void ahci_command_set_offset(AHCICommand *cmd, uint64_t lba_sect);
@@ -577,10 +615,13 @@ void ahci_command_set_size(AHCICommand *cmd, uint64_t xbytes);
void ahci_command_set_prd_size(AHCICommand *cmd, unsigned prd_size);
void ahci_command_set_sizes(AHCICommand *cmd, uint64_t xbytes,
unsigned prd_size);
+void ahci_command_set_acmd(AHCICommand *cmd, void *acmd);
+void ahci_command_enable_atapi_dma(AHCICommand *cmd);
void ahci_command_adjust(AHCICommand *cmd, uint64_t lba_sect, uint64_t gbuffer,
uint64_t xbytes, unsigned prd_size);
-/* Command Misc */
+/* Command: Misc */
uint8_t ahci_command_slot(AHCICommand *cmd);
+void ahci_write_fis(AHCIQState *ahci, AHCICommand *cmd);
#endif
diff --git a/qemu/tests/libqos/fw_cfg.c b/qemu/tests/libqos/fw_cfg.c
index ef00fedf1..76894d575 100644
--- a/qemu/tests/libqos/fw_cfg.c
+++ b/qemu/tests/libqos/fw_cfg.c
@@ -12,6 +12,7 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqos/fw_cfg.h"
#include "libqtest.h"
diff --git a/qemu/tests/libqos/fw_cfg.h b/qemu/tests/libqos/fw_cfg.h
index 61b1548b4..e8371b231 100644
--- a/qemu/tests/libqos/fw_cfg.h
+++ b/qemu/tests/libqos/fw_cfg.h
@@ -13,8 +13,6 @@
#ifndef LIBQOS_FW_CFG_H
#define LIBQOS_FW_CFG_H
-#include <stdint.h>
-#include <sys/types.h>
typedef struct QFWCFG QFWCFG;
diff --git a/qemu/tests/libqos/i2c-imx.c b/qemu/tests/libqos/i2c-imx.c
new file mode 100644
index 000000000..51c3468f9
--- /dev/null
+++ b/qemu/tests/libqos/i2c-imx.c
@@ -0,0 +1,208 @@
+/*
+ * QTest i.MX I2C driver
+ *
+ * Copyright (c) 2013 Jean-Christophe Dubois
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "libqos/i2c.h"
+
+#include <glib.h>
+
+#include "libqtest.h"
+
+#include "hw/i2c/imx_i2c.h"
+
+enum IMXI2CDirection {
+ IMX_I2C_READ,
+ IMX_I2C_WRITE,
+};
+
+typedef struct IMXI2C {
+ I2CAdapter parent;
+
+ uint64_t addr;
+} IMXI2C;
+
+
+static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr,
+ enum IMXI2CDirection direction)
+{
+ writeb(s->addr + I2DR_ADDR, (addr << 1) |
+ (direction == IMX_I2C_READ ? 1 : 0));
+}
+
+static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr,
+ const uint8_t *buf, uint16_t len)
+{
+ IMXI2C *s = (IMXI2C *)i2c;
+ uint8_t data;
+ uint8_t status;
+ uint16_t size = 0;
+
+ if (!len) {
+ return;
+ }
+
+ /* set the bus for write */
+ data = I2CR_IEN |
+ I2CR_IIEN |
+ I2CR_MSTA |
+ I2CR_MTX |
+ I2CR_TXAK;
+
+ writeb(s->addr + I2CR_ADDR, data);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ /* set the slave address */
+ imx_i2c_set_slave_addr(s, addr, IMX_I2C_WRITE);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+ g_assert((status & I2SR_RXAK) == 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ while (size < len) {
+ /* check we are still busy */
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ /* write the data */
+ writeb(s->addr + I2DR_ADDR, buf[size]);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+ g_assert((status & I2SR_RXAK) == 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ size++;
+ }
+
+ /* release the bus */
+ data &= ~(I2CR_MSTA | I2CR_MTX);
+ writeb(s->addr + I2CR_ADDR, data);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) == 0);
+}
+
+static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr,
+ uint8_t *buf, uint16_t len)
+{
+ IMXI2C *s = (IMXI2C *)i2c;
+ uint8_t data;
+ uint8_t status;
+ uint16_t size = 0;
+
+ if (!len) {
+ return;
+ }
+
+ /* set the bus for write */
+ data = I2CR_IEN |
+ I2CR_IIEN |
+ I2CR_MSTA |
+ I2CR_MTX |
+ I2CR_TXAK;
+
+ writeb(s->addr + I2CR_ADDR, data);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ /* set the slave address */
+ imx_i2c_set_slave_addr(s, addr, IMX_I2C_READ);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+ g_assert((status & I2SR_RXAK) == 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ /* set the bus for read */
+ data &= ~I2CR_MTX;
+ /* if only one byte don't ack */
+ if (len != 1) {
+ data &= ~I2CR_TXAK;
+ }
+ writeb(s->addr + I2CR_ADDR, data);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ /* dummy read */
+ readb(s->addr + I2DR_ADDR);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ while (size < len) {
+ /* check we are still busy */
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ if (size == (len - 1)) {
+ /* stop the read transaction */
+ data &= ~(I2CR_MSTA | I2CR_MTX);
+ } else {
+ /* ack the data read */
+ data |= I2CR_TXAK;
+ }
+ writeb(s->addr + I2CR_ADDR, data);
+
+ /* read the data */
+ buf[size] = readb(s->addr + I2DR_ADDR);
+
+ if (size != (len - 1)) {
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ }
+
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ size++;
+ }
+
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) == 0);
+}
+
+I2CAdapter *imx_i2c_create(uint64_t addr)
+{
+ IMXI2C *s = g_malloc0(sizeof(*s));
+ I2CAdapter *i2c = (I2CAdapter *)s;
+
+ s->addr = addr;
+
+ i2c->send = imx_i2c_send;
+ i2c->recv = imx_i2c_recv;
+
+ return i2c;
+}
diff --git a/qemu/tests/libqos/i2c-omap.c b/qemu/tests/libqos/i2c-omap.c
index 3d4d45d84..2028f2f14 100644
--- a/qemu/tests/libqos/i2c-omap.c
+++ b/qemu/tests/libqos/i2c-omap.c
@@ -6,12 +6,11 @@
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "libqos/i2c.h"
#include <glib.h>
-#include <string.h>
-#include "qemu/osdep.h"
#include "qemu/bswap.h"
#include "libqtest.h"
diff --git a/qemu/tests/libqos/i2c.c b/qemu/tests/libqos/i2c.c
index da7592f71..23bc2a3eb 100644
--- a/qemu/tests/libqos/i2c.c
+++ b/qemu/tests/libqos/i2c.c
@@ -6,6 +6,7 @@
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "libqos/i2c.h"
#include "libqtest.h"
diff --git a/qemu/tests/libqos/i2c.h b/qemu/tests/libqos/i2c.h
index 1ce9af405..6e648f922 100644
--- a/qemu/tests/libqos/i2c.h
+++ b/qemu/tests/libqos/i2c.h
@@ -9,7 +9,6 @@
#ifndef LIBQOS_I2C_H
#define LIBQOS_I2C_H
-#include <stdint.h>
typedef struct I2CAdapter I2CAdapter;
struct I2CAdapter {
@@ -27,4 +26,7 @@ void i2c_recv(I2CAdapter *i2c, uint8_t addr,
/* libi2c-omap.c */
I2CAdapter *omap_i2c_create(uint64_t addr);
+/* libi2c-imx.c */
+I2CAdapter *imx_i2c_create(uint64_t addr);
+
#endif
diff --git a/qemu/tests/libqos/libqos-pc.c b/qemu/tests/libqos/libqos-pc.c
index 140369937..72b5e3ba0 100644
--- a/qemu/tests/libqos/libqos-pc.c
+++ b/qemu/tests/libqos/libqos-pc.c
@@ -1,3 +1,4 @@
+#include "qemu/osdep.h"
#include "libqos/libqos-pc.h"
#include "libqos/malloc-pc.h"
diff --git a/qemu/tests/libqos/libqos.c b/qemu/tests/libqos/libqos.c
index fce625b18..79b0b29b4 100644
--- a/qemu/tests/libqos/libqos.c
+++ b/qemu/tests/libqos/libqos.c
@@ -1,9 +1,5 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include "qemu/osdep.h"
#include <glib.h>
-#include <unistd.h>
-#include <fcntl.h>
#include <sys/wait.h>
#include "libqtest.h"
@@ -147,6 +143,23 @@ void migrate(QOSState *from, QOSState *to, const char *uri)
set_context(to);
}
+bool have_qemu_img(void)
+{
+ char *rpath;
+ const char *path = getenv("QTEST_QEMU_IMG");
+ if (!path) {
+ return false;
+ }
+
+ rpath = realpath(path, NULL);
+ if (!rpath) {
+ return false;
+ } else {
+ free(rpath);
+ return true;
+ }
+}
+
void mkimg(const char *file, const char *fmt, unsigned size_mb)
{
gchar *cli;
@@ -155,13 +168,14 @@ void mkimg(const char *file, const char *fmt, unsigned size_mb)
GError *err = NULL;
char *qemu_img_path;
gchar *out, *out2;
- char *abs_path;
+ char *qemu_img_abs_path;
qemu_img_path = getenv("QTEST_QEMU_IMG");
- abs_path = realpath(qemu_img_path, NULL);
- assert(qemu_img_path);
+ g_assert(qemu_img_path);
+ qemu_img_abs_path = realpath(qemu_img_path, NULL);
+ g_assert(qemu_img_abs_path);
- cli = g_strdup_printf("%s create -f %s %s %uM", abs_path,
+ cli = g_strdup_printf("%s create -f %s %s %uM", qemu_img_abs_path,
fmt, file, size_mb);
ret = g_spawn_command_line_sync(cli, &out, &out2, &rc, &err);
if (err) {
@@ -183,7 +197,7 @@ void mkimg(const char *file, const char *fmt, unsigned size_mb)
g_free(out);
g_free(out2);
g_free(cli);
- free(abs_path);
+ free(qemu_img_abs_path);
}
void mkqcow2(const char *file, unsigned size_mb)
@@ -212,3 +226,29 @@ void prepare_blkdebug_script(const char *debug_fn, const char *event)
ret = fclose(debug_file);
g_assert(ret == 0);
}
+
+void generate_pattern(void *buffer, size_t len, size_t cycle_len)
+{
+ int i, j;
+ unsigned char *tx = (unsigned char *)buffer;
+ unsigned char p;
+ size_t *sx;
+
+ /* Write an indicative pattern that varies and is unique per-cycle */
+ p = rand() % 256;
+ for (i = 0; i < len; i++) {
+ tx[i] = p++ % 256;
+ if (i % cycle_len == 0) {
+ p = rand() % 256;
+ }
+ }
+
+ /* force uniqueness by writing an id per-cycle */
+ for (i = 0; i < len / cycle_len; i++) {
+ j = i * cycle_len;
+ if (j + sizeof(*sx) <= len) {
+ sx = (size_t *)&tx[j];
+ *sx = i;
+ }
+ }
+}
diff --git a/qemu/tests/libqos/libqos.h b/qemu/tests/libqos/libqos.h
index e1f14ea6f..ca14d2e9f 100644
--- a/qemu/tests/libqos/libqos.h
+++ b/qemu/tests/libqos/libqos.h
@@ -19,11 +19,13 @@ typedef struct QOSState {
QOSState *qtest_vboot(QOSOps *ops, const char *cmdline_fmt, va_list ap);
QOSState *qtest_boot(QOSOps *ops, const char *cmdline_fmt, ...);
void qtest_shutdown(QOSState *qs);
+bool have_qemu_img(void);
void mkimg(const char *file, const char *fmt, unsigned size_mb);
void mkqcow2(const char *file, unsigned size_mb);
void set_context(QOSState *s);
void migrate(QOSState *from, QOSState *to, const char *uri);
void prepare_blkdebug_script(const char *debug_fn, const char *event);
+void generate_pattern(void *buffer, size_t len, size_t cycle_len);
static inline uint64_t qmalloc(QOSState *q, size_t bytes)
{
diff --git a/qemu/tests/libqos/malloc-generic.c b/qemu/tests/libqos/malloc-generic.c
index d30a2f424..6000df2b8 100644
--- a/qemu/tests/libqos/malloc-generic.c
+++ b/qemu/tests/libqos/malloc-generic.c
@@ -7,6 +7,7 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqos/malloc-generic.h"
#include "libqos/malloc.h"
diff --git a/qemu/tests/libqos/malloc-pc.c b/qemu/tests/libqos/malloc-pc.c
index 6e253b687..eee706bd6 100644
--- a/qemu/tests/libqos/malloc-pc.c
+++ b/qemu/tests/libqos/malloc-pc.c
@@ -10,11 +10,11 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "libqos/malloc-pc.h"
#include "libqos/fw_cfg.h"
-#define NO_QEMU_PROTOS
-#include "hw/nvram/fw_cfg.h"
+#include "hw/nvram/fw_cfg_keys.h"
#include "qemu-common.h"
#include <glib.h>
diff --git a/qemu/tests/libqos/malloc.c b/qemu/tests/libqos/malloc.c
index 82b9df537..c0df52f33 100644
--- a/qemu/tests/libqos/malloc.c
+++ b/qemu/tests/libqos/malloc.c
@@ -10,10 +10,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "libqos/malloc.h"
#include "qemu-common.h"
-#include <stdio.h>
-#include <inttypes.h>
#include <glib.h>
typedef QTAILQ_HEAD(MemList, MemBlock) MemList;
@@ -270,6 +269,10 @@ uint64_t guest_alloc(QGuestAllocator *allocator, size_t size)
uint64_t rsize = size;
uint64_t naddr;
+ if (!size) {
+ return 0;
+ }
+
rsize += (allocator->page_size - 1);
rsize &= -allocator->page_size;
g_assert_cmpint((allocator->start + rsize), <=, allocator->end);
diff --git a/qemu/tests/libqos/malloc.h b/qemu/tests/libqos/malloc.h
index 0c6c9b7f3..ae9dac8f6 100644
--- a/qemu/tests/libqos/malloc.h
+++ b/qemu/tests/libqos/malloc.h
@@ -13,8 +13,6 @@
#ifndef LIBQOS_MALLOC_H
#define LIBQOS_MALLOC_H
-#include <stdint.h>
-#include <sys/types.h>
#include "qemu/queue.h"
typedef enum {
diff --git a/qemu/tests/libqos/pci-pc.c b/qemu/tests/libqos/pci-pc.c
index 6dba0db00..77f15e5a0 100644
--- a/qemu/tests/libqos/pci-pc.c
+++ b/qemu/tests/libqos/pci-pc.c
@@ -10,6 +10,7 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "libqtest.h"
#include "libqos/pci-pc.h"
@@ -183,7 +184,9 @@ static void *qpci_pc_iomap(QPCIBus *bus, QPCIDevice *dev, int barno, uint64_t *s
if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
uint16_t loc;
- g_assert((s->pci_iohole_alloc + size) <= s->pci_iohole_size);
+ g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
+ <= s->pci_iohole_size);
+ s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
loc = s->pci_iohole_start + s->pci_iohole_alloc;
s->pci_iohole_alloc += size;
@@ -193,7 +196,9 @@ static void *qpci_pc_iomap(QPCIBus *bus, QPCIDevice *dev, int barno, uint64_t *s
} else {
uint64_t loc;
- g_assert((s->pci_hole_alloc + size) <= s->pci_hole_size);
+ g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
+ <= s->pci_hole_size);
+ s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
loc = s->pci_hole_start + s->pci_hole_alloc;
s->pci_hole_alloc += size;
diff --git a/qemu/tests/libqos/pci.c b/qemu/tests/libqos/pci.c
index 4e630c250..0e104e14e 100644
--- a/qemu/tests/libqos/pci.c
+++ b/qemu/tests/libqos/pci.c
@@ -10,6 +10,7 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "libqos/pci.h"
#include "hw/pci/pci_regs.h"
@@ -34,11 +35,13 @@ void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
if (vendor_id != -1 &&
qpci_config_readw(dev, PCI_VENDOR_ID) != vendor_id) {
+ g_free(dev);
continue;
}
if (device_id != -1 &&
qpci_config_readw(dev, PCI_DEVICE_ID) != device_id) {
+ g_free(dev);
continue;
}
diff --git a/qemu/tests/libqos/pci.h b/qemu/tests/libqos/pci.h
index dfaee9ec3..c06add8db 100644
--- a/qemu/tests/libqos/pci.h
+++ b/qemu/tests/libqos/pci.h
@@ -13,7 +13,6 @@
#ifndef LIBQOS_PCI_H
#define LIBQOS_PCI_H
-#include <stdint.h>
#include "libqtest.h"
#define QPCI_DEVFN(dev, fn) (((dev) << 3) | (fn))
diff --git a/qemu/tests/libqos/usb.c b/qemu/tests/libqos/usb.c
index 41d89b848..87efb9078 100644
--- a/qemu/tests/libqos/usb.c
+++ b/qemu/tests/libqos/usb.c
@@ -11,10 +11,9 @@
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
#include "hw/usb/uhci-regs.h"
#include "libqos/usb.h"
diff --git a/qemu/tests/libqos/virtio-mmio.c b/qemu/tests/libqos/virtio-mmio.c
index b3e62e77d..a4382f366 100644
--- a/qemu/tests/libqos/virtio-mmio.c
+++ b/qemu/tests/libqos/virtio-mmio.c
@@ -7,8 +7,8 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdio.h>
#include "libqtest.h"
#include "libqos/virtio.h"
#include "libqos/virtio-mmio.h"
diff --git a/qemu/tests/libqos/virtio-pci.c b/qemu/tests/libqos/virtio-pci.c
index f9fb924b8..fde2ff0bc 100644
--- a/qemu/tests/libqos/virtio-pci.c
+++ b/qemu/tests/libqos/virtio-pci.c
@@ -7,8 +7,8 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdio.h>
#include "libqtest.h"
#include "libqos/virtio.h"
#include "libqos/virtio-pci.h"
diff --git a/qemu/tests/libqos/virtio.c b/qemu/tests/libqos/virtio.c
index 3205b88d9..613decea5 100644
--- a/qemu/tests/libqos/virtio.c
+++ b/qemu/tests/libqos/virtio.c
@@ -7,6 +7,7 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqtest.h"
#include "libqos/virtio.h"
diff --git a/qemu/tests/libqtest.c b/qemu/tests/libqtest.c
index e5188e032..b12a9e4ca 100644
--- a/qemu/tests/libqtest.c
+++ b/qemu/tests/libqtest.c
@@ -14,22 +14,14 @@
* See the COPYING file in the top-level directory.
*
*/
+#include "qemu/osdep.h"
#include "libqtest.h"
#include <glib.h>
-#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
-#include <inttypes.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#include "qemu/compiler.h"
-#include "qemu/osdep.h"
+
#include "qapi/qmp/json-parser.h"
#include "qapi/qmp/json-streamer.h"
#include "qapi/qmp/qjson.h"
@@ -46,9 +38,9 @@ struct QTestState
bool irq_level[MAX_IRQ];
GString *rx;
pid_t qemu_pid; /* our child QEMU process */
- struct sigaction sigact_old; /* restored on exit */
};
+static GHookList abrt_hooks;
static GList *qtest_instances;
static struct sigaction sigact_old;
@@ -110,12 +102,14 @@ static void kill_qemu(QTestState *s)
}
}
+static void kill_qemu_hook_func(void *s)
+{
+ kill_qemu(s);
+}
+
static void sigabrt_handler(int signo)
{
- GList *elem;
- for (elem = qtest_instances; elem; elem = elem->next) {
- kill_qemu(elem->data);
- }
+ g_hook_list_invoke(&abrt_hooks, FALSE);
}
static void setup_sigabrt_handler(void)
@@ -136,6 +130,23 @@ static void cleanup_sigabrt_handler(void)
sigaction(SIGABRT, &sigact_old, NULL);
}
+void qtest_add_abrt_handler(GHookFunc fn, const void *data)
+{
+ GHook *hook;
+
+ /* Only install SIGABRT handler once */
+ if (!abrt_hooks.is_setup) {
+ g_hook_list_init(&abrt_hooks, sizeof(GHook));
+ setup_sigabrt_handler();
+ }
+
+ hook = g_hook_alloc(&abrt_hooks);
+ hook->func = fn;
+ hook->data = (void *)data;
+
+ g_hook_prepend(&abrt_hooks, hook);
+}
+
QTestState *qtest_init(const char *extra_args)
{
QTestState *s;
@@ -156,12 +167,7 @@ QTestState *qtest_init(const char *extra_args)
sock = init_socket(socket_path);
qmpsock = init_socket(qmp_socket_path);
- /* Only install SIGABRT handler once */
- if (!qtest_instances) {
- setup_sigabrt_handler();
- }
-
- qtest_instances = g_list_prepend(qtest_instances, s);
+ qtest_add_abrt_handler(kill_qemu_hook_func, s);
s->qemu_pid = fork();
if (s->qemu_pid == 0) {
@@ -209,13 +215,14 @@ QTestState *qtest_init(const char *extra_args)
void qtest_quit(QTestState *s)
{
+ qtest_instances = g_list_remove(qtest_instances, s);
+ g_hook_destroy_link(&abrt_hooks, g_hook_find_data(&abrt_hooks, TRUE, s));
+
/* Uninstall SIGABRT handler on last instance */
- if (qtest_instances && !qtest_instances->next) {
+ if (!qtest_instances) {
cleanup_sigabrt_handler();
}
- qtest_instances = g_list_remove(qtest_instances, s);
-
kill_qemu(s);
close(s->fd);
close(s->qmp_fd);
@@ -341,7 +348,7 @@ typedef struct {
QDict *response;
} QMPResponseParser;
-static void qmp_response(JSONMessageParser *parser, QList *tokens)
+static void qmp_response(JSONMessageParser *parser, GQueue *tokens)
{
QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser);
QObject *obj;
@@ -357,7 +364,7 @@ static void qmp_response(JSONMessageParser *parser, QList *tokens)
qmp->response = (QDict *)obj;
}
-QDict *qtest_qmp_receive(QTestState *s)
+QDict *qmp_fd_receive(int fd)
{
QMPResponseParser qmp;
bool log = getenv("QTEST_LOG") != NULL;
@@ -368,7 +375,7 @@ QDict *qtest_qmp_receive(QTestState *s)
ssize_t len;
char c;
- len = read(s->qmp_fd, &c, 1);
+ len = read(fd, &c, 1);
if (len == -1 && errno == EINTR) {
continue;
}
@@ -388,12 +395,17 @@ QDict *qtest_qmp_receive(QTestState *s)
return qmp.response;
}
+QDict *qtest_qmp_receive(QTestState *s)
+{
+ return qmp_fd_receive(s->qmp_fd);
+}
+
/**
* Allow users to send a message without waiting for the reply,
* in the case that they choose to discard all replies up until
* a particular EVENT is received.
*/
-void qtest_async_qmpv(QTestState *s, const char *fmt, va_list ap)
+void qmp_fd_sendv(int fd, const char *fmt, va_list ap)
{
va_list ap_copy;
QObject *qobj;
@@ -417,13 +429,25 @@ void qtest_async_qmpv(QTestState *s, const char *fmt, va_list ap)
fprintf(stderr, "%s", str);
}
/* Send QMP request */
- socket_send(s->qmp_fd, str, size);
+ socket_send(fd, str, size);
QDECREF(qstr);
qobject_decref(qobj);
}
}
+void qtest_async_qmpv(QTestState *s, const char *fmt, va_list ap)
+{
+ qmp_fd_sendv(s->qmp_fd, fmt, ap);
+}
+
+QDict *qmp_fdv(int fd, const char *fmt, va_list ap)
+{
+ qmp_fd_sendv(fd, fmt, ap);
+
+ return qmp_fd_receive(fd);
+}
+
QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
{
qtest_async_qmpv(s, fmt, ap);
@@ -432,6 +456,26 @@ QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
return qtest_qmp_receive(s);
}
+QDict *qmp_fd(int fd, const char *fmt, ...)
+{
+ va_list ap;
+ QDict *response;
+
+ va_start(ap, fmt);
+ response = qmp_fdv(fd, fmt, ap);
+ va_end(ap);
+ return response;
+}
+
+void qmp_fd_send(int fd, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ qmp_fd_sendv(fd, fmt, ap);
+ va_end(ap);
+}
+
QDict *qtest_qmp(QTestState *s, const char *fmt, ...)
{
va_list ap;
@@ -484,6 +528,33 @@ void qtest_qmp_eventwait(QTestState *s, const char *event)
}
}
+char *qtest_hmpv(QTestState *s, const char *fmt, va_list ap)
+{
+ char *cmd;
+ QDict *resp;
+ char *ret;
+
+ cmd = g_strdup_vprintf(fmt, ap);
+ resp = qtest_qmp(s, "{'execute': 'human-monitor-command',"
+ " 'arguments': {'command-line': %s}}",
+ cmd);
+ ret = g_strdup(qdict_get_try_str(resp, "return"));
+ g_assert(ret);
+ QDECREF(resp);
+ g_free(cmd);
+ return ret;
+}
+
+char *qtest_hmp(QTestState *s, const char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = qtest_hmpv(s, fmt, ap);
+ va_end(ap);
+ return ret;
+}
const char *qtest_get_arch(void)
{
@@ -681,14 +752,15 @@ void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size)
g_strfreev(args);
}
-void qtest_add_func(const char *str, void (*fn))
+void qtest_add_func(const char *str, void (*fn)(void))
{
gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
g_test_add_func(path, fn);
g_free(path);
}
-void qtest_add_data_func(const char *str, const void *data, void (*fn))
+void qtest_add_data_func(const char *str, const void *data,
+ void (*fn)(const void *))
{
gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
g_test_add_data_func(path, data, fn);
@@ -775,6 +847,16 @@ void qmp_discard_response(const char *fmt, ...)
qtest_qmpv_discard_response(global_qtest, fmt, ap);
va_end(ap);
}
+char *hmp(const char *fmt, ...)
+{
+ va_list ap;
+ char *ret;
+
+ va_start(ap, fmt);
+ ret = qtest_hmpv(global_qtest, fmt, ap);
+ va_end(ap);
+ return ret;
+}
bool qtest_big_endian(void)
{
diff --git a/qemu/tests/libqtest.h b/qemu/tests/libqtest.h
index ec4203152..37f37adbf 100644
--- a/qemu/tests/libqtest.h
+++ b/qemu/tests/libqtest.h
@@ -17,13 +17,7 @@
#ifndef LIBQTEST_H
#define LIBQTEST_H
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdarg.h>
-#include <sys/types.h>
#include "qapi/qmp/qdict.h"
-#include "glib-compat.h"
typedef struct QTestState QTestState;
@@ -120,6 +114,29 @@ QDict *qtest_qmp_receive(QTestState *s);
void qtest_qmp_eventwait(QTestState *s, const char *event);
/**
+ * qtest_hmpv:
+ * @s: #QTestState instance to operate on.
+ * @fmt...: HMP command to send to QEMU
+ *
+ * Send HMP command to QEMU via QMP's human-monitor-command.
+ *
+ * Returns: the command's output. The caller should g_free() it.
+ */
+char *qtest_hmp(QTestState *s, const char *fmt, ...);
+
+/**
+ * qtest_hmpv:
+ * @s: #QTestState instance to operate on.
+ * @fmt: HMP command to send to QEMU
+ * @ap: HMP command arguments
+ *
+ * Send HMP command to QEMU via QMP's human-monitor-command.
+ *
+ * Returns: the command's output. The caller should g_free() it.
+ */
+char *qtest_hmpv(QTestState *s, const char *fmt, va_list ap);
+
+/**
* qtest_get_irq:
* @s: #QTestState instance to operate on.
* @num: Interrupt to observe.
@@ -393,7 +410,7 @@ const char *qtest_get_arch(void);
* The path is prefixed with the architecture under test, as
* returned by qtest_get_arch().
*/
-void qtest_add_func(const char *str, void (*fn));
+void qtest_add_func(const char *str, void (*fn)(void));
/**
* qtest_add_data_func:
@@ -405,7 +422,8 @@ void qtest_add_func(const char *str, void (*fn));
* The path is prefixed with the architecture under test, as
* returned by qtest_get_arch().
*/
-void qtest_add_data_func(const char *str, const void *data, void (*fn));
+void qtest_add_data_func(const char *str, const void *data,
+ void (*fn)(const void *));
/**
* qtest_add:
@@ -427,6 +445,8 @@ void qtest_add_data_func(const char *str, const void *data, void (*fn));
g_free(path); \
} while (0)
+void qtest_add_abrt_handler(GHookFunc fn, const void *data);
+
/**
* qtest_start:
* @args: other arguments to pass to QEMU
@@ -499,6 +519,16 @@ static inline void qmp_eventwait(const char *event)
}
/**
+ * hmp:
+ * @fmt...: HMP command to send to QEMU
+ *
+ * Send HMP command to QEMU via QMP's human-monitor-command.
+ *
+ * Returns: the command's output. The caller should g_free() it.
+ */
+char *hmp(const char *fmt, ...);
+
+/**
* get_irq:
* @num: Interrupt to observe.
*
@@ -818,4 +848,11 @@ static inline int64_t clock_set(int64_t val)
*/
bool qtest_big_endian(void);
+
+QDict *qmp_fd_receive(int fd);
+void qmp_fd_sendv(int fd, const char *fmt, va_list ap);
+void qmp_fd_send(int fd, const char *fmt, ...);
+QDict *qmp_fdv(int fd, const char *fmt, va_list ap);
+QDict *qmp_fd(int fd, const char *fmt, ...);
+
#endif
diff --git a/qemu/tests/m48t59-test.c b/qemu/tests/m48t59-test.c
index 71b4f2805..a751fd350 100644
--- a/qemu/tests/m48t59-test.c
+++ b/qemu/tests/m48t59-test.c
@@ -12,11 +12,8 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
#include "libqtest.h"
diff --git a/qemu/tests/ne2000-test.c b/qemu/tests/ne2000-test.c
index 61a678ad3..3727875f2 100644
--- a/qemu/tests/ne2000-test.c
+++ b/qemu/tests/ne2000-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void pci_nop(void)
diff --git a/qemu/tests/nvme-test.c b/qemu/tests/nvme-test.c
index ff38b5e48..ec06893ee 100644
--- a/qemu/tests/nvme-test.c
+++ b/qemu/tests/nvme-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void nop(void)
diff --git a/qemu/tests/pc-cpu-test.c b/qemu/tests/pc-cpu-test.c
index 3505c7c43..6b34ca588 100644
--- a/qemu/tests/pc-cpu-test.c
+++ b/qemu/tests/pc-cpu-test.c
@@ -7,12 +7,11 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "qemu-common.h"
#include "libqtest.h"
-#include "qemu/osdep.h"
#include "qapi/qmp/types.h"
struct PCTestData {
diff --git a/qemu/tests/pcnet-test.c b/qemu/tests/pcnet-test.c
index 84af4f327..2ddf4965c 100644
--- a/qemu/tests/pcnet-test.c
+++ b/qemu/tests/pcnet-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void pci_nop(void)
diff --git a/qemu/tests/pkix_asn1_tab.c b/qemu/tests/pkix_asn1_tab.c
new file mode 100644
index 000000000..903bc0251
--- /dev/null
+++ b/qemu/tests/pkix_asn1_tab.c
@@ -0,0 +1,1105 @@
+/*
+ * This file is taken from gnutls 1.6.3 under the GPLv2+
+ * and is under copyright of various GNUTLS contributors.
+ */
+
+#include "qemu/osdep.h"
+#include <libtasn1.h>
+
+const ASN1_ARRAY_TYPE pkix_asn1_tab[] = {
+ {"PKIX1", 536875024, 0},
+ {0, 1073741836, 0},
+ {"id-ce", 1879048204, 0},
+ {"joint-iso-ccitt", 1073741825, "2"},
+ {"ds", 1073741825, "5"},
+ {0, 1, "29"},
+ {"id-ce-authorityKeyIdentifier", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "35"},
+ {"AuthorityKeyIdentifier", 1610612741, 0},
+ {"keyIdentifier", 1610637314, "KeyIdentifier"},
+ {0, 4104, "0"},
+ {"authorityCertIssuer", 1610637314, "GeneralNames"},
+ {0, 4104, "1"},
+ {"authorityCertSerialNumber", 536895490, "CertificateSerialNumber"},
+ {0, 4104, "2"},
+ {"KeyIdentifier", 1073741831, 0},
+ {"id-ce-subjectKeyIdentifier", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "14"},
+ {"SubjectKeyIdentifier", 1073741826, "KeyIdentifier"},
+ {"id-ce-keyUsage", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "15"},
+ {"KeyUsage", 1610874886, 0},
+ {"digitalSignature", 1073741825, "0"},
+ {"nonRepudiation", 1073741825, "1"},
+ {"keyEncipherment", 1073741825, "2"},
+ {"dataEncipherment", 1073741825, "3"},
+ {"keyAgreement", 1073741825, "4"},
+ {"keyCertSign", 1073741825, "5"},
+ {"cRLSign", 1073741825, "6"},
+ {"encipherOnly", 1073741825, "7"},
+ {"decipherOnly", 1, "8"},
+ {"id-ce-privateKeyUsagePeriod", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "16"},
+ {"PrivateKeyUsagePeriod", 1610612741, 0},
+ {"notBefore", 1619025937, 0},
+ {0, 4104, "0"},
+ {"notAfter", 545284113, 0},
+ {0, 4104, "1"},
+ {"id-ce-certificatePolicies", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "32"},
+ {"CertificatePolicies", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "PolicyInformation"},
+ {"PolicyInformation", 1610612741, 0},
+ {"policyIdentifier", 1073741826, "CertPolicyId"},
+ {"policyQualifiers", 538984459, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "PolicyQualifierInfo"},
+ {"CertPolicyId", 1073741836, 0},
+ {"PolicyQualifierInfo", 1610612741, 0},
+ {"policyQualifierId", 1073741826, "PolicyQualifierId"},
+ {"qualifier", 541065229, 0},
+ {"policyQualifierId", 1, 0},
+ {"PolicyQualifierId", 1073741836, 0},
+ {"CPSuri", 1073741826, "IA5String"},
+ {"UserNotice", 1610612741, 0},
+ {"noticeRef", 1073758210, "NoticeReference"},
+ {"explicitText", 16386, "DisplayText"},
+ {"NoticeReference", 1610612741, 0},
+ {"organization", 1073741826, "DisplayText"},
+ {"noticeNumbers", 536870923, 0},
+ {0, 3, 0},
+ {"DisplayText", 1610612754, 0},
+ {"visibleString", 1612709890, "VisibleString"},
+ {"200", 524298, "1"},
+ {"bmpString", 1612709890, "BMPString"},
+ {"200", 524298, "1"},
+ {"utf8String", 538968066, "UTF8String"},
+ {"200", 524298, "1"},
+ {"id-ce-policyMappings", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "33"},
+ {"PolicyMappings", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 536870917, 0},
+ {"issuerDomainPolicy", 1073741826, "CertPolicyId"},
+ {"subjectDomainPolicy", 2, "CertPolicyId"},
+ {"DirectoryString", 1610612754, 0},
+ {"teletexString", 1612709890, "TeletexString"},
+ {"MAX", 524298, "1"},
+ {"printableString", 1612709890, "PrintableString"},
+ {"MAX", 524298, "1"},
+ {"universalString", 1612709890, "UniversalString"},
+ {"MAX", 524298, "1"},
+ {"utf8String", 1612709890, "UTF8String"},
+ {"MAX", 524298, "1"},
+ {"bmpString", 1612709890, "BMPString"},
+ {"MAX", 524298, "1"},
+ {"ia5String", 538968066, "IA5String"},
+ {"MAX", 524298, "1"},
+ {"id-ce-subjectAltName", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "17"},
+ {"SubjectAltName", 1073741826, "GeneralNames"},
+ {"GeneralNames", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "GeneralName"},
+ {"GeneralName", 1610612754, 0},
+ {"otherName", 1610620930, "AnotherName"},
+ {0, 4104, "0"},
+ {"rfc822Name", 1610620930, "IA5String"},
+ {0, 4104, "1"},
+ {"dNSName", 1610620930, "IA5String"},
+ {0, 4104, "2"},
+ {"x400Address", 1610620930, "ORAddress"},
+ {0, 4104, "3"},
+ {"directoryName", 1610620930, "RDNSequence"},
+ {0, 2056, "4"},
+ {"ediPartyName", 1610620930, "EDIPartyName"},
+ {0, 4104, "5"},
+ {"uniformResourceIdentifier", 1610620930, "IA5String"},
+ {0, 4104, "6"},
+ {"iPAddress", 1610620935, 0},
+ {0, 4104, "7"},
+ {"registeredID", 536879116, 0},
+ {0, 4104, "8"},
+ {"AnotherName", 1610612741, 0},
+ {"type-id", 1073741836, 0},
+ {"value", 541073421, 0},
+ {0, 1073743880, "0"},
+ {"type-id", 1, 0},
+ {"EDIPartyName", 1610612741, 0},
+ {"nameAssigner", 1610637314, "DirectoryString"},
+ {0, 4104, "0"},
+ {"partyName", 536879106, "DirectoryString"},
+ {0, 4104, "1"},
+ {"id-ce-issuerAltName", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "18"},
+ {"IssuerAltName", 1073741826, "GeneralNames"},
+ {"id-ce-subjectDirectoryAttributes", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "9"},
+ {"SubjectDirectoryAttributes", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "Attribute"},
+ {"id-ce-basicConstraints", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "19"},
+ {"BasicConstraints", 1610612741, 0},
+ {"cA", 1610645508, 0},
+ {0, 131081, 0},
+ {"pathLenConstraint", 537411587, 0},
+ {"0", 10, "MAX"},
+ {"id-ce-nameConstraints", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "30"},
+ {"NameConstraints", 1610612741, 0},
+ {"permittedSubtrees", 1610637314, "GeneralSubtrees"},
+ {0, 4104, "0"},
+ {"excludedSubtrees", 536895490, "GeneralSubtrees"},
+ {0, 4104, "1"},
+ {"GeneralSubtrees", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "GeneralSubtree"},
+ {"GeneralSubtree", 1610612741, 0},
+ {"base", 1073741826, "GeneralName"},
+ {"minimum", 1610653698, "BaseDistance"},
+ {0, 1073741833, "0"},
+ {0, 4104, "0"},
+ {"maximum", 536895490, "BaseDistance"},
+ {0, 4104, "1"},
+ {"BaseDistance", 1611137027, 0},
+ {"0", 10, "MAX"},
+ {"id-ce-policyConstraints", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "36"},
+ {"PolicyConstraints", 1610612741, 0},
+ {"requireExplicitPolicy", 1610637314, "SkipCerts"},
+ {0, 4104, "0"},
+ {"inhibitPolicyMapping", 536895490, "SkipCerts"},
+ {0, 4104, "1"},
+ {"SkipCerts", 1611137027, 0},
+ {"0", 10, "MAX"},
+ {"id-ce-cRLDistributionPoints", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "31"},
+ {"CRLDistributionPoints", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "DistributionPoint"},
+ {"DistributionPoint", 1610612741, 0},
+ {"distributionPoint", 1610637314, "DistributionPointName"},
+ {0, 2056, "0"},
+ {"reasons", 1610637314, "ReasonFlags"},
+ {0, 4104, "1"},
+ {"cRLIssuer", 536895490, "GeneralNames"},
+ {0, 4104, "2"},
+ {"DistributionPointName", 1610612754, 0},
+ {"fullName", 1610620930, "GeneralNames"},
+ {0, 4104, "0"},
+ {"nameRelativeToCRLIssuer", 536879106, "RelativeDistinguishedName"},
+ {0, 4104, "1"},
+ {"ReasonFlags", 1610874886, 0},
+ {"unused", 1073741825, "0"},
+ {"keyCompromise", 1073741825, "1"},
+ {"cACompromise", 1073741825, "2"},
+ {"affiliationChanged", 1073741825, "3"},
+ {"superseded", 1073741825, "4"},
+ {"cessationOfOperation", 1073741825, "5"},
+ {"certificateHold", 1073741825, "6"},
+ {"privilegeWithdrawn", 1073741825, "7"},
+ {"aACompromise", 1, "8"},
+ {"id-ce-extKeyUsage", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "37"},
+ {"ExtKeyUsageSyntax", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "KeyPurposeId"},
+ {"KeyPurposeId", 1073741836, 0},
+ {"id-kp-serverAuth", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "1"},
+ {"id-kp-clientAuth", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "2"},
+ {"id-kp-codeSigning", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "3"},
+ {"id-kp-emailProtection", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "4"},
+ {"id-kp-ipsecEndSystem", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "5"},
+ {"id-kp-ipsecTunnel", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "6"},
+ {"id-kp-ipsecUser", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "7"},
+ {"id-kp-timeStamping", 1879048204, 0},
+ {0, 1073741825, "id-kp"},
+ {0, 1, "8"},
+ {"id-pe-authorityInfoAccess", 1879048204, 0},
+ {0, 1073741825, "id-pe"},
+ {0, 1, "1"},
+ {"AuthorityInfoAccessSyntax", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "AccessDescription"},
+ {"AccessDescription", 1610612741, 0},
+ {"accessMethod", 1073741836, 0},
+ {"accessLocation", 2, "GeneralName"},
+ {"id-ce-cRLNumber", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "20"},
+ {"CRLNumber", 1611137027, 0},
+ {"0", 10, "MAX"},
+ {"id-ce-issuingDistributionPoint", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "28"},
+ {"IssuingDistributionPoint", 1610612741, 0},
+ {"distributionPoint", 1610637314, "DistributionPointName"},
+ {0, 4104, "0"},
+ {"onlyContainsUserCerts", 1610653700, 0},
+ {0, 1073872905, 0},
+ {0, 4104, "1"},
+ {"onlyContainsCACerts", 1610653700, 0},
+ {0, 1073872905, 0},
+ {0, 4104, "2"},
+ {"onlySomeReasons", 1610637314, "ReasonFlags"},
+ {0, 4104, "3"},
+ {"indirectCRL", 536911876, 0},
+ {0, 1073872905, 0},
+ {0, 4104, "4"},
+ {"id-ce-deltaCRLIndicator", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "27"},
+ {"BaseCRLNumber", 1073741826, "CRLNumber"},
+ {"id-ce-cRLReasons", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "21"},
+ {"CRLReason", 1610874901, 0},
+ {"unspecified", 1073741825, "0"},
+ {"keyCompromise", 1073741825, "1"},
+ {"cACompromise", 1073741825, "2"},
+ {"affiliationChanged", 1073741825, "3"},
+ {"superseded", 1073741825, "4"},
+ {"cessationOfOperation", 1073741825, "5"},
+ {"certificateHold", 1073741825, "6"},
+ {"removeFromCRL", 1, "8"},
+ {"id-ce-certificateIssuer", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "29"},
+ {"CertificateIssuer", 1073741826, "GeneralNames"},
+ {"id-ce-holdInstructionCode", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "23"},
+ {"HoldInstructionCode", 1073741836, 0},
+ {"holdInstruction", 1879048204, 0},
+ {"joint-iso-itu-t", 1073741825, "2"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"x9cm", 1073741825, "10040"},
+ {0, 1, "2"},
+ {"id-holdinstruction-none", 1879048204, 0},
+ {0, 1073741825, "holdInstruction"},
+ {0, 1, "1"},
+ {"id-holdinstruction-callissuer", 1879048204, 0},
+ {0, 1073741825, "holdInstruction"},
+ {0, 1, "2"},
+ {"id-holdinstruction-reject", 1879048204, 0},
+ {0, 1073741825, "holdInstruction"},
+ {0, 1, "3"},
+ {"id-ce-invalidityDate", 1879048204, 0},
+ {0, 1073741825, "id-ce"},
+ {0, 1, "24"},
+ {"InvalidityDate", 1082130449, 0},
+ {"VisibleString", 1610620935, 0},
+ {0, 4360, "26"},
+ {"NumericString", 1610620935, 0},
+ {0, 4360, "18"},
+ {"IA5String", 1610620935, 0},
+ {0, 4360, "22"},
+ {"TeletexString", 1610620935, 0},
+ {0, 4360, "20"},
+ {"PrintableString", 1610620935, 0},
+ {0, 4360, "19"},
+ {"UniversalString", 1610620935, 0},
+ {0, 4360, "28"},
+ {"BMPString", 1610620935, 0},
+ {0, 4360, "30"},
+ {"UTF8String", 1610620935, 0},
+ {0, 4360, "12"},
+ {"id-pkix", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"identified-organization", 1073741825, "3"},
+ {"dod", 1073741825, "6"},
+ {"internet", 1073741825, "1"},
+ {"security", 1073741825, "5"},
+ {"mechanisms", 1073741825, "5"},
+ {"pkix", 1, "7"},
+ {"id-pe", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "1"},
+ {"id-qt", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "2"},
+ {"id-kp", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "3"},
+ {"id-ad", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "48"},
+ {"id-qt-cps", 1879048204, 0},
+ {0, 1073741825, "id-qt"},
+ {0, 1, "1"},
+ {"id-qt-unotice", 1879048204, 0},
+ {0, 1073741825, "id-qt"},
+ {0, 1, "2"},
+ {"id-ad-ocsp", 1879048204, 0},
+ {0, 1073741825, "id-ad"},
+ {0, 1, "1"},
+ {"id-ad-caIssuers", 1879048204, 0},
+ {0, 1073741825, "id-ad"},
+ {0, 1, "2"},
+ {"Attribute", 1610612741, 0},
+ {"type", 1073741826, "AttributeType"},
+ {"values", 536870927, 0},
+ {0, 2, "AttributeValue"},
+ {"AttributeType", 1073741836, 0},
+ {"AttributeValue", 1614807053, 0},
+ {"type", 1, 0},
+ {"AttributeTypeAndValue", 1610612741, 0},
+ {"type", 1073741826, "AttributeType"},
+ {"value", 2, "AttributeValue"},
+ {"id-at", 1879048204, 0},
+ {"joint-iso-ccitt", 1073741825, "2"},
+ {"ds", 1073741825, "5"},
+ {0, 1, "4"},
+ {"id-at-initials", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "43"},
+ {"X520initials", 1073741826, "DirectoryString"},
+ {"id-at-generationQualifier", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "44"},
+ {"X520generationQualifier", 1073741826, "DirectoryString"},
+ {"id-at-surname", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "4"},
+ {"X520surName", 1073741826, "DirectoryString"},
+ {"id-at-givenName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "42"},
+ {"X520givenName", 1073741826, "DirectoryString"},
+ {"id-at-name", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "41"},
+ {"X520name", 1073741826, "DirectoryString"},
+ {"id-at-commonName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "3"},
+ {"X520CommonName", 1073741826, "DirectoryString"},
+ {"id-at-localityName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "7"},
+ {"X520LocalityName", 1073741826, "DirectoryString"},
+ {"id-at-stateOrProvinceName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "8"},
+ {"X520StateOrProvinceName", 1073741826, "DirectoryString"},
+ {"id-at-organizationName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "10"},
+ {"X520OrganizationName", 1073741826, "DirectoryString"},
+ {"id-at-organizationalUnitName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "11"},
+ {"X520OrganizationalUnitName", 1073741826, "DirectoryString"},
+ {"id-at-title", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "12"},
+ {"X520Title", 1073741826, "DirectoryString"},
+ {"id-at-description", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "13"},
+ {"X520Description", 1073741826, "DirectoryString"},
+ {"id-at-dnQualifier", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "46"},
+ {"X520dnQualifier", 1073741826, "PrintableString"},
+ {"id-at-countryName", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "6"},
+ {"X520countryName", 1612709890, "PrintableString"},
+ {0, 1048586, "2"},
+ {"id-at-serialNumber", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "5"},
+ {"X520serialNumber", 1073741826, "PrintableString"},
+ {"id-at-telephoneNumber", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "20"},
+ {"X520telephoneNumber", 1073741826, "PrintableString"},
+ {"id-at-facsimileTelephoneNumber", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "23"},
+ {"X520facsimileTelephoneNumber", 1073741826, "PrintableString"},
+ {"id-at-pseudonym", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "65"},
+ {"X520pseudonym", 1073741826, "DirectoryString"},
+ {"id-at-name", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "41"},
+ {"X520name", 1073741826, "DirectoryString"},
+ {"id-at-streetAddress", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "9"},
+ {"X520streetAddress", 1073741826, "DirectoryString"},
+ {"id-at-postalAddress", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-at"},
+ {0, 1, "16"},
+ {"X520postalAddress", 1073741826, "PostalAddress"},
+ {"PostalAddress", 1610612747, 0},
+ {0, 2, "DirectoryString"},
+ {"pkcs", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"rsadsi", 1073741825, "113549"},
+ {"pkcs", 1, "1"},
+ {"pkcs-9", 1879048204, 0},
+ {0, 1073741825, "pkcs"},
+ {0, 1, "9"},
+ {"emailAddress", 1880096780, "AttributeType"},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "1"},
+ {"Pkcs9email", 1612709890, "IA5String"},
+ {"ub-emailaddress-length", 524298, "1"},
+ {"Name", 1610612754, 0},
+ {"rdnSequence", 2, "RDNSequence"},
+ {"RDNSequence", 1610612747, 0},
+ {0, 2, "RelativeDistinguishedName"},
+ {"DistinguishedName", 1073741826, "RDNSequence"},
+ {"RelativeDistinguishedName", 1612709903, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "AttributeTypeAndValue"},
+ {"Certificate", 1610612741, 0},
+ {"tbsCertificate", 1073741826, "TBSCertificate"},
+ {"signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"signature", 6, 0},
+ {"TBSCertificate", 1610612741, 0},
+ {"version", 1610653698, "Version"},
+ {0, 1073741833, "v1"},
+ {0, 2056, "0"},
+ {"serialNumber", 1073741826, "CertificateSerialNumber"},
+ {"signature", 1073741826, "AlgorithmIdentifier"},
+ {"issuer", 1073741826, "Name"},
+ {"validity", 1073741826, "Validity"},
+ {"subject", 1073741826, "Name"},
+ {"subjectPublicKeyInfo", 1073741826, "SubjectPublicKeyInfo"},
+ {"issuerUniqueID", 1610637314, "UniqueIdentifier"},
+ {0, 4104, "1"},
+ {"subjectUniqueID", 1610637314, "UniqueIdentifier"},
+ {0, 4104, "2"},
+ {"extensions", 536895490, "Extensions"},
+ {0, 2056, "3"},
+ {"Version", 1610874883, 0},
+ {"v1", 1073741825, "0"},
+ {"v2", 1073741825, "1"},
+ {"v3", 1, "2"},
+ {"CertificateSerialNumber", 1073741827, 0},
+ {"Validity", 1610612741, 0},
+ {"notBefore", 1073741826, "Time"},
+ {"notAfter", 2, "Time"},
+ {"Time", 1610612754, 0},
+ {"utcTime", 1090519057, 0},
+ {"generalTime", 8388625, 0},
+ {"UniqueIdentifier", 1073741830, 0},
+ {"SubjectPublicKeyInfo", 1610612741, 0},
+ {"algorithm", 1073741826, "AlgorithmIdentifier"},
+ {"subjectPublicKey", 6, 0},
+ {"Extensions", 1612709899, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "Extension"},
+ {"Extension", 1610612741, 0},
+ {"extnID", 1073741836, 0},
+ {"critical", 1610645508, 0},
+ {0, 131081, 0},
+ {"extnValue", 7, 0},
+ {"CertificateList", 1610612741, 0},
+ {"tbsCertList", 1073741826, "TBSCertList"},
+ {"signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"signature", 6, 0},
+ {"TBSCertList", 1610612741, 0},
+ {"version", 1073758210, "Version"},
+ {"signature", 1073741826, "AlgorithmIdentifier"},
+ {"issuer", 1073741826, "Name"},
+ {"thisUpdate", 1073741826, "Time"},
+ {"nextUpdate", 1073758210, "Time"},
+ {"revokedCertificates", 1610629131, 0},
+ {0, 536870917, 0},
+ {"userCertificate", 1073741826, "CertificateSerialNumber"},
+ {"revocationDate", 1073741826, "Time"},
+ {"crlEntryExtensions", 16386, "Extensions"},
+ {"crlExtensions", 536895490, "Extensions"},
+ {0, 2056, "0"},
+ {"AlgorithmIdentifier", 1610612741, 0},
+ {"algorithm", 1073741836, 0},
+ {"parameters", 541081613, 0},
+ {"algorithm", 1, 0},
+ {"pkcs-1", 1879048204, 0},
+ {0, 1073741825, "pkcs"},
+ {0, 1, "1"},
+ {"rsaEncryption", 1879048204, 0},
+ {0, 1073741825, "pkcs-1"},
+ {0, 1, "1"},
+ {"md2WithRSAEncryption", 1879048204, 0},
+ {0, 1073741825, "pkcs-1"},
+ {0, 1, "2"},
+ {"md5WithRSAEncryption", 1879048204, 0},
+ {0, 1073741825, "pkcs-1"},
+ {0, 1, "4"},
+ {"sha1WithRSAEncryption", 1879048204, 0},
+ {0, 1073741825, "pkcs-1"},
+ {0, 1, "5"},
+ {"id-dsa-with-sha1", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"x9-57", 1073741825, "10040"},
+ {"x9algorithm", 1073741825, "4"},
+ {0, 1, "3"},
+ {"Dss-Sig-Value", 1610612741, 0},
+ {"r", 1073741827, 0},
+ {"s", 3, 0},
+ {"dhpublicnumber", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"ansi-x942", 1073741825, "10046"},
+ {"number-type", 1073741825, "2"},
+ {0, 1, "1"},
+ {"DomainParameters", 1610612741, 0},
+ {"p", 1073741827, 0},
+ {"g", 1073741827, 0},
+ {"q", 1073741827, 0},
+ {"j", 1073758211, 0},
+ {"validationParms", 16386, "ValidationParms"},
+ {"ValidationParms", 1610612741, 0},
+ {"seed", 1073741830, 0},
+ {"pgenCounter", 3, 0},
+ {"id-dsa", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"x9-57", 1073741825, "10040"},
+ {"x9algorithm", 1073741825, "4"},
+ {0, 1, "1"},
+ {"Dss-Parms", 1610612741, 0},
+ {"p", 1073741827, 0},
+ {"q", 1073741827, 0},
+ {"g", 3, 0},
+ {"ORAddress", 1610612741, 0},
+ {"built-in-standard-attributes", 1073741826, "BuiltInStandardAttributes"},
+ {"built-in-domain-defined-attributes", 1073758210,
+ "BuiltInDomainDefinedAttributes"},
+ {"extension-attributes", 16386, "ExtensionAttributes"},
+ {"BuiltInStandardAttributes", 1610612741, 0},
+ {"country-name", 1073758210, "CountryName"},
+ {"administration-domain-name", 1073758210, "AdministrationDomainName"},
+ {"network-address", 1610637314, "NetworkAddress"},
+ {0, 2056, "0"},
+ {"terminal-identifier", 1610637314, "TerminalIdentifier"},
+ {0, 2056, "1"},
+ {"private-domain-name", 1610637314, "PrivateDomainName"},
+ {0, 2056, "2"},
+ {"organization-name", 1610637314, "OrganizationName"},
+ {0, 2056, "3"},
+ {"numeric-user-identifier", 1610637314, "NumericUserIdentifier"},
+ {0, 2056, "4"},
+ {"personal-name", 1610637314, "PersonalName"},
+ {0, 2056, "5"},
+ {"organizational-unit-names", 536895490, "OrganizationalUnitNames"},
+ {0, 2056, "6"},
+ {"CountryName", 1610620946, 0},
+ {0, 1073746952, "1"},
+ {"x121-dcc-code", 1612709890, "NumericString"},
+ {0, 1048586, "ub-country-name-numeric-length"},
+ {"iso-3166-alpha2-code", 538968066, "PrintableString"},
+ {0, 1048586, "ub-country-name-alpha-length"},
+ {"AdministrationDomainName", 1610620946, 0},
+ {0, 1073744904, "2"},
+ {"numeric", 1612709890, "NumericString"},
+ {"ub-domain-name-length", 524298, "0"},
+ {"printable", 538968066, "PrintableString"},
+ {"ub-domain-name-length", 524298, "0"},
+ {"NetworkAddress", 1073741826, "X121Address"},
+ {"X121Address", 1612709890, "NumericString"},
+ {"ub-x121-address-length", 524298, "1"},
+ {"TerminalIdentifier", 1612709890, "PrintableString"},
+ {"ub-terminal-id-length", 524298, "1"},
+ {"PrivateDomainName", 1610612754, 0},
+ {"numeric", 1612709890, "NumericString"},
+ {"ub-domain-name-length", 524298, "1"},
+ {"printable", 538968066, "PrintableString"},
+ {"ub-domain-name-length", 524298, "1"},
+ {"OrganizationName", 1612709890, "PrintableString"},
+ {"ub-organization-name-length", 524298, "1"},
+ {"NumericUserIdentifier", 1612709890, "NumericString"},
+ {"ub-numeric-user-id-length", 524298, "1"},
+ {"PersonalName", 1610612750, 0},
+ {"surname", 1814044674, "PrintableString"},
+ {0, 1073745928, "0"},
+ {"ub-surname-length", 524298, "1"},
+ {"given-name", 1814061058, "PrintableString"},
+ {0, 1073745928, "1"},
+ {"ub-given-name-length", 524298, "1"},
+ {"initials", 1814061058, "PrintableString"},
+ {0, 1073745928, "2"},
+ {"ub-initials-length", 524298, "1"},
+ {"generation-qualifier", 740319234, "PrintableString"},
+ {0, 1073745928, "3"},
+ {"ub-generation-qualifier-length", 524298, "1"},
+ {"OrganizationalUnitNames", 1612709899, 0},
+ {"ub-organizational-units", 1074266122, "1"},
+ {0, 2, "OrganizationalUnitName"},
+ {"OrganizationalUnitName", 1612709890, "PrintableString"},
+ {"ub-organizational-unit-name-length", 524298, "1"},
+ {"BuiltInDomainDefinedAttributes", 1612709899, 0},
+ {"ub-domain-defined-attributes", 1074266122, "1"},
+ {0, 2, "BuiltInDomainDefinedAttribute"},
+ {"BuiltInDomainDefinedAttribute", 1610612741, 0},
+ {"type", 1612709890, "PrintableString"},
+ {"ub-domain-defined-attribute-type-length", 524298, "1"},
+ {"value", 538968066, "PrintableString"},
+ {"ub-domain-defined-attribute-value-length", 524298, "1"},
+ {"ExtensionAttributes", 1612709903, 0},
+ {"ub-extension-attributes", 1074266122, "1"},
+ {0, 2, "ExtensionAttribute"},
+ {"ExtensionAttribute", 1610612741, 0},
+ {"extension-attribute-type", 1611145219, 0},
+ {0, 1073743880, "0"},
+ {"0", 10, "ub-extension-attributes"},
+ {"extension-attribute-value", 541073421, 0},
+ {0, 1073743880, "1"},
+ {"extension-attribute-type", 1, 0},
+ {"common-name", 1342177283, "1"},
+ {"CommonName", 1612709890, "PrintableString"},
+ {"ub-common-name-length", 524298, "1"},
+ {"teletex-common-name", 1342177283, "2"},
+ {"TeletexCommonName", 1612709890, "TeletexString"},
+ {"ub-common-name-length", 524298, "1"},
+ {"teletex-organization-name", 1342177283, "3"},
+ {"TeletexOrganizationName", 1612709890, "TeletexString"},
+ {"ub-organization-name-length", 524298, "1"},
+ {"teletex-personal-name", 1342177283, "4"},
+ {"TeletexPersonalName", 1610612750, 0},
+ {"surname", 1814044674, "TeletexString"},
+ {0, 1073743880, "0"},
+ {"ub-surname-length", 524298, "1"},
+ {"given-name", 1814061058, "TeletexString"},
+ {0, 1073743880, "1"},
+ {"ub-given-name-length", 524298, "1"},
+ {"initials", 1814061058, "TeletexString"},
+ {0, 1073743880, "2"},
+ {"ub-initials-length", 524298, "1"},
+ {"generation-qualifier", 740319234, "TeletexString"},
+ {0, 1073743880, "3"},
+ {"ub-generation-qualifier-length", 524298, "1"},
+ {"teletex-organizational-unit-names", 1342177283, "5"},
+ {"TeletexOrganizationalUnitNames", 1612709899, 0},
+ {"ub-organizational-units", 1074266122, "1"},
+ {0, 2, "TeletexOrganizationalUnitName"},
+ {"TeletexOrganizationalUnitName", 1612709890, "TeletexString"},
+ {"ub-organizational-unit-name-length", 524298, "1"},
+ {"pds-name", 1342177283, "7"},
+ {"PDSName", 1612709890, "PrintableString"},
+ {"ub-pds-name-length", 524298, "1"},
+ {"physical-delivery-country-name", 1342177283, "8"},
+ {"PhysicalDeliveryCountryName", 1610612754, 0},
+ {"x121-dcc-code", 1612709890, "NumericString"},
+ {0, 1048586, "ub-country-name-numeric-length"},
+ {"iso-3166-alpha2-code", 538968066, "PrintableString"},
+ {0, 1048586, "ub-country-name-alpha-length"},
+ {"postal-code", 1342177283, "9"},
+ {"PostalCode", 1610612754, 0},
+ {"numeric-code", 1612709890, "NumericString"},
+ {"ub-postal-code-length", 524298, "1"},
+ {"printable-code", 538968066, "PrintableString"},
+ {"ub-postal-code-length", 524298, "1"},
+ {"physical-delivery-office-name", 1342177283, "10"},
+ {"PhysicalDeliveryOfficeName", 1073741826, "PDSParameter"},
+ {"physical-delivery-office-number", 1342177283, "11"},
+ {"PhysicalDeliveryOfficeNumber", 1073741826, "PDSParameter"},
+ {"extension-OR-address-components", 1342177283, "12"},
+ {"ExtensionORAddressComponents", 1073741826, "PDSParameter"},
+ {"physical-delivery-personal-name", 1342177283, "13"},
+ {"PhysicalDeliveryPersonalName", 1073741826, "PDSParameter"},
+ {"physical-delivery-organization-name", 1342177283, "14"},
+ {"PhysicalDeliveryOrganizationName", 1073741826, "PDSParameter"},
+ {"extension-physical-delivery-address-components", 1342177283, "15"},
+ {"ExtensionPhysicalDeliveryAddressComponents", 1073741826, "PDSParameter"},
+ {"unformatted-postal-address", 1342177283, "16"},
+ {"UnformattedPostalAddress", 1610612750, 0},
+ {"printable-address", 1814052875, 0},
+ {"ub-pds-physical-address-lines", 1074266122, "1"},
+ {0, 538968066, "PrintableString"},
+ {"ub-pds-parameter-length", 524298, "1"},
+ {"teletex-string", 740311042, "TeletexString"},
+ {"ub-unformatted-address-length", 524298, "1"},
+ {"street-address", 1342177283, "17"},
+ {"StreetAddress", 1073741826, "PDSParameter"},
+ {"post-office-box-address", 1342177283, "18"},
+ {"PostOfficeBoxAddress", 1073741826, "PDSParameter"},
+ {"poste-restante-address", 1342177283, "19"},
+ {"PosteRestanteAddress", 1073741826, "PDSParameter"},
+ {"unique-postal-name", 1342177283, "20"},
+ {"UniquePostalName", 1073741826, "PDSParameter"},
+ {"local-postal-attributes", 1342177283, "21"},
+ {"LocalPostalAttributes", 1073741826, "PDSParameter"},
+ {"PDSParameter", 1610612750, 0},
+ {"printable-string", 1814052866, "PrintableString"},
+ {"ub-pds-parameter-length", 524298, "1"},
+ {"teletex-string", 740311042, "TeletexString"},
+ {"ub-pds-parameter-length", 524298, "1"},
+ {"extended-network-address", 1342177283, "22"},
+ {"ExtendedNetworkAddress", 1610612754, 0},
+ {"e163-4-address", 1610612741, 0},
+ {"number", 1612718082, "NumericString"},
+ {0, 1073743880, "0"},
+ {"ub-e163-4-number-length", 524298, "1"},
+ {"sub-address", 538992642, "NumericString"},
+ {0, 1073743880, "1"},
+ {"ub-e163-4-sub-address-length", 524298, "1"},
+ {"psap-address", 536879106, "PresentationAddress"},
+ {0, 2056, "0"},
+ {"PresentationAddress", 1610612741, 0},
+ {"pSelector", 1610637319, 0},
+ {0, 2056, "0"},
+ {"sSelector", 1610637319, 0},
+ {0, 2056, "1"},
+ {"tSelector", 1610637319, 0},
+ {0, 2056, "2"},
+ {"nAddresses", 538976271, 0},
+ {0, 1073743880, "3"},
+ {"MAX", 1074266122, "1"},
+ {0, 7, 0},
+ {"terminal-type", 1342177283, "23"},
+ {"TerminalType", 1610874883, 0},
+ {"telex", 1073741825, "3"},
+ {"teletex", 1073741825, "4"},
+ {"g3-facsimile", 1073741825, "5"},
+ {"g4-facsimile", 1073741825, "6"},
+ {"ia5-terminal", 1073741825, "7"},
+ {"videotex", 1, "8"},
+ {"teletex-domain-defined-attributes", 1342177283, "6"},
+ {"TeletexDomainDefinedAttributes", 1612709899, 0},
+ {"ub-domain-defined-attributes", 1074266122, "1"},
+ {0, 2, "TeletexDomainDefinedAttribute"},
+ {"TeletexDomainDefinedAttribute", 1610612741, 0},
+ {"type", 1612709890, "TeletexString"},
+ {"ub-domain-defined-attribute-type-length", 524298, "1"},
+ {"value", 538968066, "TeletexString"},
+ {"ub-domain-defined-attribute-value-length", 524298, "1"},
+ {"ub-name", 1342177283, "32768"},
+ {"ub-common-name", 1342177283, "64"},
+ {"ub-locality-name", 1342177283, "128"},
+ {"ub-state-name", 1342177283, "128"},
+ {"ub-organization-name", 1342177283, "64"},
+ {"ub-organizational-unit-name", 1342177283, "64"},
+ {"ub-title", 1342177283, "64"},
+ {"ub-match", 1342177283, "128"},
+ {"ub-emailaddress-length", 1342177283, "128"},
+ {"ub-common-name-length", 1342177283, "64"},
+ {"ub-country-name-alpha-length", 1342177283, "2"},
+ {"ub-country-name-numeric-length", 1342177283, "3"},
+ {"ub-domain-defined-attributes", 1342177283, "4"},
+ {"ub-domain-defined-attribute-type-length", 1342177283, "8"},
+ {"ub-domain-defined-attribute-value-length", 1342177283, "128"},
+ {"ub-domain-name-length", 1342177283, "16"},
+ {"ub-extension-attributes", 1342177283, "256"},
+ {"ub-e163-4-number-length", 1342177283, "15"},
+ {"ub-e163-4-sub-address-length", 1342177283, "40"},
+ {"ub-generation-qualifier-length", 1342177283, "3"},
+ {"ub-given-name-length", 1342177283, "16"},
+ {"ub-initials-length", 1342177283, "5"},
+ {"ub-integer-options", 1342177283, "256"},
+ {"ub-numeric-user-id-length", 1342177283, "32"},
+ {"ub-organization-name-length", 1342177283, "64"},
+ {"ub-organizational-unit-name-length", 1342177283, "32"},
+ {"ub-organizational-units", 1342177283, "4"},
+ {"ub-pds-name-length", 1342177283, "16"},
+ {"ub-pds-parameter-length", 1342177283, "30"},
+ {"ub-pds-physical-address-lines", 1342177283, "6"},
+ {"ub-postal-code-length", 1342177283, "16"},
+ {"ub-surname-length", 1342177283, "40"},
+ {"ub-terminal-id-length", 1342177283, "24"},
+ {"ub-unformatted-address-length", 1342177283, "180"},
+ {"ub-x121-address-length", 1342177283, "16"},
+ {"pkcs-7-ContentInfo", 1610612741, 0},
+ {"contentType", 1073741826, "pkcs-7-ContentType"},
+ {"content", 541073421, 0},
+ {0, 1073743880, "0"},
+ {"contentType", 1, 0},
+ {"pkcs-7-DigestInfo", 1610612741, 0},
+ {"digestAlgorithm", 1073741826, "pkcs-7-DigestAlgorithmIdentifier"},
+ {"digest", 2, "pkcs-7-Digest"},
+ {"pkcs-7-Digest", 1073741831, 0},
+ {"pkcs-7-ContentType", 1073741836, 0},
+ {"pkcs-7-SignedData", 1610612741, 0},
+ {"version", 1073741826, "pkcs-7-CMSVersion"},
+ {"digestAlgorithms", 1073741826, "pkcs-7-DigestAlgorithmIdentifiers"},
+ {"encapContentInfo", 1073741826, "pkcs-7-EncapsulatedContentInfo"},
+ {"certificates", 1610637314, "pkcs-7-CertificateSet"},
+ {0, 4104, "0"},
+ {"crls", 1610637314, "pkcs-7-CertificateRevocationLists"},
+ {0, 4104, "1"},
+ {"signerInfos", 2, "pkcs-7-SignerInfos"},
+ {"pkcs-7-CMSVersion", 1610874883, 0},
+ {"v0", 1073741825, "0"},
+ {"v1", 1073741825, "1"},
+ {"v2", 1073741825, "2"},
+ {"v3", 1073741825, "3"},
+ {"v4", 1, "4"},
+ {"pkcs-7-DigestAlgorithmIdentifiers", 1610612751, 0},
+ {0, 2, "pkcs-7-DigestAlgorithmIdentifier"},
+ {"pkcs-7-DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"},
+ {"pkcs-7-EncapsulatedContentInfo", 1610612741, 0},
+ {"eContentType", 1073741826, "pkcs-7-ContentType"},
+ {"eContent", 536895495, 0},
+ {0, 2056, "0"},
+ {"pkcs-7-CertificateRevocationLists", 1610612751, 0},
+ {0, 13, 0},
+ {"pkcs-7-CertificateChoices", 1610612754, 0},
+ {"certificate", 13, 0},
+ {"pkcs-7-CertificateSet", 1610612751, 0},
+ {0, 2, "pkcs-7-CertificateChoices"},
+ {"pkcs-7-SignerInfos", 1610612751, 0},
+ {0, 13, 0},
+ {"pkcs-10-CertificationRequestInfo", 1610612741, 0},
+ {"version", 1610874883, 0},
+ {"v1", 1, "0"},
+ {"subject", 1073741826, "Name"},
+ {"subjectPKInfo", 1073741826, "SubjectPublicKeyInfo"},
+ {"attributes", 536879106, "Attributes"},
+ {0, 4104, "0"},
+ {"Attributes", 1610612751, 0},
+ {0, 2, "Attribute"},
+ {"pkcs-10-CertificationRequest", 1610612741, 0},
+ {"certificationRequestInfo", 1073741826, "pkcs-10-CertificationRequestInfo"},
+ {"signatureAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"signature", 6, 0},
+ {"pkcs-9-ub-challengePassword", 1342177283, "255"},
+ {"pkcs-9-certTypes", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "22"},
+ {"pkcs-9-crlTypes", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "23"},
+ {"pkcs-9-at-challengePassword", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "7"},
+ {"pkcs-9-challengePassword", 1610612754, 0},
+ {"printableString", 1612709890, "PrintableString"},
+ {"pkcs-9-ub-challengePassword", 524298, "1"},
+ {"utf8String", 538968066, "UTF8String"},
+ {"pkcs-9-ub-challengePassword", 524298, "1"},
+ {"pkcs-9-at-localKeyId", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "21"},
+ {"pkcs-9-localKeyId", 1073741831, 0},
+ {"pkcs-9-at-friendlyName", 1879048204, 0},
+ {0, 1073741825, "pkcs-9"},
+ {0, 1, "20"},
+ {"pkcs-9-friendlyName", 1612709890, "BMPString"},
+ {"255", 524298, "1"},
+ {"pkcs-8-PrivateKeyInfo", 1610612741, 0},
+ {"version", 1073741826, "pkcs-8-Version"},
+ {"privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"privateKey", 1073741826, "pkcs-8-PrivateKey"},
+ {"attributes", 536895490, "Attributes"},
+ {0, 4104, "0"},
+ {"pkcs-8-Version", 1610874883, 0},
+ {"v1", 1, "0"},
+ {"pkcs-8-PrivateKey", 1073741831, 0},
+ {"pkcs-8-Attributes", 1610612751, 0},
+ {0, 2, "Attribute"},
+ {"pkcs-8-EncryptedPrivateKeyInfo", 1610612741, 0},
+ {"encryptionAlgorithm", 1073741826, "AlgorithmIdentifier"},
+ {"encryptedData", 2, "pkcs-8-EncryptedData"},
+ {"pkcs-8-EncryptedData", 1073741831, 0},
+ {"pkcs-5", 1879048204, 0},
+ {0, 1073741825, "pkcs"},
+ {0, 1, "5"},
+ {"pkcs-5-encryptionAlgorithm", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"rsadsi", 1073741825, "113549"},
+ {0, 1, "3"},
+ {"pkcs-5-des-EDE3-CBC", 1879048204, 0},
+ {0, 1073741825, "pkcs-5-encryptionAlgorithm"},
+ {0, 1, "7"},
+ {"pkcs-5-des-EDE3-CBC-params", 1612709895, 0},
+ {0, 1048586, "8"},
+ {"pkcs-5-id-PBES2", 1879048204, 0},
+ {0, 1073741825, "pkcs-5"},
+ {0, 1, "13"},
+ {"pkcs-5-PBES2-params", 1610612741, 0},
+ {"keyDerivationFunc", 1073741826, "AlgorithmIdentifier"},
+ {"encryptionScheme", 2, "AlgorithmIdentifier"},
+ {"pkcs-5-id-PBKDF2", 1879048204, 0},
+ {0, 1073741825, "pkcs-5"},
+ {0, 1, "12"},
+ {"pkcs-5-PBKDF2-params", 1610612741, 0},
+ {"salt", 1610612754, 0},
+ {"specified", 1073741831, 0},
+ {"otherSource", 2, "AlgorithmIdentifier"},
+ {"iterationCount", 1611137027, 0},
+ {"1", 10, "MAX"},
+ {"keyLength", 1611153411, 0},
+ {"1", 10, "MAX"},
+ {"prf", 16386, "AlgorithmIdentifier"},
+ {"pkcs-12", 1879048204, 0},
+ {0, 1073741825, "pkcs"},
+ {0, 1, "12"},
+ {"pkcs-12-PFX", 1610612741, 0},
+ {"version", 1610874883, 0},
+ {"v3", 1, "3"},
+ {"authSafe", 1073741826, "pkcs-7-ContentInfo"},
+ {"macData", 16386, "pkcs-12-MacData"},
+ {"pkcs-12-PbeParams", 1610612741, 0},
+ {"salt", 1073741831, 0},
+ {"iterations", 3, 0},
+ {"pkcs-12-MacData", 1610612741, 0},
+ {"mac", 1073741826, "pkcs-7-DigestInfo"},
+ {"macSalt", 1073741831, 0},
+ {"iterations", 536903683, 0},
+ {0, 9, "1"},
+ {"pkcs-12-AuthenticatedSafe", 1610612747, 0},
+ {0, 2, "pkcs-7-ContentInfo"},
+ {"pkcs-12-SafeContents", 1610612747, 0},
+ {0, 2, "pkcs-12-SafeBag"},
+ {"pkcs-12-SafeBag", 1610612741, 0},
+ {"bagId", 1073741836, 0},
+ {"bagValue", 1614815245, 0},
+ {0, 1073743880, "0"},
+ {"badId", 1, 0},
+ {"bagAttributes", 536887311, 0},
+ {0, 2, "pkcs-12-PKCS12Attribute"},
+ {"pkcs-12-bagtypes", 1879048204, 0},
+ {0, 1073741825, "pkcs-12"},
+ {0, 1073741825, "10"},
+ {0, 1, "1"},
+ {"pkcs-12-keyBag", 1879048204, 0},
+ {0, 1073741825, "pkcs-12-bagtypes"},
+ {0, 1, "1"},
+ {"pkcs-12-pkcs8ShroudedKeyBag", 1879048204, 0},
+ {0, 1073741825, "pkcs-12-bagtypes"},
+ {0, 1, "2"},
+ {"pkcs-12-certBag", 1879048204, 0},
+ {0, 1073741825, "pkcs-12-bagtypes"},
+ {0, 1, "3"},
+ {"pkcs-12-crlBag", 1879048204, 0},
+ {0, 1073741825, "pkcs-12-bagtypes"},
+ {0, 1, "4"},
+ {"pkcs-12-KeyBag", 1073741826, "pkcs-8-PrivateKeyInfo"},
+ {"pkcs-12-PKCS8ShroudedKeyBag", 1073741826, "pkcs-8-EncryptedPrivateKeyInfo"},
+ {"pkcs-12-CertBag", 1610612741, 0},
+ {"certId", 1073741836, 0},
+ {"certValue", 541073421, 0},
+ {0, 1073743880, "0"},
+ {"certId", 1, 0},
+ {"pkcs-12-CRLBag", 1610612741, 0},
+ {"crlId", 1073741836, 0},
+ {"crlValue", 541073421, 0},
+ {0, 1073743880, "0"},
+ {"crlId", 1, 0},
+ {"pkcs-12-PKCS12Attribute", 1073741826, "Attribute"},
+ {"pkcs-7-data", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"rsadsi", 1073741825, "113549"},
+ {"pkcs", 1073741825, "1"},
+ {"pkcs7", 1073741825, "7"},
+ {0, 1, "1"},
+ {"pkcs-7-encryptedData", 1879048204, 0},
+ {"iso", 1073741825, "1"},
+ {"member-body", 1073741825, "2"},
+ {"us", 1073741825, "840"},
+ {"rsadsi", 1073741825, "113549"},
+ {"pkcs", 1073741825, "1"},
+ {"pkcs7", 1073741825, "7"},
+ {0, 1, "6"},
+ {"pkcs-7-Data", 1073741831, 0},
+ {"pkcs-7-EncryptedData", 1610612741, 0},
+ {"version", 1073741826, "pkcs-7-CMSVersion"},
+ {"encryptedContentInfo", 1073741826, "pkcs-7-EncryptedContentInfo"},
+ {"unprotectedAttrs", 536895490, "pkcs-7-UnprotectedAttributes"},
+ {0, 4104, "1"},
+ {"pkcs-7-EncryptedContentInfo", 1610612741, 0},
+ {"contentType", 1073741826, "pkcs-7-ContentType"},
+ {"contentEncryptionAlgorithm", 1073741826,
+ "pkcs-7-ContentEncryptionAlgorithmIdentifier"},
+ {"encryptedContent", 536895490, "pkcs-7-EncryptedContent"},
+ {0, 4104, "0"},
+ {"pkcs-7-ContentEncryptionAlgorithmIdentifier", 1073741826,
+ "AlgorithmIdentifier"},
+ {"pkcs-7-EncryptedContent", 1073741831, 0},
+ {"pkcs-7-UnprotectedAttributes", 1612709903, 0},
+ {"MAX", 1074266122, "1"},
+ {0, 2, "Attribute"},
+ {"id-at-ldap-DC", 1880096780, "AttributeType"},
+ {0, 1073741825, "0"},
+ {0, 1073741825, "9"},
+ {0, 1073741825, "2342"},
+ {0, 1073741825, "19200300"},
+ {0, 1073741825, "100"},
+ {0, 1073741825, "1"},
+ {0, 1, "25"},
+ {"ldap-DC", 1073741826, "IA5String"},
+ {"id-at-ldap-UID", 1880096780, "AttributeType"},
+ {0, 1073741825, "0"},
+ {0, 1073741825, "9"},
+ {0, 1073741825, "2342"},
+ {0, 1073741825, "19200300"},
+ {0, 1073741825, "100"},
+ {0, 1073741825, "1"},
+ {0, 1, "1"},
+ {"ldap-UID", 1073741826, "DirectoryString"},
+ {"id-pda", 1879048204, 0},
+ {0, 1073741825, "id-pkix"},
+ {0, 1, "9"},
+ {"id-pda-dateOfBirth", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "1"},
+ {"DateOfBirth", 1082130449, 0},
+ {"id-pda-placeOfBirth", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "2"},
+ {"PlaceOfBirth", 1073741826, "DirectoryString"},
+ {"id-pda-gender", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "3"},
+ {"Gender", 1612709890, "PrintableString"},
+ {0, 1048586, "1"},
+ {"id-pda-countryOfCitizenship", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "4"},
+ {"CountryOfCitizenship", 1612709890, "PrintableString"},
+ {0, 1048586, "2"},
+ {"id-pda-countryOfResidence", 1880096780, "AttributeType"},
+ {0, 1073741825, "id-pda"},
+ {0, 1, "5"},
+ {"CountryOfResidence", 538968066, "PrintableString"},
+ {0, 1048586, "2"},
+ {0, 0, 0}
+};
diff --git a/qemu/tests/pvpanic-test.c b/qemu/tests/pvpanic-test.c
index a7ad6b306..d435833f7 100644
--- a/qemu/tests/pvpanic-test.c
+++ b/qemu/tests/pvpanic-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
static void test_panic(void)
{
diff --git a/qemu/tests/pxe-test.c b/qemu/tests/pxe-test.c
new file mode 100644
index 000000000..875e4c4a2
--- /dev/null
+++ b/qemu/tests/pxe-test.c
@@ -0,0 +1,68 @@
+/*
+ * PXE test cases.
+ *
+ * Copyright (c) 2016 Red Hat Inc.
+ *
+ * Authors:
+ * Michael S. Tsirkin <mst@redhat.com>,
+ * Victor Kaplansky <victork@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+#include <glib/gstdio.h>
+#include "qemu-common.h"
+#include "libqtest.h"
+#include "boot-sector.h"
+
+#define NETNAME "net0"
+
+static const char *disk = "tests/pxe-test-disk.raw";
+
+static void test_pxe_one(const char *params)
+{
+ char *args;
+
+ args = g_strdup_printf("-machine accel=tcg "
+ "-netdev user,id=" NETNAME ",tftp=./,bootfile=%s "
+ "%s ",
+ disk, params);
+
+ qtest_start(args);
+ boot_sector_test();
+ qtest_quit(global_qtest);
+ g_free(args);
+}
+
+static void test_pxe_e1000(void)
+{
+ test_pxe_one("-device e1000,netdev=" NETNAME);
+}
+
+static void test_pxe_virtio_pci(void)
+{
+ test_pxe_one("-device virtio-net-pci,netdev=" NETNAME);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ const char *arch = qtest_get_arch();
+
+ ret = boot_sector_init(disk);
+ if(ret)
+ return ret;
+
+ g_test_init(&argc, &argv, NULL);
+
+ if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+ qtest_add_func("pxe/e1000", test_pxe_e1000);
+ qtest_add_func("pxe/virtio", test_pxe_virtio_pci);
+ }
+ ret = g_test_run();
+ boot_sector_cleanup(disk);
+ return ret;
+}
diff --git a/qemu/tests/q35-test.c b/qemu/tests/q35-test.c
index 812abe548..a105f1078 100644
--- a/qemu/tests/q35-test.c
+++ b/qemu/tests/q35-test.c
@@ -9,12 +9,11 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
#include "libqos/pci.h"
#include "libqos/pci-pc.h"
-#include "qemu/osdep.h"
#include "hw/pci-host/q35.h"
static void smram_set_bit(QPCIDevice *pcidev, uint8_t mask, bool enabled)
diff --git a/qemu/tests/qapi-schema/alternate-any.err b/qemu/tests/qapi-schema/alternate-any.err
new file mode 100644
index 000000000..aaa015473
--- /dev/null
+++ b/qemu/tests/qapi-schema/alternate-any.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-any.json:2: Alternate 'Alt' member 'one' cannot use type 'any'
diff --git a/qemu/tests/qapi-schema/data-array-empty.exit b/qemu/tests/qapi-schema/alternate-any.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/data-array-empty.exit
+++ b/qemu/tests/qapi-schema/alternate-any.exit
diff --git a/qemu/tests/qapi-schema/alternate-any.json b/qemu/tests/qapi-schema/alternate-any.json
new file mode 100644
index 000000000..e47a73a11
--- /dev/null
+++ b/qemu/tests/qapi-schema/alternate-any.json
@@ -0,0 +1,4 @@
+# we do not allow the 'any' type as an alternate branch
+{ 'alternate': 'Alt',
+ 'data': { 'one': 'any',
+ 'two': 'int' } }
diff --git a/qemu/tests/qapi-schema/alternate-good.err b/qemu/tests/qapi-schema/alternate-any.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/alternate-good.err
+++ b/qemu/tests/qapi-schema/alternate-any.out
diff --git a/qemu/tests/qapi-schema/alternate-clash.err b/qemu/tests/qapi-schema/alternate-clash.err
index 51bea3e27..604d8495e 100644
--- a/qemu/tests/qapi-schema/alternate-clash.err
+++ b/qemu/tests/qapi-schema/alternate-clash.err
@@ -1 +1 @@
-tests/qapi-schema/alternate-clash.json:2: Alternate 'Alt1' member 'ONE' clashes with 'one'
+tests/qapi-schema/alternate-clash.json:7: 'a_b' (branch of Alt1) collides with 'a-b' (branch of Alt1)
diff --git a/qemu/tests/qapi-schema/alternate-clash.json b/qemu/tests/qapi-schema/alternate-clash.json
index 39479353b..6d73bc527 100644
--- a/qemu/tests/qapi-schema/alternate-clash.json
+++ b/qemu/tests/qapi-schema/alternate-clash.json
@@ -1,3 +1,8 @@
-# we detect C enum collisions in an alternate
+# Alternate branch name collision
+# Reject an alternate that would result in a collision in generated C
+# names (this would try to generate two enum values 'ALT1_KIND_A_B').
+# TODO: In the future, if alternates are simplified to not generate
+# the implicit Alt1Kind enum, we would still have a collision with the
+# resulting C union trying to have two members named 'a_b'.
{ 'alternate': 'Alt1',
- 'data': { 'one': 'str', 'ONE': 'int' } }
+ 'data': { 'a-b': 'str', 'a_b': 'int' } }
diff --git a/qemu/tests/qapi-schema/alternate-empty.err b/qemu/tests/qapi-schema/alternate-empty.err
new file mode 100644
index 000000000..bb06c5bfe
--- /dev/null
+++ b/qemu/tests/qapi-schema/alternate-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/alternate-empty.json:2: Alternate 'Alt' should have at least two branches in 'data'
diff --git a/qemu/tests/qapi-schema/data-array-unknown.exit b/qemu/tests/qapi-schema/alternate-empty.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/data-array-unknown.exit
+++ b/qemu/tests/qapi-schema/alternate-empty.exit
diff --git a/qemu/tests/qapi-schema/alternate-empty.json b/qemu/tests/qapi-schema/alternate-empty.json
new file mode 100644
index 000000000..fff15baf1
--- /dev/null
+++ b/qemu/tests/qapi-schema/alternate-empty.json
@@ -0,0 +1,2 @@
+# alternates must list at least two types to be useful
+{ 'alternate': 'Alt', 'data': { 'i': 'int' } }
diff --git a/qemu/tests/qapi-schema/data-array-empty.out b/qemu/tests/qapi-schema/alternate-empty.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/data-array-empty.out
+++ b/qemu/tests/qapi-schema/alternate-empty.out
diff --git a/qemu/tests/qapi-schema/alternate-good.exit b/qemu/tests/qapi-schema/alternate-good.exit
deleted file mode 100644
index 573541ac9..000000000
--- a/qemu/tests/qapi-schema/alternate-good.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/qemu/tests/qapi-schema/alternate-good.json b/qemu/tests/qapi-schema/alternate-good.json
deleted file mode 100644
index 33717704c..000000000
--- a/qemu/tests/qapi-schema/alternate-good.json
+++ /dev/null
@@ -1,9 +0,0 @@
-# Working example of alternate
-{ 'struct': 'Data',
- 'data': { '*number': 'int', '*name': 'str' } }
-{ 'enum': 'Enum',
- 'data': [ 'hello', 'world' ] }
-{ 'alternate': 'Alt',
- 'data': { 'value': 'int',
- 'string': 'Enum',
- 'struct': 'Data' } }
diff --git a/qemu/tests/qapi-schema/alternate-good.out b/qemu/tests/qapi-schema/alternate-good.out
deleted file mode 100644
index 99848eefb..000000000
--- a/qemu/tests/qapi-schema/alternate-good.out
+++ /dev/null
@@ -1,6 +0,0 @@
-[OrderedDict([('struct', 'Data'), ('data', OrderedDict([('*number', 'int'), ('*name', 'str')]))]),
- OrderedDict([('enum', 'Enum'), ('data', ['hello', 'world'])]),
- OrderedDict([('alternate', 'Alt'), ('data', OrderedDict([('value', 'int'), ('string', 'Enum'), ('struct', 'Data')]))])]
-[{'enum_name': 'Enum', 'enum_values': ['hello', 'world']},
- {'enum_name': 'AltKind', 'enum_values': None}]
-[OrderedDict([('struct', 'Data'), ('data', OrderedDict([('*number', 'int'), ('*name', 'str')]))])]
diff --git a/qemu/tests/qapi-schema/alternate-nested.json b/qemu/tests/qapi-schema/alternate-nested.json
index c4233b9f3..8e2218649 100644
--- a/qemu/tests/qapi-schema/alternate-nested.json
+++ b/qemu/tests/qapi-schema/alternate-nested.json
@@ -2,4 +2,4 @@
{ 'alternate': 'Alt1',
'data': { 'name': 'str', 'value': 'int' } }
{ 'alternate': 'Alt2',
- 'data': { 'nested': 'Alt1' } }
+ 'data': { 'nested': 'Alt1', 'b': 'bool' } }
diff --git a/qemu/tests/qapi-schema/alternate-unknown.json b/qemu/tests/qapi-schema/alternate-unknown.json
index ad5c10302..08c80dced 100644
--- a/qemu/tests/qapi-schema/alternate-unknown.json
+++ b/qemu/tests/qapi-schema/alternate-unknown.json
@@ -1,3 +1,3 @@
# we reject an alternate with unknown type in branch
{ 'alternate': 'Alt',
- 'data': { 'unknown': 'MissingType' } }
+ 'data': { 'unknown': 'MissingType', 'i': 'int' } }
diff --git a/qemu/tests/qapi-schema/args-alternate.err b/qemu/tests/qapi-schema/args-alternate.err
new file mode 100644
index 000000000..3086eae56
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-alternate.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-alternate.json:3: 'data' for command 'oops' cannot use alternate type 'Alt'
diff --git a/qemu/tests/qapi-schema/data-int.exit b/qemu/tests/qapi-schema/args-alternate.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/data-int.exit
+++ b/qemu/tests/qapi-schema/args-alternate.exit
diff --git a/qemu/tests/qapi-schema/args-alternate.json b/qemu/tests/qapi-schema/args-alternate.json
new file mode 100644
index 000000000..69e94d481
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-alternate.json
@@ -0,0 +1,3 @@
+# we do not allow alternate arguments
+{ 'alternate': 'Alt', 'data': { 'case1': 'int', 'case2': 'str' } }
+{ 'command': 'oops', 'data': 'Alt' }
diff --git a/qemu/tests/qapi-schema/data-array-unknown.out b/qemu/tests/qapi-schema/args-alternate.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/data-array-unknown.out
+++ b/qemu/tests/qapi-schema/args-alternate.out
diff --git a/qemu/tests/qapi-schema/args-any.err b/qemu/tests/qapi-schema/args-any.err
new file mode 100644
index 000000000..bf9b5e073
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-any.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-any.json:2: 'data' for command 'oops' cannot use built-in type 'any'
diff --git a/qemu/tests/qapi-schema/data-member-array-bad.exit b/qemu/tests/qapi-schema/args-any.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/data-member-array-bad.exit
+++ b/qemu/tests/qapi-schema/args-any.exit
diff --git a/qemu/tests/qapi-schema/args-any.json b/qemu/tests/qapi-schema/args-any.json
new file mode 100644
index 000000000..58fe5e470
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-any.json
@@ -0,0 +1,2 @@
+# we do not allow an 'any' argument
+{ 'command': 'oops', 'data': 'any' }
diff --git a/qemu/tests/qapi-schema/data-int.out b/qemu/tests/qapi-schema/args-any.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/data-int.out
+++ b/qemu/tests/qapi-schema/args-any.out
diff --git a/qemu/tests/qapi-schema/data-array-empty.err b/qemu/tests/qapi-schema/args-array-empty.err
index f713f1489..cb7ed33b3 100644
--- a/qemu/tests/qapi-schema/data-array-empty.err
+++ b/qemu/tests/qapi-schema/args-array-empty.err
@@ -1 +1 @@
-tests/qapi-schema/data-array-empty.json:2: Member 'empty' of 'data' for command 'oops': array type must contain single type name
+tests/qapi-schema/args-array-empty.json:2: Member 'empty' of 'data' for command 'oops': array type must contain single type name
diff --git a/qemu/tests/qapi-schema/data-member-unknown.exit b/qemu/tests/qapi-schema/args-array-empty.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/data-member-unknown.exit
+++ b/qemu/tests/qapi-schema/args-array-empty.exit
diff --git a/qemu/tests/qapi-schema/data-array-empty.json b/qemu/tests/qapi-schema/args-array-empty.json
index 652dcfb24..652dcfb24 100644
--- a/qemu/tests/qapi-schema/data-array-empty.json
+++ b/qemu/tests/qapi-schema/args-array-empty.json
diff --git a/qemu/tests/qapi-schema/data-member-array-bad.out b/qemu/tests/qapi-schema/args-array-empty.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/data-member-array-bad.out
+++ b/qemu/tests/qapi-schema/args-array-empty.out
diff --git a/qemu/tests/qapi-schema/args-array-unknown.err b/qemu/tests/qapi-schema/args-array-unknown.err
new file mode 100644
index 000000000..cd7a0f98d
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-array-unknown.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-array-unknown.json:2: Member 'array' of 'data' for command 'oops' uses unknown type 'NoSuchType'
diff --git a/qemu/tests/qapi-schema/data-unknown.exit b/qemu/tests/qapi-schema/args-array-unknown.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/data-unknown.exit
+++ b/qemu/tests/qapi-schema/args-array-unknown.exit
diff --git a/qemu/tests/qapi-schema/data-array-unknown.json b/qemu/tests/qapi-schema/args-array-unknown.json
index 6f3e88331..6f3e88331 100644
--- a/qemu/tests/qapi-schema/data-array-unknown.json
+++ b/qemu/tests/qapi-schema/args-array-unknown.json
diff --git a/qemu/tests/qapi-schema/data-member-array.err b/qemu/tests/qapi-schema/args-array-unknown.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/data-member-array.err
+++ b/qemu/tests/qapi-schema/args-array-unknown.out
diff --git a/qemu/tests/qapi-schema/args-int.err b/qemu/tests/qapi-schema/args-int.err
new file mode 100644
index 000000000..dc1d2504f
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-int.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-int.json:2: 'data' for command 'oops' cannot use built-in type 'int'
diff --git a/qemu/tests/qapi-schema/enum-max-member.exit b/qemu/tests/qapi-schema/args-int.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/enum-max-member.exit
+++ b/qemu/tests/qapi-schema/args-int.exit
diff --git a/qemu/tests/qapi-schema/data-int.json b/qemu/tests/qapi-schema/args-int.json
index a334d92e8..a334d92e8 100644
--- a/qemu/tests/qapi-schema/data-int.json
+++ b/qemu/tests/qapi-schema/args-int.json
diff --git a/qemu/tests/qapi-schema/data-member-unknown.out b/qemu/tests/qapi-schema/args-int.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/data-member-unknown.out
+++ b/qemu/tests/qapi-schema/args-int.out
diff --git a/qemu/tests/qapi-schema/args-invalid.err b/qemu/tests/qapi-schema/args-invalid.err
new file mode 100644
index 000000000..fe1e94975
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-invalid.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-invalid.json:1: 'data' for command 'foo' should be a dictionary or type name
diff --git a/qemu/tests/qapi-schema/enum-union-clash.exit b/qemu/tests/qapi-schema/args-invalid.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/enum-union-clash.exit
+++ b/qemu/tests/qapi-schema/args-invalid.exit
diff --git a/qemu/tests/qapi-schema/args-invalid.json b/qemu/tests/qapi-schema/args-invalid.json
new file mode 100644
index 000000000..db0981341
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-invalid.json
@@ -0,0 +1,2 @@
+{ 'command': 'foo',
+ 'data': false }
diff --git a/qemu/tests/qapi-schema/data-unknown.out b/qemu/tests/qapi-schema/args-invalid.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/data-unknown.out
+++ b/qemu/tests/qapi-schema/args-invalid.out
diff --git a/qemu/tests/qapi-schema/data-member-array-bad.err b/qemu/tests/qapi-schema/args-member-array-bad.err
index 2c072d598..881b4d954 100644
--- a/qemu/tests/qapi-schema/data-member-array-bad.err
+++ b/qemu/tests/qapi-schema/args-member-array-bad.err
@@ -1 +1 @@
-tests/qapi-schema/data-member-array-bad.json:2: Member 'member' of 'data' for command 'oops': array type must contain single type name
+tests/qapi-schema/args-member-array-bad.json:2: Member 'member' of 'data' for command 'oops': array type must contain single type name
diff --git a/qemu/tests/qapi-schema/event-max.exit b/qemu/tests/qapi-schema/args-member-array-bad.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/event-max.exit
+++ b/qemu/tests/qapi-schema/args-member-array-bad.exit
diff --git a/qemu/tests/qapi-schema/data-member-array-bad.json b/qemu/tests/qapi-schema/args-member-array-bad.json
index b2ff144ec..b2ff144ec 100644
--- a/qemu/tests/qapi-schema/data-member-array-bad.json
+++ b/qemu/tests/qapi-schema/args-member-array-bad.json
diff --git a/qemu/tests/qapi-schema/enum-empty.err b/qemu/tests/qapi-schema/args-member-array-bad.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/enum-empty.err
+++ b/qemu/tests/qapi-schema/args-member-array-bad.out
diff --git a/qemu/tests/qapi-schema/args-member-case.err b/qemu/tests/qapi-schema/args-member-case.err
new file mode 100644
index 000000000..19c442660
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-member-case.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-member-case.json:2: 'Arg' (parameter of no-way-this-will-get-whitelisted) should not use uppercase
diff --git a/qemu/tests/qapi-schema/flat-union-base-star.exit b/qemu/tests/qapi-schema/args-member-case.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/flat-union-base-star.exit
+++ b/qemu/tests/qapi-schema/args-member-case.exit
diff --git a/qemu/tests/qapi-schema/args-member-case.json b/qemu/tests/qapi-schema/args-member-case.json
new file mode 100644
index 000000000..93439bee8
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-member-case.json
@@ -0,0 +1,2 @@
+# Member names should be 'lower-case' unless the struct/command is whitelisted
+{ 'command': 'no-way-this-will-get-whitelisted', 'data': { 'Arg': 'int' } }
diff --git a/qemu/tests/qapi-schema/enum-max-member.out b/qemu/tests/qapi-schema/args-member-case.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/enum-max-member.out
+++ b/qemu/tests/qapi-schema/args-member-case.out
diff --git a/qemu/tests/qapi-schema/args-member-unknown.err b/qemu/tests/qapi-schema/args-member-unknown.err
new file mode 100644
index 000000000..f6f82828c
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-member-unknown.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-member-unknown.json:2: Member 'member' of 'data' for command 'oops' uses unknown type 'NoSuchType'
diff --git a/qemu/tests/qapi-schema/flat-union-branch-clash.exit b/qemu/tests/qapi-schema/args-member-unknown.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/flat-union-branch-clash.exit
+++ b/qemu/tests/qapi-schema/args-member-unknown.exit
diff --git a/qemu/tests/qapi-schema/data-member-unknown.json b/qemu/tests/qapi-schema/args-member-unknown.json
index 342a41ec9..342a41ec9 100644
--- a/qemu/tests/qapi-schema/data-member-unknown.json
+++ b/qemu/tests/qapi-schema/args-member-unknown.json
diff --git a/qemu/tests/qapi-schema/enum-union-clash.out b/qemu/tests/qapi-schema/args-member-unknown.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/enum-union-clash.out
+++ b/qemu/tests/qapi-schema/args-member-unknown.out
diff --git a/qemu/tests/qapi-schema/args-name-clash.err b/qemu/tests/qapi-schema/args-name-clash.err
new file mode 100644
index 000000000..d953e8d24
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-name-clash.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-name-clash.json:4: 'a_b' (parameter of oops) collides with 'a-b' (parameter of oops)
diff --git a/qemu/tests/qapi-schema/nested-struct-returns.exit b/qemu/tests/qapi-schema/args-name-clash.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/nested-struct-returns.exit
+++ b/qemu/tests/qapi-schema/args-name-clash.exit
diff --git a/qemu/tests/qapi-schema/args-name-clash.json b/qemu/tests/qapi-schema/args-name-clash.json
new file mode 100644
index 000000000..61423cb89
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-name-clash.json
@@ -0,0 +1,4 @@
+# C member name collision
+# Reject members that clash when mapped to C names (we would have two 'a_b'
+# members).
+{ 'command': 'oops', 'data': { 'a-b': 'str', 'a_b': 'str' } }
diff --git a/qemu/tests/qapi-schema/event-max.out b/qemu/tests/qapi-schema/args-name-clash.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/event-max.out
+++ b/qemu/tests/qapi-schema/args-name-clash.out
diff --git a/qemu/tests/qapi-schema/args-union.err b/qemu/tests/qapi-schema/args-union.err
new file mode 100644
index 000000000..1d693d74d
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-union.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-union.json:4: 'data' for command 'oops' cannot use union type 'Uni'
diff --git a/qemu/tests/qapi-schema/type-bypass-no-gen.exit b/qemu/tests/qapi-schema/args-union.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/type-bypass-no-gen.exit
+++ b/qemu/tests/qapi-schema/args-union.exit
diff --git a/qemu/tests/qapi-schema/args-union.json b/qemu/tests/qapi-schema/args-union.json
new file mode 100644
index 000000000..7bdcbb7f0
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-union.json
@@ -0,0 +1,4 @@
+# we do not allow union arguments
+# TODO should we support this?
+{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } }
+{ 'command': 'oops', 'data': 'Uni' }
diff --git a/qemu/tests/qapi-schema/flat-union-base-star.out b/qemu/tests/qapi-schema/args-union.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/flat-union-base-star.out
+++ b/qemu/tests/qapi-schema/args-union.out
diff --git a/qemu/tests/qapi-schema/args-unknown.err b/qemu/tests/qapi-schema/args-unknown.err
new file mode 100644
index 000000000..4d91ec869
--- /dev/null
+++ b/qemu/tests/qapi-schema/args-unknown.err
@@ -0,0 +1 @@
+tests/qapi-schema/args-unknown.json:2: 'data' for command 'oops' uses unknown type 'NoSuchType'
diff --git a/qemu/tests/qapi-schema/union-bad-branch.exit b/qemu/tests/qapi-schema/args-unknown.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/union-bad-branch.exit
+++ b/qemu/tests/qapi-schema/args-unknown.exit
diff --git a/qemu/tests/qapi-schema/data-unknown.json b/qemu/tests/qapi-schema/args-unknown.json
index 32aba43b3..32aba43b3 100644
--- a/qemu/tests/qapi-schema/data-unknown.json
+++ b/qemu/tests/qapi-schema/args-unknown.json
diff --git a/qemu/tests/qapi-schema/flat-union-branch-clash.out b/qemu/tests/qapi-schema/args-unknown.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/flat-union-branch-clash.out
+++ b/qemu/tests/qapi-schema/args-unknown.out
diff --git a/qemu/tests/qapi-schema/base-cycle-direct.err b/qemu/tests/qapi-schema/base-cycle-direct.err
new file mode 100644
index 000000000..9c68f6543
--- /dev/null
+++ b/qemu/tests/qapi-schema/base-cycle-direct.err
@@ -0,0 +1 @@
+tests/qapi-schema/base-cycle-direct.json:2: Object Loopy contains itself
diff --git a/qemu/tests/qapi-schema/union-max.exit b/qemu/tests/qapi-schema/base-cycle-direct.exit
index d00491fd7..d00491fd7 100644
--- a/qemu/tests/qapi-schema/union-max.exit
+++ b/qemu/tests/qapi-schema/base-cycle-direct.exit
diff --git a/qemu/tests/qapi-schema/base-cycle-direct.json b/qemu/tests/qapi-schema/base-cycle-direct.json
new file mode 100644
index 000000000..4fc66d051
--- /dev/null
+++ b/qemu/tests/qapi-schema/base-cycle-direct.json
@@ -0,0 +1,2 @@
+# we reject a loop in base classes
+{ 'struct': 'Loopy', 'base': 'Loopy', 'data': {} }
diff --git a/qemu/tests/qapi-schema/flat-union-reverse-define.err b/qemu/tests/qapi-schema/base-cycle-direct.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/flat-union-reverse-define.err
+++ b/qemu/tests/qapi-schema/base-cycle-direct.out
diff --git a/qemu/tests/qapi-schema/base-cycle-indirect.err b/qemu/tests/qapi-schema/base-cycle-indirect.err
new file mode 100644
index 000000000..fc92fe47f
--- /dev/null
+++ b/qemu/tests/qapi-schema/base-cycle-indirect.err
@@ -0,0 +1 @@
+tests/qapi-schema/base-cycle-indirect.json:2: Object Base1 contains itself
diff --git a/qemu/tests/qapi-schema/base-cycle-indirect.exit b/qemu/tests/qapi-schema/base-cycle-indirect.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/base-cycle-indirect.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/base-cycle-indirect.json b/qemu/tests/qapi-schema/base-cycle-indirect.json
new file mode 100644
index 000000000..28667721a
--- /dev/null
+++ b/qemu/tests/qapi-schema/base-cycle-indirect.json
@@ -0,0 +1,3 @@
+# we reject a loop in base classes
+{ 'struct': 'Base1', 'base': 'Base2', 'data': {} }
+{ 'struct': 'Base2', 'base': 'Base1', 'data': {} }
diff --git a/qemu/tests/qapi-schema/nested-struct-returns.out b/qemu/tests/qapi-schema/base-cycle-indirect.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/nested-struct-returns.out
+++ b/qemu/tests/qapi-schema/base-cycle-indirect.out
diff --git a/qemu/tests/qapi-schema/command-int.json b/qemu/tests/qapi-schema/command-int.json
index c90d408ab..9a62554fc 100644
--- a/qemu/tests/qapi-schema/command-int.json
+++ b/qemu/tests/qapi-schema/command-int.json
@@ -1,3 +1,2 @@
# we reject collisions between commands and types
-{ 'command': 'int', 'data': { 'character': 'str' },
- 'returns': { 'value': 'int' } }
+{ 'command': 'int', 'data': { 'character': 'str' } }
diff --git a/qemu/tests/qapi-schema/comments.out b/qemu/tests/qapi-schema/comments.out
index 4ce3dcf12..5d7c13cad 100644
--- a/qemu/tests/qapi-schema/comments.out
+++ b/qemu/tests/qapi-schema/comments.out
@@ -1,3 +1,4 @@
-[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
-[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}]
-[]
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+ prefix QTYPE
+enum Status ['good', 'bad', 'ugly']
+object q_empty
diff --git a/qemu/tests/qapi-schema/data-array-unknown.err b/qemu/tests/qapi-schema/data-array-unknown.err
deleted file mode 100644
index 8b731bbcc..000000000
--- a/qemu/tests/qapi-schema/data-array-unknown.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/data-array-unknown.json:2: Member 'array' of 'data' for command 'oops' uses unknown type 'array of NoSuchType'
diff --git a/qemu/tests/qapi-schema/data-int.err b/qemu/tests/qapi-schema/data-int.err
deleted file mode 100644
index 1a9b077c0..000000000
--- a/qemu/tests/qapi-schema/data-int.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/data-int.json:2: 'data' for command 'oops' cannot use built-in type 'int'
diff --git a/qemu/tests/qapi-schema/data-member-array.exit b/qemu/tests/qapi-schema/data-member-array.exit
deleted file mode 100644
index 573541ac9..000000000
--- a/qemu/tests/qapi-schema/data-member-array.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/qemu/tests/qapi-schema/data-member-array.json b/qemu/tests/qapi-schema/data-member-array.json
deleted file mode 100644
index e6f7f5da1..000000000
--- a/qemu/tests/qapi-schema/data-member-array.json
+++ /dev/null
@@ -1,4 +0,0 @@
-# valid array members
-{ 'enum': 'abc', 'data': [ 'a', 'b', 'c' ] }
-{ 'struct': 'def', 'data': { 'array': [ 'abc' ] } }
-{ 'command': 'okay', 'data': { 'member1': [ 'int' ], 'member2': [ 'def' ] } }
diff --git a/qemu/tests/qapi-schema/data-member-array.out b/qemu/tests/qapi-schema/data-member-array.out
deleted file mode 100644
index c39fa2548..000000000
--- a/qemu/tests/qapi-schema/data-member-array.out
+++ /dev/null
@@ -1,5 +0,0 @@
-[OrderedDict([('enum', 'abc'), ('data', ['a', 'b', 'c'])]),
- OrderedDict([('struct', 'def'), ('data', OrderedDict([('array', ['abc'])]))]),
- OrderedDict([('command', 'okay'), ('data', OrderedDict([('member1', ['int']), ('member2', ['def'])]))])]
-[{'enum_name': 'abc', 'enum_values': ['a', 'b', 'c']}]
-[OrderedDict([('struct', 'def'), ('data', OrderedDict([('array', ['abc'])]))])]
diff --git a/qemu/tests/qapi-schema/data-member-unknown.err b/qemu/tests/qapi-schema/data-member-unknown.err
deleted file mode 100644
index ab905db80..000000000
--- a/qemu/tests/qapi-schema/data-member-unknown.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/data-member-unknown.json:2: Member 'member' of 'data' for command 'oops' uses unknown type 'NoSuchType'
diff --git a/qemu/tests/qapi-schema/data-unknown.err b/qemu/tests/qapi-schema/data-unknown.err
deleted file mode 100644
index 5b07277a9..000000000
--- a/qemu/tests/qapi-schema/data-unknown.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/data-unknown.json:2: 'data' for command 'oops' uses unknown type 'NoSuchType'
diff --git a/qemu/tests/qapi-schema/duplicate-key.err b/qemu/tests/qapi-schema/duplicate-key.err
index 768b276f8..6d02f8353 100644
--- a/qemu/tests/qapi-schema/duplicate-key.err
+++ b/qemu/tests/qapi-schema/duplicate-key.err
@@ -1 +1 @@
-tests/qapi-schema/duplicate-key.json:2:10: Duplicate key "key"
+tests/qapi-schema/duplicate-key.json:3:10: Duplicate key "key"
diff --git a/qemu/tests/qapi-schema/duplicate-key.json b/qemu/tests/qapi-schema/duplicate-key.json
index 1b55d8810..14ac0e8a4 100644
--- a/qemu/tests/qapi-schema/duplicate-key.json
+++ b/qemu/tests/qapi-schema/duplicate-key.json
@@ -1,2 +1,3 @@
+# QAPI cannot include the same key more than once in any {}
{ 'key': 'value',
'key': 'value' }
diff --git a/qemu/tests/qapi-schema/empty.out b/qemu/tests/qapi-schema/empty.out
index b7f89a45c..8a5b03442 100644
--- a/qemu/tests/qapi-schema/empty.out
+++ b/qemu/tests/qapi-schema/empty.out
@@ -1,3 +1,3 @@
-[]
-[]
-[]
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+ prefix QTYPE
+object q_empty
diff --git a/qemu/tests/qapi-schema/enum-bad-prefix.err b/qemu/tests/qapi-schema/enum-bad-prefix.err
new file mode 100644
index 000000000..399f5f7af
--- /dev/null
+++ b/qemu/tests/qapi-schema/enum-bad-prefix.err
@@ -0,0 +1 @@
+tests/qapi-schema/enum-bad-prefix.json:2: Enum 'MyEnum' requires a string for 'prefix'
diff --git a/qemu/tests/qapi-schema/enum-bad-prefix.exit b/qemu/tests/qapi-schema/enum-bad-prefix.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/enum-bad-prefix.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/enum-bad-prefix.json b/qemu/tests/qapi-schema/enum-bad-prefix.json
new file mode 100644
index 000000000..996f628f6
--- /dev/null
+++ b/qemu/tests/qapi-schema/enum-bad-prefix.json
@@ -0,0 +1,2 @@
+# The prefix must be a string type
+{ 'enum': 'MyEnum', 'data': [ 'one' ], 'prefix': [ 'fish' ] }
diff --git a/qemu/tests/qapi-schema/returns-int.err b/qemu/tests/qapi-schema/enum-bad-prefix.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/returns-int.err
+++ b/qemu/tests/qapi-schema/enum-bad-prefix.out
diff --git a/qemu/tests/qapi-schema/enum-clash-member.err b/qemu/tests/qapi-schema/enum-clash-member.err
index 48bd1360e..5403c7850 100644
--- a/qemu/tests/qapi-schema/enum-clash-member.err
+++ b/qemu/tests/qapi-schema/enum-clash-member.err
@@ -1 +1 @@
-tests/qapi-schema/enum-clash-member.json:2: Enum 'MyEnum' member 'ONE' clashes with 'one'
+tests/qapi-schema/enum-clash-member.json:2: 'one_two' (member of MyEnum) collides with 'one-two' (member of MyEnum)
diff --git a/qemu/tests/qapi-schema/enum-clash-member.json b/qemu/tests/qapi-schema/enum-clash-member.json
index b7dc02a28..b6928b8bf 100644
--- a/qemu/tests/qapi-schema/enum-clash-member.json
+++ b/qemu/tests/qapi-schema/enum-clash-member.json
@@ -1,2 +1,2 @@
# we reject enums where members will clash when mapped to C enum
-{ 'enum': 'MyEnum', 'data': [ 'one', 'ONE' ] }
+{ 'enum': 'MyEnum', 'data': [ 'one-two', 'one_two' ] }
diff --git a/qemu/tests/qapi-schema/enum-empty.exit b/qemu/tests/qapi-schema/enum-empty.exit
deleted file mode 100644
index 573541ac9..000000000
--- a/qemu/tests/qapi-schema/enum-empty.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/qemu/tests/qapi-schema/enum-empty.json b/qemu/tests/qapi-schema/enum-empty.json
deleted file mode 100644
index 40d4e85a2..000000000
--- a/qemu/tests/qapi-schema/enum-empty.json
+++ /dev/null
@@ -1,2 +0,0 @@
-# An empty enum, although unusual, is currently acceptable
-{ 'enum': 'MyEnum', 'data': [ ] }
diff --git a/qemu/tests/qapi-schema/enum-empty.out b/qemu/tests/qapi-schema/enum-empty.out
deleted file mode 100644
index 3b75c1613..000000000
--- a/qemu/tests/qapi-schema/enum-empty.out
+++ /dev/null
@@ -1,3 +0,0 @@
-[OrderedDict([('enum', 'MyEnum'), ('data', [])])]
-[{'enum_name': 'MyEnum', 'enum_values': []}]
-[]
diff --git a/qemu/tests/qapi-schema/enum-max-member.err b/qemu/tests/qapi-schema/enum-max-member.err
deleted file mode 100644
index f77837fb4..000000000
--- a/qemu/tests/qapi-schema/enum-max-member.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/enum-max-member.json:3: Enum 'MyEnum' member 'max' clashes with '(automatic)'
diff --git a/qemu/tests/qapi-schema/enum-max-member.json b/qemu/tests/qapi-schema/enum-max-member.json
deleted file mode 100644
index 4bcda0bf0..000000000
--- a/qemu/tests/qapi-schema/enum-max-member.json
+++ /dev/null
@@ -1,3 +0,0 @@
-# we reject user-supplied 'max' for clashing with implicit enum end
-# TODO: should we instead munge the implicit value to avoid the clash?
-{ 'enum': 'MyEnum', 'data': [ 'max' ] }
diff --git a/qemu/tests/qapi-schema/enum-member-case.err b/qemu/tests/qapi-schema/enum-member-case.err
new file mode 100644
index 000000000..b652e9aac
--- /dev/null
+++ b/qemu/tests/qapi-schema/enum-member-case.err
@@ -0,0 +1 @@
+tests/qapi-schema/enum-member-case.json:3: 'Value' (member of NoWayThisWillGetWhitelisted) should not use uppercase
diff --git a/qemu/tests/qapi-schema/enum-member-case.exit b/qemu/tests/qapi-schema/enum-member-case.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/enum-member-case.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/enum-member-case.json b/qemu/tests/qapi-schema/enum-member-case.json
new file mode 100644
index 000000000..2096b350c
--- /dev/null
+++ b/qemu/tests/qapi-schema/enum-member-case.json
@@ -0,0 +1,3 @@
+# Member names should be 'lower-case' unless the enum is whitelisted
+{ 'enum': 'UuidInfo', 'data': [ 'Value' ] } # UuidInfo is whitelisted
+{ 'enum': 'NoWayThisWillGetWhitelisted', 'data': [ 'Value' ] }
diff --git a/qemu/tests/qapi-schema/type-bypass-no-gen.out b/qemu/tests/qapi-schema/enum-member-case.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/type-bypass-no-gen.out
+++ b/qemu/tests/qapi-schema/enum-member-case.out
diff --git a/qemu/tests/qapi-schema/enum-union-clash.err b/qemu/tests/qapi-schema/enum-union-clash.err
deleted file mode 100644
index c04e1a806..000000000
--- a/qemu/tests/qapi-schema/enum-union-clash.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/enum-union-clash.json:2: enum 'UnionKind' should not end in 'Kind'
diff --git a/qemu/tests/qapi-schema/event-case.out b/qemu/tests/qapi-schema/event-case.out
index 3764bc781..b6b4134a8 100644
--- a/qemu/tests/qapi-schema/event-case.out
+++ b/qemu/tests/qapi-schema/event-case.out
@@ -1,3 +1,4 @@
-[OrderedDict([('event', 'oops')])]
-[]
-[]
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+ prefix QTYPE
+event oops None
+object q_empty
diff --git a/qemu/tests/qapi-schema/event-max.err b/qemu/tests/qapi-schema/event-max.err
deleted file mode 100644
index c85653437..000000000
--- a/qemu/tests/qapi-schema/event-max.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/event-max.json:2: Event name 'MAX' cannot be created
diff --git a/qemu/tests/qapi-schema/event-max.json b/qemu/tests/qapi-schema/event-max.json
deleted file mode 100644
index f3d7de2a3..000000000
--- a/qemu/tests/qapi-schema/event-max.json
+++ /dev/null
@@ -1,2 +0,0 @@
-# an event named 'MAX' would conflict with implicit C enum
-{ 'event': 'MAX' }
diff --git a/qemu/tests/qapi-schema/flat-union-bad-base.err b/qemu/tests/qapi-schema/flat-union-bad-base.err
index f9c31b2bf..bee24a217 100644
--- a/qemu/tests/qapi-schema/flat-union-bad-base.err
+++ b/qemu/tests/qapi-schema/flat-union-bad-base.err
@@ -1 +1 @@
-tests/qapi-schema/flat-union-bad-base.json:9: Flat union 'TestUnion' must have a string base field
+tests/qapi-schema/flat-union-bad-base.json:8: 'string' (member of TestTypeA) collides with 'string' (base of TestUnion)
diff --git a/qemu/tests/qapi-schema/flat-union-bad-base.json b/qemu/tests/qapi-schema/flat-union-bad-base.json
index e2e622bb6..74dd42170 100644
--- a/qemu/tests/qapi-schema/flat-union-bad-base.json
+++ b/qemu/tests/qapi-schema/flat-union-bad-base.json
@@ -1,5 +1,4 @@
-# we require the base to be an existing struct
-# TODO: should we allow an anonymous inline base type?
+# we allow anonymous base, but enforce no duplicate keys
{ 'enum': 'TestEnum',
'data': [ 'value1', 'value2' ] }
{ 'struct': 'TestTypeA',
@@ -7,7 +6,7 @@
{ 'struct': 'TestTypeB',
'data': { 'integer': 'int' } }
{ 'union': 'TestUnion',
- 'base': { 'enum1': 'TestEnum', 'kind': 'str' },
+ 'base': { 'enum1': 'TestEnum', 'string': 'str' },
'discriminator': 'enum1',
'data': { 'value1': 'TestTypeA',
'value2': 'TestTypeB' } }
diff --git a/qemu/tests/qapi-schema/flat-union-base-any.err b/qemu/tests/qapi-schema/flat-union-base-any.err
new file mode 100644
index 000000000..646f1c9cd
--- /dev/null
+++ b/qemu/tests/qapi-schema/flat-union-base-any.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-base-any.json:8: 'base' for union 'TestUnion' cannot use built-in type 'any'
diff --git a/qemu/tests/qapi-schema/flat-union-base-any.exit b/qemu/tests/qapi-schema/flat-union-base-any.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/flat-union-base-any.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/flat-union-base-star.json b/qemu/tests/qapi-schema/flat-union-base-any.json
index 5099439a9..fe66b713e 100644
--- a/qemu/tests/qapi-schema/flat-union-base-star.json
+++ b/qemu/tests/qapi-schema/flat-union-base-any.json
@@ -6,7 +6,7 @@
{ 'struct': 'TestTypeB',
'data': { 'integer': 'int' } }
{ 'union': 'TestUnion',
- 'base': '**',
+ 'base': 'any',
'discriminator': 'enum1',
'data': { 'value1': 'TestTypeA',
'value2': 'TestTypeB' } }
diff --git a/qemu/tests/qapi-schema/type-bypass.err b/qemu/tests/qapi-schema/flat-union-base-any.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/type-bypass.err
+++ b/qemu/tests/qapi-schema/flat-union-base-any.out
diff --git a/qemu/tests/qapi-schema/flat-union-base-star.err b/qemu/tests/qapi-schema/flat-union-base-star.err
deleted file mode 100644
index b7748f08b..000000000
--- a/qemu/tests/qapi-schema/flat-union-base-star.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/flat-union-base-star.json:8: Base '**' is not a valid struct
diff --git a/qemu/tests/qapi-schema/flat-union-base-union.err b/qemu/tests/qapi-schema/flat-union-base-union.err
index ede9859a3..f138395e4 100644
--- a/qemu/tests/qapi-schema/flat-union-base-union.err
+++ b/qemu/tests/qapi-schema/flat-union-base-union.err
@@ -1 +1 @@
-tests/qapi-schema/flat-union-base-union.json:11: Base 'UnionBase' is not a valid struct
+tests/qapi-schema/flat-union-base-union.json:14: 'base' for union 'TestUnion' cannot use union type 'UnionBase'
diff --git a/qemu/tests/qapi-schema/flat-union-base-union.json b/qemu/tests/qapi-schema/flat-union-base-union.json
index 6a8ea687a..98b4eba18 100644
--- a/qemu/tests/qapi-schema/flat-union-base-union.json
+++ b/qemu/tests/qapi-schema/flat-union-base-union.json
@@ -1,4 +1,7 @@
-# we require the base to be a struct
+# For now, we require the base to be a struct without variants
+# TODO: It would be possible to allow a union as a base, as long as all
+# permutations of QMP names exposed by base do not clash with any QMP
+# member names added by local variants.
{ 'enum': 'TestEnum',
'data': [ 'value1', 'value2' ] }
{ 'struct': 'TestTypeA',
diff --git a/qemu/tests/qapi-schema/flat-union-branch-clash.err b/qemu/tests/qapi-schema/flat-union-branch-clash.err
deleted file mode 100644
index f11276688..000000000
--- a/qemu/tests/qapi-schema/flat-union-branch-clash.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/flat-union-branch-clash.json:10: Member name 'name' of branch 'value1' clashes with base 'Base'
diff --git a/qemu/tests/qapi-schema/flat-union-clash-member.err b/qemu/tests/qapi-schema/flat-union-clash-member.err
new file mode 100644
index 000000000..2adf69755
--- /dev/null
+++ b/qemu/tests/qapi-schema/flat-union-clash-member.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-clash-member.json:11: 'name' (member of Branch1) collides with 'name' (member of Base)
diff --git a/qemu/tests/qapi-schema/flat-union-clash-member.exit b/qemu/tests/qapi-schema/flat-union-clash-member.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/flat-union-clash-member.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/flat-union-branch-clash.json b/qemu/tests/qapi-schema/flat-union-clash-member.json
index 8fb054f00..9efc7719b 100644
--- a/qemu/tests/qapi-schema/flat-union-branch-clash.json
+++ b/qemu/tests/qapi-schema/flat-union-clash-member.json
@@ -1,4 +1,5 @@
-# we check for no duplicate keys between branches and base
+# We check for no duplicate keys between branch members and base
+# base's member 'name' clashes with Branch1's
{ 'enum': 'TestEnum',
'data': [ 'value1', 'value2' ] }
{ 'struct': 'Base',
diff --git a/qemu/tests/qapi-schema/union-bad-branch.out b/qemu/tests/qapi-schema/flat-union-clash-member.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/union-bad-branch.out
+++ b/qemu/tests/qapi-schema/flat-union-clash-member.out
diff --git a/qemu/tests/qapi-schema/flat-union-empty.err b/qemu/tests/qapi-schema/flat-union-empty.err
new file mode 100644
index 000000000..15754f54e
--- /dev/null
+++ b/qemu/tests/qapi-schema/flat-union-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/flat-union-empty.json:4: Union 'Union' cannot have empty 'data'
diff --git a/qemu/tests/qapi-schema/flat-union-empty.exit b/qemu/tests/qapi-schema/flat-union-empty.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/flat-union-empty.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/flat-union-empty.json b/qemu/tests/qapi-schema/flat-union-empty.json
new file mode 100644
index 000000000..77f1d9abf
--- /dev/null
+++ b/qemu/tests/qapi-schema/flat-union-empty.json
@@ -0,0 +1,4 @@
+# flat unions cannot be empty
+{ 'enum': 'Empty', 'data': [ ] }
+{ 'struct': 'Base', 'data': { 'type': 'Empty' } }
+{ 'union': 'Union', 'base': 'Base', 'discriminator': 'type', 'data': { } }
diff --git a/qemu/tests/qapi-schema/union-max.out b/qemu/tests/qapi-schema/flat-union-empty.out
index e69de29bb..e69de29bb 100644
--- a/qemu/tests/qapi-schema/union-max.out
+++ b/qemu/tests/qapi-schema/flat-union-empty.out
diff --git a/qemu/tests/qapi-schema/flat-union-inline.err b/qemu/tests/qapi-schema/flat-union-inline.err
index ec586277b..2333358d2 100644
--- a/qemu/tests/qapi-schema/flat-union-inline.err
+++ b/qemu/tests/qapi-schema/flat-union-inline.err
@@ -1 +1 @@
-tests/qapi-schema/flat-union-inline.json:7: Flat union 'TestUnion' must have a string base field
+tests/qapi-schema/flat-union-inline.json:7: Member 'value1' of union 'TestUnion' should be a type name
diff --git a/qemu/tests/qapi-schema/flat-union-inline.json b/qemu/tests/qapi-schema/flat-union-inline.json
index 6bfdd6581..62c7cda61 100644
--- a/qemu/tests/qapi-schema/flat-union-inline.json
+++ b/qemu/tests/qapi-schema/flat-union-inline.json
@@ -1,11 +1,11 @@
# we require branches to be a struct name
-# TODO: should we allow anonymous inline types?
+# TODO: should we allow anonymous inline branch types?
{ 'enum': 'TestEnum',
'data': [ 'value1', 'value2' ] }
{ 'struct': 'Base',
'data': { 'enum1': 'TestEnum', 'kind': 'str' } }
{ 'union': 'TestUnion',
- 'base': { 'enum1': 'TestEnum', 'kind': 'str' },
+ 'base': 'Base',
'discriminator': 'enum1',
'data': { 'value1': { 'string': 'str' },
'value2': { 'integer': 'int' } } }
diff --git a/qemu/tests/qapi-schema/flat-union-no-base.err b/qemu/tests/qapi-schema/flat-union-no-base.err
index bb3f70874..841c93b55 100644
--- a/qemu/tests/qapi-schema/flat-union-no-base.err
+++ b/qemu/tests/qapi-schema/flat-union-no-base.err
@@ -1 +1 @@
-tests/qapi-schema/flat-union-no-base.json:9: Flat union 'TestUnion' must have a string base field
+tests/qapi-schema/flat-union-no-base.json:9: Flat union 'TestUnion' must have a base
diff --git a/qemu/tests/qapi-schema/flat-union-reverse-define.exit b/qemu/tests/qapi-schema/flat-union-reverse-define.exit
deleted file mode 100644
index 573541ac9..000000000
--- a/qemu/tests/qapi-schema/flat-union-reverse-define.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/qemu/tests/qapi-schema/flat-union-reverse-define.json b/qemu/tests/qapi-schema/flat-union-reverse-define.json
deleted file mode 100644
index 648bbfe2b..000000000
--- a/qemu/tests/qapi-schema/flat-union-reverse-define.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{ 'union': 'TestUnion',
- 'base': 'TestBase',
- 'discriminator': 'enum1',
- 'data': { 'value1': 'TestTypeA',
- 'value2': 'TestTypeB' } }
-
-{ 'struct': 'TestBase',
- 'data': { 'enum1': 'TestEnum' } }
-
-{ 'enum': 'TestEnum',
- 'data': [ 'value1', 'value2' ] }
-
-{ 'struct': 'TestTypeA',
- 'data': { 'string': 'str' } }
-
-{ 'struct': 'TestTypeB',
- 'data': { 'integer': 'int' } }
diff --git a/qemu/tests/qapi-schema/flat-union-reverse-define.out b/qemu/tests/qapi-schema/flat-union-reverse-define.out
deleted file mode 100644
index 1ed7b8a51..000000000
--- a/qemu/tests/qapi-schema/flat-union-reverse-define.out
+++ /dev/null
@@ -1,9 +0,0 @@
-[OrderedDict([('union', 'TestUnion'), ('base', 'TestBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'TestTypeA'), ('value2', 'TestTypeB')]))]),
- OrderedDict([('struct', 'TestBase'), ('data', OrderedDict([('enum1', 'TestEnum')]))]),
- OrderedDict([('enum', 'TestEnum'), ('data', ['value1', 'value2'])]),
- OrderedDict([('struct', 'TestTypeA'), ('data', OrderedDict([('string', 'str')]))]),
- OrderedDict([('struct', 'TestTypeB'), ('data', OrderedDict([('integer', 'int')]))])]
-[{'enum_name': 'TestEnum', 'enum_values': ['value1', 'value2']}]
-[OrderedDict([('struct', 'TestBase'), ('data', OrderedDict([('enum1', 'TestEnum')]))]),
- OrderedDict([('struct', 'TestTypeA'), ('data', OrderedDict([('string', 'str')]))]),
- OrderedDict([('struct', 'TestTypeB'), ('data', OrderedDict([('integer', 'int')]))])]
diff --git a/qemu/tests/qapi-schema/ident-with-escape.out b/qemu/tests/qapi-schema/ident-with-escape.out
index 402843081..382ce2fa2 100644
--- a/qemu/tests/qapi-schema/ident-with-escape.out
+++ b/qemu/tests/qapi-schema/ident-with-escape.out
@@ -1,3 +1,7 @@
-[OrderedDict([('command', 'fooA'), ('data', OrderedDict([('bar1', 'str')]))])]
-[]
-[]
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+ prefix QTYPE
+command fooA q_obj_fooA-arg -> None
+ gen=True success_response=True
+object q_empty
+object q_obj_fooA-arg
+ member bar1: str optional=False
diff --git a/qemu/tests/qapi-schema/include-non-file.err b/qemu/tests/qapi-schema/include-non-file.err
index 9658c7880..faae1eacf 100644
--- a/qemu/tests/qapi-schema/include-non-file.err
+++ b/qemu/tests/qapi-schema/include-non-file.err
@@ -1 +1 @@
-tests/qapi-schema/include-non-file.json:1: Expected a file name (string), got: ['foo', 'bar']
+tests/qapi-schema/include-non-file.json:1: Value of 'include' must be a string
diff --git a/qemu/tests/qapi-schema/include-non-file.json b/qemu/tests/qapi-schema/include-non-file.json
index cd43c3f9d..4711aa42e 100644
--- a/qemu/tests/qapi-schema/include-non-file.json
+++ b/qemu/tests/qapi-schema/include-non-file.json
@@ -1 +1 @@
-{ 'include': [ 'foo', 'bar' ] }
+{ 'include': {} }
diff --git a/qemu/tests/qapi-schema/include-relpath.out b/qemu/tests/qapi-schema/include-relpath.out
index 4ce3dcf12..5d7c13cad 100644
--- a/qemu/tests/qapi-schema/include-relpath.out
+++ b/qemu/tests/qapi-schema/include-relpath.out
@@ -1,3 +1,4 @@
-[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
-[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}]
-[]
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+ prefix QTYPE
+enum Status ['good', 'bad', 'ugly']
+object q_empty
diff --git a/qemu/tests/qapi-schema/include-repetition.out b/qemu/tests/qapi-schema/include-repetition.out
index 4ce3dcf12..5d7c13cad 100644
--- a/qemu/tests/qapi-schema/include-repetition.out
+++ b/qemu/tests/qapi-schema/include-repetition.out
@@ -1,3 +1,4 @@
-[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
-[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}]
-[]
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+ prefix QTYPE
+enum Status ['good', 'bad', 'ugly']
+object q_empty
diff --git a/qemu/tests/qapi-schema/include-simple.out b/qemu/tests/qapi-schema/include-simple.out
index 4ce3dcf12..5d7c13cad 100644
--- a/qemu/tests/qapi-schema/include-simple.out
+++ b/qemu/tests/qapi-schema/include-simple.out
@@ -1,3 +1,4 @@
-[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
-[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}]
-[]
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+ prefix QTYPE
+enum Status ['good', 'bad', 'ugly']
+object q_empty
diff --git a/qemu/tests/qapi-schema/indented-expr.out b/qemu/tests/qapi-schema/indented-expr.out
index b5ce9151b..ae3293a3a 100644
--- a/qemu/tests/qapi-schema/indented-expr.out
+++ b/qemu/tests/qapi-schema/indented-expr.out
@@ -1,3 +1,7 @@
-[OrderedDict([('command', 'eins')]), OrderedDict([('command', 'zwei')])]
-[]
-[]
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+ prefix QTYPE
+command eins None -> None
+ gen=True success_response=True
+object q_empty
+command zwei None -> None
+ gen=True success_response=True
diff --git a/qemu/tests/qapi-schema/leading-comma-list.err b/qemu/tests/qapi-schema/leading-comma-list.err
new file mode 100644
index 000000000..f5c870bb9
--- /dev/null
+++ b/qemu/tests/qapi-schema/leading-comma-list.err
@@ -0,0 +1 @@
+tests/qapi-schema/leading-comma-list.json:2:13: Expected "{", "[", "]", string, boolean or "null"
diff --git a/qemu/tests/qapi-schema/leading-comma-list.exit b/qemu/tests/qapi-schema/leading-comma-list.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/leading-comma-list.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/leading-comma-list.json b/qemu/tests/qapi-schema/leading-comma-list.json
new file mode 100644
index 000000000..c5ba50159
--- /dev/null
+++ b/qemu/tests/qapi-schema/leading-comma-list.json
@@ -0,0 +1,2 @@
+{ 'enum': 'Status',
+ 'data': [ , 'good', 'bad', 'ugly' ] }
diff --git a/qemu/tests/qapi-schema/leading-comma-list.out b/qemu/tests/qapi-schema/leading-comma-list.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/leading-comma-list.out
diff --git a/qemu/tests/qapi-schema/leading-comma-object.err b/qemu/tests/qapi-schema/leading-comma-object.err
new file mode 100644
index 000000000..f767b9554
--- /dev/null
+++ b/qemu/tests/qapi-schema/leading-comma-object.err
@@ -0,0 +1 @@
+tests/qapi-schema/leading-comma-object.json:1:3: Expected string or "}"
diff --git a/qemu/tests/qapi-schema/leading-comma-object.exit b/qemu/tests/qapi-schema/leading-comma-object.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/leading-comma-object.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/leading-comma-object.json b/qemu/tests/qapi-schema/leading-comma-object.json
new file mode 100644
index 000000000..c89023ff3
--- /dev/null
+++ b/qemu/tests/qapi-schema/leading-comma-object.json
@@ -0,0 +1,2 @@
+{ , 'enum': 'Status',
+ 'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/qemu/tests/qapi-schema/leading-comma-object.out b/qemu/tests/qapi-schema/leading-comma-object.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/leading-comma-object.out
diff --git a/qemu/tests/qapi-schema/nested-struct-data.json b/qemu/tests/qapi-schema/nested-struct-data.json
index 3d52d2b39..efbe773de 100644
--- a/qemu/tests/qapi-schema/nested-struct-data.json
+++ b/qemu/tests/qapi-schema/nested-struct-data.json
@@ -1,4 +1,3 @@
# inline subtypes collide with our desired future use of defaults
{ 'command': 'foo',
- 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' },
- 'returns': {} }
+ 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
diff --git a/qemu/tests/qapi-schema/nested-struct-returns.err b/qemu/tests/qapi-schema/nested-struct-returns.err
deleted file mode 100644
index 5238d075b..000000000
--- a/qemu/tests/qapi-schema/nested-struct-returns.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/nested-struct-returns.json:2: Member 'a' of 'returns' for command 'foo' should be a type name
diff --git a/qemu/tests/qapi-schema/nested-struct-returns.json b/qemu/tests/qapi-schema/nested-struct-returns.json
deleted file mode 100644
index d2cd047f0..000000000
--- a/qemu/tests/qapi-schema/nested-struct-returns.json
+++ /dev/null
@@ -1,3 +0,0 @@
-# inline subtypes collide with our desired future use of defaults
-{ 'command': 'foo',
- 'returns': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
diff --git a/qemu/tests/qapi-schema/qapi-schema-test.json b/qemu/tests/qapi-schema/qapi-schema-test.json
index c7eaa865d..f571e1bb3 100644
--- a/qemu/tests/qapi-schema/qapi-schema-test.json
+++ b/qemu/tests/qapi-schema/qapi-schema-test.json
@@ -1,19 +1,42 @@
# *-*- Mode: Python -*-*
+# This file is a stress test of supported qapi constructs that must
+# parse and compile correctly.
+
+{ 'struct': 'TestStruct',
+ 'data': { 'integer': 'int', 'boolean': 'bool', 'string': 'str' } }
+
# for testing enums
-{ 'enum': 'EnumOne',
- 'data': [ 'value1', 'value2', 'value3' ] }
{ 'struct': 'NestedEnumsOne',
- 'data': { 'enum1': 'EnumOne', '*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } }
+ 'data': { 'enum1': 'EnumOne', # Intentional forward reference
+ '*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } }
+
+# An empty enum, although unusual, is currently acceptable
+{ 'enum': 'MyEnum', 'data': [ ] }
+
+# Likewise for an empty struct, including an empty base
+{ 'struct': 'Empty1', 'data': { } }
+{ 'struct': 'Empty2', 'base': 'Empty1', 'data': { } }
+
+{ 'command': 'user_def_cmd0', 'data': 'Empty2', 'returns': 'Empty2' }
+
+# for testing override of default naming heuristic
+{ 'enum': 'QEnumTwo',
+ 'prefix': 'QENUM_TWO',
+ 'data': [ 'value1', 'value2' ] }
# for testing nested structs
+{ 'struct': 'UserDefOne',
+ 'base': 'UserDefZero', # intentional forward reference
+ 'data': { 'string': 'str',
+ '*enum1': 'EnumOne' } } # intentional forward reference
+
+{ 'enum': 'EnumOne',
+ 'data': [ 'value1', 'value2', 'value3' ] }
+
{ 'struct': 'UserDefZero',
'data': { 'integer': 'int' } }
-{ 'struct': 'UserDefOne',
- 'base': 'UserDefZero',
- 'data': { 'string': 'str', '*enum1': 'EnumOne' } }
-
{ 'struct': 'UserDefTwoDictDict',
'data': { 'userdef': 'UserDefOne', 'string': 'str' } }
@@ -26,35 +49,55 @@
'data': { 'string0': 'str',
'dict1': 'UserDefTwoDict' } }
+# dummy struct to force generation of array types not otherwise mentioned
+{ 'struct': 'ForceArrays',
+ 'data': { 'unused1':['UserDefOne'], 'unused2':['UserDefTwo'],
+ 'unused3':['TestStruct'] } }
+
# for testing unions
+# Among other things, test that a name collision between branches does
+# not cause any problems (since only one branch can be in use at a time),
+# by intentionally using two branches that both have a C member 'a_b'
{ 'struct': 'UserDefA',
- 'data': { 'boolean': 'bool' } }
+ 'data': { 'boolean': 'bool', '*a_b': 'int' } }
{ 'struct': 'UserDefB',
- 'data': { 'integer': 'int' } }
+ 'data': { 'intb': 'int', '*a-b': 'bool' } }
-{ 'struct': 'UserDefC',
- 'data': { 'string1': 'str', 'string2': 'str' } }
+{ 'union': 'UserDefFlatUnion',
+ 'base': 'UserDefUnionBase', # intentional forward reference
+ 'discriminator': 'enum1',
+ 'data': { 'value1' : 'UserDefA',
+ 'value2' : 'UserDefB',
+ 'value3' : 'UserDefB' } }
{ 'struct': 'UserDefUnionBase',
+ 'base': 'UserDefZero',
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
-{ 'union': 'UserDefFlatUnion',
- 'base': 'UserDefUnionBase',
- 'discriminator': 'enum1',
- 'data': { 'value1' : 'UserDefA', 'value2' : 'UserDefB', 'value3' : 'UserDefB' } }
-# FIXME generated struct UserDefFlatUnion has members for direct base
-# UserDefOne, but lacks members for indirect base UserDefZero
-
-# this variant of UserDefFlatUnion defaults to a union that uses fields with
+# this variant of UserDefFlatUnion defaults to a union that uses members with
# allocated types to test corner cases in the cleanup/dealloc visitor
{ 'union': 'UserDefFlatUnion2',
- 'base': 'UserDefUnionBase',
+ 'base': { '*integer': 'int', 'string': 'str', 'enum1': 'QEnumTwo' },
'discriminator': 'enum1',
- 'data': { 'value1' : 'UserDefC', 'value2' : 'UserDefB', 'value3' : 'UserDefA' } }
+ 'data': { 'value1' : 'UserDefC', # intentional forward reference
+ 'value2' : 'UserDefB' } }
+{ 'struct': 'WrapAlternate',
+ 'data': { 'alt': 'UserDefAlternate' } }
{ 'alternate': 'UserDefAlternate',
- 'data': { 'uda': 'UserDefA', 's': 'str', 'i': 'int' } }
+ 'data': { 'udfu': 'UserDefFlatUnion', 's': 'str', 'i': 'int' } }
+
+{ 'struct': 'UserDefC',
+ 'data': { 'string1': 'str', 'string2': 'str' } }
+
+# for testing use of 'number' within alternates
+{ 'alternate': 'AltStrBool', 'data': { 's': 'str', 'b': 'bool' } }
+{ 'alternate': 'AltStrNum', 'data': { 's': 'str', 'n': 'number' } }
+{ 'alternate': 'AltNumStr', 'data': { 'n': 'number', 's': 'str' } }
+{ 'alternate': 'AltStrInt', 'data': { 's': 'str', 'i': 'int' } }
+{ 'alternate': 'AltIntNum', 'data': { 'i': 'int', 'n': 'number' } }
+{ 'alternate': 'AltNumInt', 'data': { 'n': 'number', 'i': 'int' } }
# for testing native lists
{ 'union': 'UserDefNativeListUnion',
@@ -70,7 +113,8 @@
'number': ['number'],
'boolean': ['bool'],
'string': ['str'],
- 'sizes': ['size'] } }
+ 'sizes': ['size'],
+ 'any': ['any'] } }
# testing commands
{ 'command': 'user_def_cmd', 'data': {} }
@@ -78,8 +122,11 @@
{ 'command': 'user_def_cmd2',
'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'},
'returns': 'UserDefTwo' }
-{ 'command': 'user_def_cmd3', 'data': {'a': 'int', '*b': 'int' },
+
+# Returning a non-dictionary requires a name from the whitelist
+{ 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' },
'returns': 'int' }
+{ 'command': 'guest-sync', 'data': { 'arg': 'any' }, 'returns': 'any' }
# For testing integer range flattening in opts-visitor. The following schema
# corresponds to the option format:
@@ -108,12 +155,13 @@
{ 'event': 'EVENT_D',
'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
-# test that we correctly compile downstream extensions
+# test that we correctly compile downstream extensions, as well as munge
+# ticklish names
{ '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' } }
+ 'data': { '__org.qemu_x-member2': 'str', '*wchar-t': 'int' } }
{ 'union': '__org.qemu_x-Union1', 'data': { '__org.qemu_x-branch': 'str' } }
{ 'struct': '__org.qemu_x-Struct2',
'data': { 'array': ['__org.qemu_x-Union1'] } }
diff --git a/qemu/tests/qapi-schema/qapi-schema-test.out b/qemu/tests/qapi-schema/qapi-schema-test.out
index cf0ccc402..19cd214f6 100644
--- a/qemu/tests/qapi-schema/qapi-schema-test.out
+++ b/qemu/tests/qapi-schema/qapi-schema-test.out
@@ -1,55 +1,211 @@
-[OrderedDict([('enum', 'EnumOne'), ('data', ['value1', 'value2', 'value3'])]),
- OrderedDict([('struct', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]),
- OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]),
- OrderedDict([('struct', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]),
- OrderedDict([('struct', 'UserDefTwoDictDict'), ('data', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]),
- OrderedDict([('struct', 'UserDefTwoDict'), ('data', OrderedDict([('string1', 'str'), ('dict2', 'UserDefTwoDictDict'), ('*dict3', 'UserDefTwoDictDict')]))]),
- OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', 'UserDefTwoDict')]))]),
- OrderedDict([('struct', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
- OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
- OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]),
- OrderedDict([('struct', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
- OrderedDict([('union', 'UserDefFlatUnion'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefA'), ('value2', 'UserDefB'), ('value3', 'UserDefB')]))]),
- OrderedDict([('union', 'UserDefFlatUnion2'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefC'), ('value2', 'UserDefB'), ('value3', 'UserDefA')]))]),
- OrderedDict([('alternate', 'UserDefAlternate'), ('data', OrderedDict([('uda', 'UserDefA'), ('s', 'str'), ('i', 'int')]))]),
- OrderedDict([('union', 'UserDefNativeListUnion'), ('data', OrderedDict([('integer', ['int']), ('s8', ['int8']), ('s16', ['int16']), ('s32', ['int32']), ('s64', ['int64']), ('u8', ['uint8']), ('u16', ['uint16']), ('u32', ['uint32']), ('u64', ['uint64']), ('number', ['number']), ('boolean', ['bool']), ('string', ['str']), ('sizes', ['size'])]))]),
- OrderedDict([('command', 'user_def_cmd'), ('data', OrderedDict())]),
- OrderedDict([('command', 'user_def_cmd1'), ('data', OrderedDict([('ud1a', 'UserDefOne')]))]),
- OrderedDict([('command', 'user_def_cmd2'), ('data', OrderedDict([('ud1a', 'UserDefOne'), ('*ud1b', 'UserDefOne')])), ('returns', 'UserDefTwo')]),
- OrderedDict([('command', 'user_def_cmd3'), ('data', OrderedDict([('a', 'int'), ('*b', 'int')])), ('returns', 'int')]),
- OrderedDict([('struct', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
- OrderedDict([('struct', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))]),
- OrderedDict([('event', 'EVENT_A')]),
- OrderedDict([('event', 'EVENT_B'), ('data', OrderedDict())]),
- OrderedDict([('event', 'EVENT_C'), ('data', OrderedDict([('*a', 'int'), ('*b', 'UserDefOne'), ('c', 'str')]))]),
- OrderedDict([('event', 'EVENT_D'), ('data', OrderedDict([('a', 'EventStructOne'), ('b', 'str'), ('*c', 'str'), ('*enum3', 'EnumOne')]))]),
- OrderedDict([('enum', '__org.qemu_x-Enum'), ('data', ['__org.qemu_x-value'])]),
- OrderedDict([('struct', '__org.qemu_x-Base'), ('data', OrderedDict([('__org.qemu_x-member1', '__org.qemu_x-Enum')]))]),
- OrderedDict([('struct', '__org.qemu_x-Struct'), ('base', '__org.qemu_x-Base'), ('data', OrderedDict([('__org.qemu_x-member2', 'str')]))]),
- OrderedDict([('union', '__org.qemu_x-Union1'), ('data', OrderedDict([('__org.qemu_x-branch', 'str')]))]),
- OrderedDict([('struct', '__org.qemu_x-Struct2'), ('data', OrderedDict([('array', ['__org.qemu_x-Union1'])]))]),
- OrderedDict([('union', '__org.qemu_x-Union2'), ('base', '__org.qemu_x-Base'), ('discriminator', '__org.qemu_x-member1'), ('data', OrderedDict([('__org.qemu_x-value', '__org.qemu_x-Struct2')]))]),
- OrderedDict([('alternate', '__org.qemu_x-Alt'), ('data', OrderedDict([('__org.qemu_x-branch', 'str'), ('b', '__org.qemu_x-Base')]))]),
- OrderedDict([('event', '__ORG.QEMU_X-EVENT'), ('data', '__org.qemu_x-Struct')]),
- OrderedDict([('command', '__org.qemu_x-command'), ('data', OrderedDict([('a', ['__org.qemu_x-Enum']), ('b', ['__org.qemu_x-Struct']), ('c', '__org.qemu_x-Union2'), ('d', '__org.qemu_x-Alt')])), ('returns', '__org.qemu_x-Union1')])]
-[{'enum_name': 'EnumOne', 'enum_values': ['value1', 'value2', 'value3']},
- {'enum_name': '__org.qemu_x-Enum', 'enum_values': ['__org.qemu_x-value']},
- {'enum_name': 'UserDefAlternateKind', 'enum_values': None},
- {'enum_name': 'UserDefNativeListUnionKind', 'enum_values': None},
- {'enum_name': '__org.qemu_x-Union1Kind', 'enum_values': None},
- {'enum_name': '__org.qemu_x-AltKind', 'enum_values': None}]
-[OrderedDict([('struct', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]),
- OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]),
- OrderedDict([('struct', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]),
- OrderedDict([('struct', 'UserDefTwoDictDict'), ('data', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]),
- OrderedDict([('struct', 'UserDefTwoDict'), ('data', OrderedDict([('string1', 'str'), ('dict2', 'UserDefTwoDictDict'), ('*dict3', 'UserDefTwoDictDict')]))]),
- OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', 'UserDefTwoDict')]))]),
- OrderedDict([('struct', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
- OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
- OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]),
- OrderedDict([('struct', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
- OrderedDict([('struct', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
- OrderedDict([('struct', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))]),
- OrderedDict([('struct', '__org.qemu_x-Base'), ('data', OrderedDict([('__org.qemu_x-member1', '__org.qemu_x-Enum')]))]),
- OrderedDict([('struct', '__org.qemu_x-Struct'), ('base', '__org.qemu_x-Base'), ('data', OrderedDict([('__org.qemu_x-member2', 'str')]))]),
- OrderedDict([('struct', '__org.qemu_x-Struct2'), ('data', OrderedDict([('array', ['__org.qemu_x-Union1'])]))])]
+alternate AltIntNum
+ case i: int
+ case n: number
+alternate AltNumInt
+ case n: number
+ case i: int
+alternate AltNumStr
+ case n: number
+ case s: str
+alternate AltStrBool
+ case s: str
+ case b: bool
+alternate AltStrInt
+ case s: str
+ case i: int
+alternate AltStrNum
+ case s: str
+ case n: number
+event EVENT_A None
+event EVENT_B None
+event EVENT_C q_obj_EVENT_C-arg
+event EVENT_D q_obj_EVENT_D-arg
+object Empty1
+object Empty2
+ base Empty1
+enum EnumOne ['value1', 'value2', 'value3']
+object EventStructOne
+ member struct1: UserDefOne optional=False
+ member string: str optional=False
+ member enum2: EnumOne optional=True
+object ForceArrays
+ member unused1: UserDefOneList optional=False
+ member unused2: UserDefTwoList optional=False
+ member unused3: TestStructList optional=False
+enum MyEnum []
+object NestedEnumsOne
+ member enum1: EnumOne optional=False
+ member enum2: EnumOne optional=True
+ member enum3: EnumOne optional=False
+ member enum4: EnumOne optional=True
+enum QEnumTwo ['value1', 'value2']
+ prefix QENUM_TWO
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+ prefix QTYPE
+object TestStruct
+ member integer: int optional=False
+ member boolean: bool optional=False
+ member string: str optional=False
+object UserDefA
+ member boolean: bool optional=False
+ member a_b: int optional=True
+alternate UserDefAlternate
+ case udfu: UserDefFlatUnion
+ case s: str
+ case i: int
+object UserDefB
+ member intb: int optional=False
+ member a-b: bool optional=True
+object UserDefC
+ member string1: str optional=False
+ member string2: str optional=False
+object UserDefFlatUnion
+ base UserDefUnionBase
+ tag enum1
+ case value1: UserDefA
+ case value2: UserDefB
+ case value3: UserDefB
+object UserDefFlatUnion2
+ base q_obj_UserDefFlatUnion2-base
+ tag enum1
+ case value1: UserDefC
+ case value2: UserDefB
+object UserDefNativeListUnion
+ member type: UserDefNativeListUnionKind optional=False
+ case integer: q_obj_intList-wrapper
+ case s8: q_obj_int8List-wrapper
+ case s16: q_obj_int16List-wrapper
+ case s32: q_obj_int32List-wrapper
+ case s64: q_obj_int64List-wrapper
+ case u8: q_obj_uint8List-wrapper
+ case u16: q_obj_uint16List-wrapper
+ case u32: q_obj_uint32List-wrapper
+ case u64: q_obj_uint64List-wrapper
+ case number: q_obj_numberList-wrapper
+ case boolean: q_obj_boolList-wrapper
+ case string: q_obj_strList-wrapper
+ case sizes: q_obj_sizeList-wrapper
+ case any: q_obj_anyList-wrapper
+enum UserDefNativeListUnionKind ['integer', 's8', 's16', 's32', 's64', 'u8', 'u16', 'u32', 'u64', 'number', 'boolean', 'string', 'sizes', 'any']
+object UserDefOne
+ base UserDefZero
+ member string: str optional=False
+ member enum1: EnumOne optional=True
+object UserDefOptions
+ member i64: intList optional=True
+ member u64: uint64List optional=True
+ member u16: uint16List optional=True
+ member i64x: int optional=True
+ member u64x: uint64 optional=True
+object UserDefTwo
+ member string0: str optional=False
+ member dict1: UserDefTwoDict optional=False
+object UserDefTwoDict
+ member string1: str optional=False
+ member dict2: UserDefTwoDictDict optional=False
+ member dict3: UserDefTwoDictDict optional=True
+object UserDefTwoDictDict
+ member userdef: UserDefOne optional=False
+ member string: str optional=False
+object UserDefUnionBase
+ base UserDefZero
+ member string: str optional=False
+ member enum1: EnumOne optional=False
+object UserDefZero
+ member integer: int optional=False
+object WrapAlternate
+ member alt: UserDefAlternate optional=False
+event __ORG.QEMU_X-EVENT __org.qemu_x-Struct
+alternate __org.qemu_x-Alt
+ case __org.qemu_x-branch: str
+ case b: __org.qemu_x-Base
+object __org.qemu_x-Base
+ member __org.qemu_x-member1: __org.qemu_x-Enum optional=False
+enum __org.qemu_x-Enum ['__org.qemu_x-value']
+object __org.qemu_x-Struct
+ base __org.qemu_x-Base
+ member __org.qemu_x-member2: str optional=False
+ member wchar-t: int optional=True
+object __org.qemu_x-Struct2
+ member array: __org.qemu_x-Union1List optional=False
+object __org.qemu_x-Union1
+ member type: __org.qemu_x-Union1Kind optional=False
+ case __org.qemu_x-branch: q_obj_str-wrapper
+enum __org.qemu_x-Union1Kind ['__org.qemu_x-branch']
+object __org.qemu_x-Union2
+ base __org.qemu_x-Base
+ tag __org.qemu_x-member1
+ case __org.qemu_x-value: __org.qemu_x-Struct2
+command __org.qemu_x-command q_obj___org.qemu_x-command-arg -> __org.qemu_x-Union1
+ gen=True success_response=True
+command guest-get-time q_obj_guest-get-time-arg -> int
+ gen=True success_response=True
+command guest-sync q_obj_guest-sync-arg -> any
+ gen=True success_response=True
+object q_empty
+object q_obj_EVENT_C-arg
+ member a: int optional=True
+ member b: UserDefOne optional=True
+ member c: str optional=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
+object q_obj_UserDefFlatUnion2-base
+ member integer: int optional=True
+ member string: str optional=False
+ member enum1: QEnumTwo optional=False
+object q_obj___org.qemu_x-command-arg
+ member a: __org.qemu_x-EnumList optional=False
+ member b: __org.qemu_x-StructList optional=False
+ member c: __org.qemu_x-Union2 optional=False
+ member d: __org.qemu_x-Alt optional=False
+object q_obj_anyList-wrapper
+ member data: anyList optional=False
+object q_obj_boolList-wrapper
+ member data: boolList optional=False
+object q_obj_guest-get-time-arg
+ member a: int optional=False
+ member b: int optional=True
+object q_obj_guest-sync-arg
+ member arg: any optional=False
+object q_obj_int16List-wrapper
+ member data: int16List optional=False
+object q_obj_int32List-wrapper
+ member data: int32List optional=False
+object q_obj_int64List-wrapper
+ member data: int64List optional=False
+object q_obj_int8List-wrapper
+ member data: int8List optional=False
+object q_obj_intList-wrapper
+ member data: intList optional=False
+object q_obj_numberList-wrapper
+ member data: numberList optional=False
+object q_obj_sizeList-wrapper
+ member data: sizeList optional=False
+object q_obj_str-wrapper
+ member data: str optional=False
+object q_obj_strList-wrapper
+ member data: strList optional=False
+object q_obj_uint16List-wrapper
+ member data: uint16List optional=False
+object q_obj_uint32List-wrapper
+ member data: uint32List optional=False
+object q_obj_uint64List-wrapper
+ member data: uint64List optional=False
+object q_obj_uint8List-wrapper
+ member data: uint8List optional=False
+object q_obj_user_def_cmd1-arg
+ member ud1a: UserDefOne optional=False
+object q_obj_user_def_cmd2-arg
+ member ud1a: UserDefOne optional=False
+ member ud1b: UserDefOne optional=True
+command user_def_cmd None -> None
+ gen=True success_response=True
+command user_def_cmd0 Empty2 -> Empty2
+ gen=True success_response=True
+command user_def_cmd1 q_obj_user_def_cmd1-arg -> None
+ gen=True success_response=True
+command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo
+ gen=True success_response=True
diff --git a/qemu/tests/qapi-schema/reserved-command-q.err b/qemu/tests/qapi-schema/reserved-command-q.err
new file mode 100644
index 000000000..f939e044e
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-command-q.err
@@ -0,0 +1 @@
+tests/qapi-schema/reserved-command-q.json:5: 'command' uses invalid name 'q-unix'
diff --git a/qemu/tests/qapi-schema/reserved-command-q.exit b/qemu/tests/qapi-schema/reserved-command-q.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-command-q.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/reserved-command-q.json b/qemu/tests/qapi-schema/reserved-command-q.json
new file mode 100644
index 000000000..99f8aae31
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-command-q.json
@@ -0,0 +1,5 @@
+# C entity name collision
+# We reject names like 'q-unix', because they can collide with the mangled
+# name for 'unix' in generated C.
+{ 'command': 'unix' }
+{ 'command': 'q-unix' }
diff --git a/qemu/tests/qapi-schema/reserved-command-q.out b/qemu/tests/qapi-schema/reserved-command-q.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-command-q.out
diff --git a/qemu/tests/qapi-schema/reserved-enum-q.err b/qemu/tests/qapi-schema/reserved-enum-q.err
new file mode 100644
index 000000000..e1c3480ee
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-enum-q.err
@@ -0,0 +1 @@
+tests/qapi-schema/reserved-enum-q.json:4: Member of enum 'Foo' uses invalid name 'q-Unix'
diff --git a/qemu/tests/qapi-schema/reserved-enum-q.exit b/qemu/tests/qapi-schema/reserved-enum-q.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-enum-q.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/reserved-enum-q.json b/qemu/tests/qapi-schema/reserved-enum-q.json
new file mode 100644
index 000000000..3593a765e
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-enum-q.json
@@ -0,0 +1,4 @@
+# C entity name collision
+# We reject names like 'q-unix', because they can collide with the mangled
+# name for 'unix' in generated C.
+{ 'enum': 'Foo', 'data': [ 'unix', 'q-Unix' ] }
diff --git a/qemu/tests/qapi-schema/reserved-enum-q.out b/qemu/tests/qapi-schema/reserved-enum-q.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-enum-q.out
diff --git a/qemu/tests/qapi-schema/reserved-member-has.err b/qemu/tests/qapi-schema/reserved-member-has.err
new file mode 100644
index 000000000..e75577144
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-has.err
@@ -0,0 +1 @@
+tests/qapi-schema/reserved-member-has.json:5: Member of 'data' for command 'oops' uses reserved name 'has-a'
diff --git a/qemu/tests/qapi-schema/reserved-member-has.exit b/qemu/tests/qapi-schema/reserved-member-has.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-has.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/reserved-member-has.json b/qemu/tests/qapi-schema/reserved-member-has.json
new file mode 100644
index 000000000..45b9109bd
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-has.json
@@ -0,0 +1,5 @@
+# C member name collision
+# We reject names like 'has-a', because they can collide with the flag
+# for an optional 'a' in generated C.
+# TODO we could munge the optional flag name to avoid the collision.
+{ 'command': 'oops', 'data': { '*a': 'str', 'has-a': 'str' } }
diff --git a/qemu/tests/qapi-schema/reserved-member-has.out b/qemu/tests/qapi-schema/reserved-member-has.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-has.out
diff --git a/qemu/tests/qapi-schema/reserved-member-q.err b/qemu/tests/qapi-schema/reserved-member-q.err
new file mode 100644
index 000000000..f3d5dd781
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-q.err
@@ -0,0 +1 @@
+tests/qapi-schema/reserved-member-q.json:4: Member of 'data' for struct 'Foo' uses invalid name 'q-unix'
diff --git a/qemu/tests/qapi-schema/reserved-member-q.exit b/qemu/tests/qapi-schema/reserved-member-q.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-q.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/reserved-member-q.json b/qemu/tests/qapi-schema/reserved-member-q.json
new file mode 100644
index 000000000..62fed8fdd
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-q.json
@@ -0,0 +1,4 @@
+# C member name collision
+# We reject names like 'q-unix', because they can collide with the mangled
+# name for 'unix' in generated C.
+{ 'struct': 'Foo', 'data': { 'unix':'int', 'q-unix':'bool' } }
diff --git a/qemu/tests/qapi-schema/reserved-member-q.out b/qemu/tests/qapi-schema/reserved-member-q.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-q.out
diff --git a/qemu/tests/qapi-schema/reserved-member-u.err b/qemu/tests/qapi-schema/reserved-member-u.err
new file mode 100644
index 000000000..87d42296c
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-u.err
@@ -0,0 +1 @@
+tests/qapi-schema/reserved-member-u.json:7: Member of 'data' for struct 'Oops' uses reserved name 'u'
diff --git a/qemu/tests/qapi-schema/reserved-member-u.exit b/qemu/tests/qapi-schema/reserved-member-u.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-u.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/reserved-member-u.json b/qemu/tests/qapi-schema/reserved-member-u.json
new file mode 100644
index 000000000..1eaf0f301
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-u.json
@@ -0,0 +1,7 @@
+# Potential C member name collision
+# We reject use of 'u' as a member name, to allow it for internal use in
+# putting union branch members in a separate namespace from QMP members.
+# This is true even for non-unions, because it is possible to convert a
+# struct to flat union while remaining backwards compatible in QMP.
+# TODO - we could munge the member name to 'q_u' to avoid the collision
+{ 'struct': 'Oops', 'data': { 'u': 'str' } }
diff --git a/qemu/tests/qapi-schema/reserved-member-u.out b/qemu/tests/qapi-schema/reserved-member-u.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-u.out
diff --git a/qemu/tests/qapi-schema/reserved-member-underscore.err b/qemu/tests/qapi-schema/reserved-member-underscore.err
new file mode 100644
index 000000000..65ff0da8c
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-underscore.err
@@ -0,0 +1 @@
+tests/qapi-schema/reserved-member-underscore.json:4: Member of 'data' for struct 'Oops' uses invalid name '_oops'
diff --git a/qemu/tests/qapi-schema/reserved-member-underscore.exit b/qemu/tests/qapi-schema/reserved-member-underscore.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-underscore.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/reserved-member-underscore.json b/qemu/tests/qapi-schema/reserved-member-underscore.json
new file mode 100644
index 000000000..4a3a01763
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-underscore.json
@@ -0,0 +1,4 @@
+# C member name collision
+# We reject use of a single leading underscore in all names (names must
+# begin with a letter or a downstream extension double-underscore prefix).
+{ 'struct': 'Oops', 'data': { '_oops': 'str' } }
diff --git a/qemu/tests/qapi-schema/reserved-member-underscore.out b/qemu/tests/qapi-schema/reserved-member-underscore.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-member-underscore.out
diff --git a/qemu/tests/qapi-schema/reserved-type-kind.err b/qemu/tests/qapi-schema/reserved-type-kind.err
new file mode 100644
index 000000000..0a38efaad
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-type-kind.err
@@ -0,0 +1 @@
+tests/qapi-schema/reserved-type-kind.json:2: enum 'UnionKind' should not end in 'Kind'
diff --git a/qemu/tests/qapi-schema/reserved-type-kind.exit b/qemu/tests/qapi-schema/reserved-type-kind.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-type-kind.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/enum-union-clash.json b/qemu/tests/qapi-schema/reserved-type-kind.json
index 593282b6c..9ecaba12b 100644
--- a/qemu/tests/qapi-schema/enum-union-clash.json
+++ b/qemu/tests/qapi-schema/reserved-type-kind.json
@@ -1,4 +1,2 @@
# we reject types that would conflict with implicit union enum
{ 'enum': 'UnionKind', 'data': [ 'oops' ] }
-{ 'union': 'Union',
- 'data': { 'a': 'int' } }
diff --git a/qemu/tests/qapi-schema/reserved-type-kind.out b/qemu/tests/qapi-schema/reserved-type-kind.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-type-kind.out
diff --git a/qemu/tests/qapi-schema/reserved-type-list.err b/qemu/tests/qapi-schema/reserved-type-list.err
new file mode 100644
index 000000000..4510fa6d9
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-type-list.err
@@ -0,0 +1 @@
+tests/qapi-schema/reserved-type-list.json:5: struct 'FooList' should not end in 'List'
diff --git a/qemu/tests/qapi-schema/reserved-type-list.exit b/qemu/tests/qapi-schema/reserved-type-list.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-type-list.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/reserved-type-list.json b/qemu/tests/qapi-schema/reserved-type-list.json
new file mode 100644
index 000000000..98d53bf80
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-type-list.json
@@ -0,0 +1,5 @@
+# Potential C name collision
+# We reserve names ending in 'List' for use by array types.
+# TODO - we could choose array names to avoid collision with user types,
+# in order to let this compile
+{ 'struct': 'FooList', 'data': { 's': 'str' } }
diff --git a/qemu/tests/qapi-schema/reserved-type-list.out b/qemu/tests/qapi-schema/reserved-type-list.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/reserved-type-list.out
diff --git a/qemu/tests/qapi-schema/returns-dict.err b/qemu/tests/qapi-schema/returns-dict.err
new file mode 100644
index 000000000..eb2d0c466
--- /dev/null
+++ b/qemu/tests/qapi-schema/returns-dict.err
@@ -0,0 +1 @@
+tests/qapi-schema/returns-dict.json:2: 'returns' for command 'oops' should be a type name
diff --git a/qemu/tests/qapi-schema/returns-dict.exit b/qemu/tests/qapi-schema/returns-dict.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/returns-dict.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/returns-dict.json b/qemu/tests/qapi-schema/returns-dict.json
new file mode 100644
index 000000000..1cfef3ede
--- /dev/null
+++ b/qemu/tests/qapi-schema/returns-dict.json
@@ -0,0 +1,2 @@
+# we reject inline struct return type
+{ 'command': 'oops', 'returns': { 'a': 'str' } }
diff --git a/qemu/tests/qapi-schema/returns-dict.out b/qemu/tests/qapi-schema/returns-dict.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/returns-dict.out
diff --git a/qemu/tests/qapi-schema/returns-int.exit b/qemu/tests/qapi-schema/returns-int.exit
deleted file mode 100644
index 573541ac9..000000000
--- a/qemu/tests/qapi-schema/returns-int.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/qemu/tests/qapi-schema/returns-int.json b/qemu/tests/qapi-schema/returns-int.json
deleted file mode 100644
index 870ec6366..000000000
--- a/qemu/tests/qapi-schema/returns-int.json
+++ /dev/null
@@ -1,3 +0,0 @@
-# It is okay (although not extensible) to return a non-dictionary
-# But to make it work, the name must be in a whitelist
-{ 'command': 'guest-get-time', 'returns': 'int' }
diff --git a/qemu/tests/qapi-schema/returns-int.out b/qemu/tests/qapi-schema/returns-int.out
deleted file mode 100644
index 70b3ac5e6..000000000
--- a/qemu/tests/qapi-schema/returns-int.out
+++ /dev/null
@@ -1,3 +0,0 @@
-[OrderedDict([('command', 'guest-get-time'), ('returns', 'int')])]
-[]
-[]
diff --git a/qemu/tests/qapi-schema/returns-whitelist.err b/qemu/tests/qapi-schema/returns-whitelist.err
index a41f019a5..f47c1ee7c 100644
--- a/qemu/tests/qapi-schema/returns-whitelist.err
+++ b/qemu/tests/qapi-schema/returns-whitelist.err
@@ -1 +1 @@
-tests/qapi-schema/returns-whitelist.json:10: 'returns' for command 'no-way-this-will-get-whitelisted' cannot use built-in type 'array of int'
+tests/qapi-schema/returns-whitelist.json:10: 'returns' for command 'no-way-this-will-get-whitelisted' cannot use built-in type 'int'
diff --git a/qemu/tests/qapi-schema/struct-base-clash-deep.err b/qemu/tests/qapi-schema/struct-base-clash-deep.err
index e3e9f8d28..e2d7943f2 100644
--- a/qemu/tests/qapi-schema/struct-base-clash-deep.err
+++ b/qemu/tests/qapi-schema/struct-base-clash-deep.err
@@ -1 +1 @@
-tests/qapi-schema/struct-base-clash-deep.json:7: Member name 'name' clashes with base 'Base'
+tests/qapi-schema/struct-base-clash-deep.json:10: 'name' (member of Sub) collides with 'name' (member of Base)
diff --git a/qemu/tests/qapi-schema/struct-base-clash-deep.json b/qemu/tests/qapi-schema/struct-base-clash-deep.json
index 552fe9431..fa873ab5d 100644
--- a/qemu/tests/qapi-schema/struct-base-clash-deep.json
+++ b/qemu/tests/qapi-schema/struct-base-clash-deep.json
@@ -1,4 +1,7 @@
-# we check for no duplicate keys with indirect base
+# Reject attempts to duplicate QMP members
+# Here, 'name' would have to appear twice on the wire, locally and
+# indirectly for the grandparent base; the collision doesn't care that
+# one instance is optional.
{ 'struct': 'Base',
'data': { 'name': 'str' } }
{ 'struct': 'Mid',
diff --git a/qemu/tests/qapi-schema/struct-base-clash.err b/qemu/tests/qapi-schema/struct-base-clash.err
index 3ac37fb26..c52f33d27 100644
--- a/qemu/tests/qapi-schema/struct-base-clash.err
+++ b/qemu/tests/qapi-schema/struct-base-clash.err
@@ -1 +1 @@
-tests/qapi-schema/struct-base-clash.json:4: Member name 'name' clashes with base 'Base'
+tests/qapi-schema/struct-base-clash.json:5: 'name' (member of Sub) collides with 'name' (member of Base)
diff --git a/qemu/tests/qapi-schema/struct-base-clash.json b/qemu/tests/qapi-schema/struct-base-clash.json
index f2afc9b6f..11aec80fe 100644
--- a/qemu/tests/qapi-schema/struct-base-clash.json
+++ b/qemu/tests/qapi-schema/struct-base-clash.json
@@ -1,4 +1,5 @@
-# we check for no duplicate keys with base
+# Reject attempts to duplicate QMP members
+# Here, 'name' would have to appear twice on the wire, locally and for base.
{ 'struct': 'Base',
'data': { 'name': 'str' } }
{ 'struct': 'Sub',
diff --git a/qemu/tests/qapi-schema/struct-data-invalid.err b/qemu/tests/qapi-schema/struct-data-invalid.err
new file mode 100644
index 000000000..6644f4c2a
--- /dev/null
+++ b/qemu/tests/qapi-schema/struct-data-invalid.err
@@ -0,0 +1 @@
+tests/qapi-schema/struct-data-invalid.json:1: 'data' for struct 'foo' should be a dictionary or type name
diff --git a/qemu/tests/qapi-schema/struct-data-invalid.exit b/qemu/tests/qapi-schema/struct-data-invalid.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/struct-data-invalid.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/struct-data-invalid.json b/qemu/tests/qapi-schema/struct-data-invalid.json
new file mode 100644
index 000000000..9adbc3bb6
--- /dev/null
+++ b/qemu/tests/qapi-schema/struct-data-invalid.json
@@ -0,0 +1,2 @@
+{ 'struct': 'foo',
+ 'data': false }
diff --git a/qemu/tests/qapi-schema/struct-data-invalid.out b/qemu/tests/qapi-schema/struct-data-invalid.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/struct-data-invalid.out
diff --git a/qemu/tests/qapi-schema/struct-member-invalid.err b/qemu/tests/qapi-schema/struct-member-invalid.err
new file mode 100644
index 000000000..69a326d45
--- /dev/null
+++ b/qemu/tests/qapi-schema/struct-member-invalid.err
@@ -0,0 +1 @@
+tests/qapi-schema/struct-member-invalid.json:1: Member 'a' of 'data' for struct 'foo' should be a type name
diff --git a/qemu/tests/qapi-schema/struct-member-invalid.exit b/qemu/tests/qapi-schema/struct-member-invalid.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/struct-member-invalid.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/struct-member-invalid.json b/qemu/tests/qapi-schema/struct-member-invalid.json
new file mode 100644
index 000000000..8f172f7a8
--- /dev/null
+++ b/qemu/tests/qapi-schema/struct-member-invalid.json
@@ -0,0 +1,2 @@
+{ 'struct': 'foo',
+ 'data': { 'a': false } }
diff --git a/qemu/tests/qapi-schema/struct-member-invalid.out b/qemu/tests/qapi-schema/struct-member-invalid.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/struct-member-invalid.out
diff --git a/qemu/tests/qapi-schema/test-qapi.py b/qemu/tests/qapi-schema/test-qapi.py
index 634ef2d00..649677e01 100644
--- a/qemu/tests/qapi-schema/test-qapi.py
+++ b/qemu/tests/qapi-schema/test-qapi.py
@@ -15,11 +15,42 @@ from pprint import pprint
import os
import sys
-try:
- exprs = parse_schema(sys.argv[1])
-except SystemExit:
- raise
-
-pprint(exprs)
-pprint(enum_types)
-pprint(struct_types)
+
+class QAPISchemaTestVisitor(QAPISchemaVisitor):
+ def visit_enum_type(self, name, info, values, prefix):
+ print 'enum %s %s' % (name, values)
+ if prefix:
+ print ' prefix %s' % prefix
+
+ def visit_object_type(self, name, info, base, members, variants):
+ print 'object %s' % name
+ if base:
+ print ' base %s' % base.name
+ for m in members:
+ print ' member %s: %s optional=%s' % \
+ (m.name, m.type.name, m.optional)
+ self._print_variants(variants)
+
+ def visit_alternate_type(self, name, info, variants):
+ print 'alternate %s' % name
+ self._print_variants(variants)
+
+ def visit_command(self, name, info, arg_type, ret_type,
+ gen, success_response):
+ print 'command %s %s -> %s' % \
+ (name, arg_type and arg_type.name, ret_type and ret_type.name)
+ print ' gen=%s success_response=%s' % (gen, success_response)
+
+ def visit_event(self, name, info, arg_type):
+ print 'event %s %s' % (name, arg_type and arg_type.name)
+
+ @staticmethod
+ def _print_variants(variants):
+ if variants:
+ if variants.tag_name:
+ print ' tag %s' % variants.tag_name
+ for v in variants.variants:
+ print ' case %s: %s' % (v.name, v.type.name)
+
+schema = QAPISchema(sys.argv[1])
+schema.visit(QAPISchemaTestVisitor())
diff --git a/qemu/tests/qapi-schema/type-bypass-no-gen.err b/qemu/tests/qapi-schema/type-bypass-no-gen.err
deleted file mode 100644
index 20cef0a8a..000000000
--- a/qemu/tests/qapi-schema/type-bypass-no-gen.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/type-bypass-no-gen.json:2: Member 'arg' of 'data' for command 'unsafe' uses '**' but did not request 'gen':false
diff --git a/qemu/tests/qapi-schema/type-bypass-no-gen.json b/qemu/tests/qapi-schema/type-bypass-no-gen.json
deleted file mode 100644
index 4feae3719..000000000
--- a/qemu/tests/qapi-schema/type-bypass-no-gen.json
+++ /dev/null
@@ -1,2 +0,0 @@
-# type bypass only works with 'gen':false
-{ 'command': 'unsafe', 'data': { 'arg': '**' }, 'returns': '**' }
diff --git a/qemu/tests/qapi-schema/type-bypass.exit b/qemu/tests/qapi-schema/type-bypass.exit
deleted file mode 100644
index 573541ac9..000000000
--- a/qemu/tests/qapi-schema/type-bypass.exit
+++ /dev/null
@@ -1 +0,0 @@
-0
diff --git a/qemu/tests/qapi-schema/type-bypass.json b/qemu/tests/qapi-schema/type-bypass.json
deleted file mode 100644
index 48b213783..000000000
--- a/qemu/tests/qapi-schema/type-bypass.json
+++ /dev/null
@@ -1,2 +0,0 @@
-# Use of 'gen':false allows bypassing type system
-{ 'command': 'unsafe', 'data': { 'arg': '**' }, 'returns': '**', 'gen': false }
diff --git a/qemu/tests/qapi-schema/type-bypass.out b/qemu/tests/qapi-schema/type-bypass.out
deleted file mode 100644
index eaf20f834..000000000
--- a/qemu/tests/qapi-schema/type-bypass.out
+++ /dev/null
@@ -1,3 +0,0 @@
-[OrderedDict([('command', 'unsafe'), ('data', OrderedDict([('arg', '**')])), ('returns', '**'), ('gen', False)])]
-[]
-[]
diff --git a/qemu/tests/qapi-schema/union-bad-branch.err b/qemu/tests/qapi-schema/union-bad-branch.err
deleted file mode 100644
index 882273556..000000000
--- a/qemu/tests/qapi-schema/union-bad-branch.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/union-bad-branch.json:6: Union 'MyUnion' member 'ONE' clashes with 'one'
diff --git a/qemu/tests/qapi-schema/union-bad-branch.json b/qemu/tests/qapi-schema/union-bad-branch.json
deleted file mode 100644
index 913aa38bc..000000000
--- a/qemu/tests/qapi-schema/union-bad-branch.json
+++ /dev/null
@@ -1,8 +0,0 @@
-# we reject normal unions where branches would collide in C
-{ 'struct': 'One',
- 'data': { 'string': 'str' } }
-{ 'struct': 'Two',
- 'data': { 'number': 'int' } }
-{ 'union': 'MyUnion',
- 'data': { 'one': 'One',
- 'ONE': 'Two' } }
diff --git a/qemu/tests/qapi-schema/union-base-no-discriminator.err b/qemu/tests/qapi-schema/union-base-no-discriminator.err
index fc8b79c45..8b7a24260 100644
--- a/qemu/tests/qapi-schema/union-base-no-discriminator.err
+++ b/qemu/tests/qapi-schema/union-base-no-discriminator.err
@@ -1 +1 @@
-tests/qapi-schema/union-base-no-discriminator.json:11: Union 'TestUnion' requires a discriminator to go along with base
+tests/qapi-schema/union-base-no-discriminator.json:11: Simple union 'TestUnion' must not have a base
diff --git a/qemu/tests/qapi-schema/union-branch-case.err b/qemu/tests/qapi-schema/union-branch-case.err
new file mode 100644
index 000000000..11521901d
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-branch-case.err
@@ -0,0 +1 @@
+tests/qapi-schema/union-branch-case.json:2: 'Branch' (branch of NoWayThisWillGetWhitelisted) should not use uppercase
diff --git a/qemu/tests/qapi-schema/union-branch-case.exit b/qemu/tests/qapi-schema/union-branch-case.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-branch-case.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/union-branch-case.json b/qemu/tests/qapi-schema/union-branch-case.json
new file mode 100644
index 000000000..e6565dc3b
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-branch-case.json
@@ -0,0 +1,2 @@
+# Branch names should be 'lower-case' unless the union is whitelisted
+{ 'union': 'NoWayThisWillGetWhitelisted', 'data': { 'Branch': 'int' } }
diff --git a/qemu/tests/qapi-schema/union-branch-case.out b/qemu/tests/qapi-schema/union-branch-case.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-branch-case.out
diff --git a/qemu/tests/qapi-schema/union-clash-branches.err b/qemu/tests/qapi-schema/union-clash-branches.err
new file mode 100644
index 000000000..e5b21135b
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-clash-branches.err
@@ -0,0 +1 @@
+tests/qapi-schema/union-clash-branches.json:4: 'a_b' (branch of TestUnion) collides with 'a-b' (branch of TestUnion)
diff --git a/qemu/tests/qapi-schema/union-clash-branches.exit b/qemu/tests/qapi-schema/union-clash-branches.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-clash-branches.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/union-clash-branches.json b/qemu/tests/qapi-schema/union-clash-branches.json
new file mode 100644
index 000000000..3bece8c94
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-clash-branches.json
@@ -0,0 +1,5 @@
+# Union branch name collision
+# Reject a union that would result in a collision in generated C names (this
+# would try to generate two members 'a_b').
+{ 'union': 'TestUnion',
+ 'data': { 'a-b': 'int', 'a_b': 'str' } }
diff --git a/qemu/tests/qapi-schema/union-clash-branches.out b/qemu/tests/qapi-schema/union-clash-branches.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-clash-branches.out
diff --git a/qemu/tests/qapi-schema/union-empty.err b/qemu/tests/qapi-schema/union-empty.err
new file mode 100644
index 000000000..12c20221b
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-empty.err
@@ -0,0 +1 @@
+tests/qapi-schema/union-empty.json:2: Union 'Union' cannot have empty 'data'
diff --git a/qemu/tests/qapi-schema/union-empty.exit b/qemu/tests/qapi-schema/union-empty.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-empty.exit
@@ -0,0 +1 @@
+1
diff --git a/qemu/tests/qapi-schema/union-empty.json b/qemu/tests/qapi-schema/union-empty.json
new file mode 100644
index 000000000..1f0b13ca2
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-empty.json
@@ -0,0 +1,2 @@
+# unions cannot be empty
+{ 'union': 'Union', 'data': { } }
diff --git a/qemu/tests/qapi-schema/union-empty.out b/qemu/tests/qapi-schema/union-empty.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/qemu/tests/qapi-schema/union-empty.out
diff --git a/qemu/tests/qapi-schema/union-invalid-base.err b/qemu/tests/qapi-schema/union-invalid-base.err
index 9f637963e..03d7b97a9 100644
--- a/qemu/tests/qapi-schema/union-invalid-base.err
+++ b/qemu/tests/qapi-schema/union-invalid-base.err
@@ -1 +1 @@
-tests/qapi-schema/union-invalid-base.json:8: Base 'int' is not a valid struct
+tests/qapi-schema/union-invalid-base.json:8: 'base' for union 'TestUnion' cannot use built-in type 'int'
diff --git a/qemu/tests/qapi-schema/union-max.err b/qemu/tests/qapi-schema/union-max.err
deleted file mode 100644
index 55ce4399d..000000000
--- a/qemu/tests/qapi-schema/union-max.err
+++ /dev/null
@@ -1 +0,0 @@
-tests/qapi-schema/union-max.json:2: Union 'Union' member 'max' clashes with '(automatic)'
diff --git a/qemu/tests/qapi-schema/union-max.json b/qemu/tests/qapi-schema/union-max.json
deleted file mode 100644
index d6ad98699..000000000
--- a/qemu/tests/qapi-schema/union-max.json
+++ /dev/null
@@ -1,3 +0,0 @@
-# we reject 'max' branch in a union, for collision with C enum
-{ 'union': 'Union',
- 'data': { 'max': 'int' } }
diff --git a/qemu/tests/qemu-iotests/001 b/qemu/tests/qemu-iotests/001
index 4e1646941..ffd14e2ce 100755
--- a/qemu/tests/qemu-iotests/001
+++ b/qemu/tests/qemu-iotests/001
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/002 b/qemu/tests/qemu-iotests/002
index 6a865aac7..d4f8e91b9 100755
--- a/qemu/tests/qemu-iotests/002
+++ b/qemu/tests/qemu-iotests/002
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/003 b/qemu/tests/qemu-iotests/003
index 98638d4ce..19889b9fc 100755
--- a/qemu/tests/qemu-iotests/003
+++ b/qemu/tests/qemu-iotests/003
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/004 b/qemu/tests/qemu-iotests/004
index 2ad77ed51..67e1beb20 100755
--- a/qemu/tests/qemu-iotests/004
+++ b/qemu/tests/qemu-iotests/004
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/005 b/qemu/tests/qemu-iotests/005
index ba1236dfb..444737751 100755
--- a/qemu/tests/qemu-iotests/005
+++ b/qemu/tests/qemu-iotests/005
@@ -28,7 +28,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/007 b/qemu/tests/qemu-iotests/007
index 7b5aff59b..fa543eeb7 100755
--- a/qemu/tests/qemu-iotests/007
+++ b/qemu/tests/qemu-iotests/007
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/008 b/qemu/tests/qemu-iotests/008
index 2d28efd42..8e89d74fe 100755
--- a/qemu/tests/qemu-iotests/008
+++ b/qemu/tests/qemu-iotests/008
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/009 b/qemu/tests/qemu-iotests/009
index 57a43f5a1..16e4475ca 100755
--- a/qemu/tests/qemu-iotests/009
+++ b/qemu/tests/qemu-iotests/009
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/010 b/qemu/tests/qemu-iotests/010
index 896a0058f..151dac238 100755
--- a/qemu/tests/qemu-iotests/010
+++ b/qemu/tests/qemu-iotests/010
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/011 b/qemu/tests/qemu-iotests/011
index 1c5158af4..f8d044ec8 100755
--- a/qemu/tests/qemu-iotests/011
+++ b/qemu/tests/qemu-iotests/011
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/012 b/qemu/tests/qemu-iotests/012
index 7c5b6892d..d1d3f2209 100755
--- a/qemu/tests/qemu-iotests/012
+++ b/qemu/tests/qemu-iotests/012
@@ -27,7 +27,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/013 b/qemu/tests/qemu-iotests/013
index ea3cab91d..d013f87da 100755
--- a/qemu/tests/qemu-iotests/013
+++ b/qemu/tests/qemu-iotests/013
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/014 b/qemu/tests/qemu-iotests/014
index b23c2db9b..2ea79e8c8 100755
--- a/qemu/tests/qemu-iotests/014
+++ b/qemu/tests/qemu-iotests/014
@@ -27,7 +27,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/015 b/qemu/tests/qemu-iotests/015
index 6f2609524..aaf9c3f41 100755
--- a/qemu/tests/qemu-iotests/015
+++ b/qemu/tests/qemu-iotests/015
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/017 b/qemu/tests/qemu-iotests/017
index 3af3cdfbc..e3f9e7596 100755
--- a/qemu/tests/qemu-iotests/017
+++ b/qemu/tests/qemu-iotests/017
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/017.out b/qemu/tests/qemu-iotests/017.out
index 7c409fc5b..8fc924194 100644
--- a/qemu/tests/qemu-iotests/017.out
+++ b/qemu/tests/qemu-iotests/017.out
@@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4295032832
No errors were found on the image.
Creating test image with backing file
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base
Filling test image
=== IO: pattern 1
diff --git a/qemu/tests/qemu-iotests/018 b/qemu/tests/qemu-iotests/018
index d8a7d435a..1d39d35c4 100755
--- a/qemu/tests/qemu-iotests/018
+++ b/qemu/tests/qemu-iotests/018
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -66,8 +65,8 @@ _check_test_img
echo "Creating test image with backing file"
echo
-TEST_IMG=$TEST_IMG_SAVE
-_make_test_img -b "$TEST_IMG.base" 6G
+TEST_IMG="$TEST_IMG_SAVE.orig"
+_make_test_img -b "$TEST_IMG_SAVE.base" 6G
echo "Filling test image"
echo
@@ -81,8 +80,8 @@ for offset in $TEST_OFFSETS; do
done
_check_test_img
-mv "$TEST_IMG" "$TEST_IMG.orig"
-$QEMU_IMG convert -O $IMGFMT "$TEST_IMG.orig" "$TEST_IMG"
+TEST_IMG="$TEST_IMG_SAVE"
+$QEMU_IMG convert -f $IMGFMT -O $IMGFMT "$TEST_IMG.orig" "$TEST_IMG"
echo "Reading"
echo
diff --git a/qemu/tests/qemu-iotests/018.out b/qemu/tests/qemu-iotests/018.out
index 39a6011d2..5df966727 100644
--- a/qemu/tests/qemu-iotests/018.out
+++ b/qemu/tests/qemu-iotests/018.out
@@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4295032832
No errors were found on the image.
Creating test image with backing file
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base
Filling test image
=== IO: pattern 1
diff --git a/qemu/tests/qemu-iotests/019 b/qemu/tests/qemu-iotests/019
index f5ecbf545..24a789a25 100755
--- a/qemu/tests/qemu-iotests/019
+++ b/qemu/tests/qemu-iotests/019
@@ -27,7 +27,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -54,6 +53,9 @@ _unsupported_imgopts "subformat=monolithicFlat" \
TEST_OFFSETS="0 4294967296"
CLUSTER_SIZE=65536
+TEST_IMG_SAVE="$TEST_IMG"
+TEST_IMG="$TEST_IMG.base"
+
_make_test_img 6G
echo "Filling base image"
@@ -71,8 +73,8 @@ _check_test_img
echo "Creating test image with backing file"
echo
-mv "$TEST_IMG" "$TEST_IMG.base"
-_make_test_img -b "$TEST_IMG.base" 6G
+TEST_IMG="$TEST_IMG_SAVE.orig"
+_make_test_img -b "$TEST_IMG_SAVE.base" 6G
echo "Filling test image"
echo
@@ -86,9 +88,7 @@ for offset in $TEST_OFFSETS; do
done
_check_test_img
-mv "$TEST_IMG" "$TEST_IMG.orig"
-
-
+TEST_IMG="$TEST_IMG_SAVE"
# Test the conversion twice: One test with the old-style -B option and another
# one with -o backing_file
@@ -98,7 +98,7 @@ for backing_option in "-B " "-o backing_file="; do
echo
echo Testing conversion with $backing_option"$TEST_IMG.base" | _filter_testdir | _filter_imgfmt
echo
- $QEMU_IMG convert -O $IMGFMT $backing_option"$TEST_IMG.base" "$TEST_IMG.orig" "$TEST_IMG"
+ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT $backing_option"$TEST_IMG.base" "$TEST_IMG.orig" "$TEST_IMG"
echo "Checking if backing clusters are allocated when they shouldn't"
echo
diff --git a/qemu/tests/qemu-iotests/019.out b/qemu/tests/qemu-iotests/019.out
index 4695b972d..012426497 100644
--- a/qemu/tests/qemu-iotests/019.out
+++ b/qemu/tests/qemu-iotests/019.out
@@ -1,5 +1,5 @@
QA output created by 019
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=6442450944
Filling base image
=== IO: pattern 42
@@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4296015872
No errors were found on the image.
Creating test image with backing file
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT.orig', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base
Filling test image
=== IO: pattern 43
diff --git a/qemu/tests/qemu-iotests/020 b/qemu/tests/qemu-iotests/020
index 2f258dc6e..9c4a68c97 100755
--- a/qemu/tests/qemu-iotests/020
+++ b/qemu/tests/qemu-iotests/020
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -56,6 +55,9 @@ fi
TEST_OFFSETS="0 4294967296"
+TEST_IMG_SAVE="$TEST_IMG"
+TEST_IMG="$TEST_IMG.base"
+
_make_test_img 6G
echo "Filling base image"
@@ -73,7 +75,7 @@ _check_test_img
echo "Creating test image with backing file"
echo
-mv "$TEST_IMG" "$TEST_IMG.base"
+TEST_IMG="$TEST_IMG_SAVE"
_make_test_img -b "$TEST_IMG.base" 6G
echo "Filling test image"
@@ -89,7 +91,7 @@ done
_check_test_img
$QEMU_IMG commit "$TEST_IMG"
-mv "$TEST_IMG.base" "$TEST_IMG"
+TEST_IMG="$TEST_IMG.base"
echo "Reading from the backing file"
echo
diff --git a/qemu/tests/qemu-iotests/020.out b/qemu/tests/qemu-iotests/020.out
index 71aab1c74..42f6c1b15 100644
--- a/qemu/tests/qemu-iotests/020.out
+++ b/qemu/tests/qemu-iotests/020.out
@@ -1,5 +1,5 @@
QA output created by 020
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=6442450944
Filling base image
=== IO: pattern 0
@@ -269,7 +269,7 @@ wrote 65536/65536 bytes at offset 4295032832
No errors were found on the image.
Creating test image with backing file
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base
Filling test image
=== IO: pattern 1
diff --git a/qemu/tests/qemu-iotests/021 b/qemu/tests/qemu-iotests/021
index 1c69024cc..11e8ed718 100755
--- a/qemu/tests/qemu-iotests/021
+++ b/qemu/tests/qemu-iotests/021
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/022 b/qemu/tests/qemu-iotests/022
index d35b8162b..2452a9f86 100755
--- a/qemu/tests/qemu-iotests/022
+++ b/qemu/tests/qemu-iotests/022
@@ -27,7 +27,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/023 b/qemu/tests/qemu-iotests/023
index 9ad06b990..497ae1ed1 100755
--- a/qemu/tests/qemu-iotests/023
+++ b/qemu/tests/qemu-iotests/023
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/024 b/qemu/tests/qemu-iotests/024
index 9bf99e198..e0d77ce2f 100755
--- a/qemu/tests/qemu-iotests/024
+++ b/qemu/tests/qemu-iotests/024
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -60,16 +59,22 @@ CLUSTER_SIZE=65536
echo "Creating backing file"
echo
+TEST_IMG_SAVE="$TEST_IMG"
+TEST_IMG="$TEST_IMG.base_old"
+
_make_test_img 1G
io_pattern writev 0 $CLUSTER_SIZE $((2 * CLUSTER_SIZE)) 8 0x11
-mv "$TEST_IMG" "$TEST_IMG.base_old"
+
+TEST_IMG="$TEST_IMG_SAVE.base_new"
echo "Creating new backing file"
echo
_make_test_img 1G
io_pattern writev 0 $((2 * CLUSTER_SIZE)) $((4 * CLUSTER_SIZE)) 4 0x22
-mv "$TEST_IMG" "$TEST_IMG.base_new"
+
+
+TEST_IMG="$TEST_IMG_SAVE"
echo "Creating COW image"
echo
diff --git a/qemu/tests/qemu-iotests/024.out b/qemu/tests/qemu-iotests/024.out
index 521d46942..33cfaf5cf 100644
--- a/qemu/tests/qemu-iotests/024.out
+++ b/qemu/tests/qemu-iotests/024.out
@@ -1,7 +1,7 @@
QA output created by 024
Creating backing file
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+Formatting 'TEST_DIR/t.IMGFMT.base_old', fmt=IMGFMT size=1073741824
=== IO: pattern 0x11
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -21,7 +21,7 @@ wrote 65536/65536 bytes at offset 917504
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Creating new backing file
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+Formatting 'TEST_DIR/t.IMGFMT.base_new', fmt=IMGFMT size=1073741824
=== IO: pattern 0x22
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -33,7 +33,7 @@ wrote 131072/131072 bytes at offset 786432
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Creating COW image
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file='TEST_DIR/t.IMGFMT.base_old'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824 backing_file=TEST_DIR/t.IMGFMT.base_old
=== IO: pattern 0x33
wrote 262144/262144 bytes at offset 0
256 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/qemu/tests/qemu-iotests/025 b/qemu/tests/qemu-iotests/025
index 467a4b709..c41370f3b 100755
--- a/qemu/tests/qemu-iotests/025
+++ b/qemu/tests/qemu-iotests/025
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/026 b/qemu/tests/qemu-iotests/026
index 0fc3244c7..f5a7f02b2 100755
--- a/qemu/tests/qemu-iotests/026
+++ b/qemu/tests/qemu-iotests/026
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -66,7 +65,7 @@ for event in \
\
l2_load \
l2_update \
- l2_alloc.write \
+ l2_alloc_write \
\
write_aio \
\
@@ -126,11 +125,11 @@ CLUSTER_SIZE=512
for event in \
- refblock_alloc.hookup \
- refblock_alloc.write \
- refblock_alloc.write_blocks \
- refblock_alloc.write_table \
- refblock_alloc.switch_table \
+ refblock_alloc_hookup \
+ refblock_alloc_write \
+ refblock_alloc_write_blocks \
+ refblock_alloc_write_table \
+ refblock_alloc_switch_table \
do
@@ -170,9 +169,9 @@ CLUSTER_SIZE=1024
for event in \
- l1_grow.alloc_table \
- l1_grow.write_table \
- l1_grow.activate_table \
+ l1_grow_alloc_table \
+ l1_grow_write_table \
+ l1_grow_activate_table \
do
diff --git a/qemu/tests/qemu-iotests/026.out b/qemu/tests/qemu-iotests/026.out
index 5e964fb5a..d84d82c11 100644
--- a/qemu/tests/qemu-iotests/026.out
+++ b/qemu/tests/qemu-iotests/026.out
@@ -195,24 +195,24 @@ write failed: No space left on device
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 5; imm: off; once: on; write
+Event: l2_alloc_write; errno: 5; imm: off; once: on; write
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 5; imm: off; once: on; write -b
+Event: l2_alloc_write; errno: 5; imm: off; once: on; write -b
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 5; imm: off; once: off; write
+Event: l2_alloc_write; errno: 5; imm: off; once: off; write
Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 5; imm: off; once: off; write -b
+Event: l2_alloc_write; errno: 5; imm: off; once: off; write -b
Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
@@ -221,24 +221,24 @@ write failed: Input/output error
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 28; imm: off; once: on; write
+Event: l2_alloc_write; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 28; imm: off; once: on; write -b
+Event: l2_alloc_write; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 28; imm: off; once: off; write
+Event: l2_alloc_write; errno: 28; imm: off; once: off; write
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 28; imm: off; once: off; write -b
+Event: l2_alloc_write; errno: 28; imm: off; once: off; write -b
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -490,17 +490,17 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.hookup; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_hookup; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.hookup; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_hookup; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -509,7 +509,7 @@ write failed: No space left on device
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write -b
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -518,41 +518,41 @@ write failed: No space left on device
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_write; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_write; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_write; errno: 28; imm: off; once: off; write
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_write; errno: 28; imm: off; once: off; write -b
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -561,7 +561,7 @@ write failed: No space left on device
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -570,17 +570,17 @@ write failed: No space left on device
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_table; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_write_table; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_table; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_write_table; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -589,7 +589,7 @@ write failed: No space left on device
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -598,17 +598,17 @@ write failed: No space left on device
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.switch_table; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_switch_table; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.switch_table; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_switch_table; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -617,7 +617,7 @@ write failed: No space left on device
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write -b
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
@@ -629,60 +629,60 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.alloc_table; errno: 5; imm: off; once: on
+Event: l1_grow_alloc_table; errno: 5; imm: off; once: on
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.alloc_table; errno: 5; imm: off; once: off
+Event: l1_grow_alloc_table; errno: 5; imm: off; once: off
Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.alloc_table; errno: 28; imm: off; once: on
+Event: l1_grow_alloc_table; errno: 28; imm: off; once: on
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.alloc_table; errno: 28; imm: off; once: off
+Event: l1_grow_alloc_table; errno: 28; imm: off; once: off
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.write_table; errno: 5; imm: off; once: on
+Event: l1_grow_write_table; errno: 5; imm: off; once: on
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.write_table; errno: 5; imm: off; once: off
+Event: l1_grow_write_table; errno: 5; imm: off; once: off
Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.write_table; errno: 28; imm: off; once: on
+Event: l1_grow_write_table; errno: 28; imm: off; once: on
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.write_table; errno: 28; imm: off; once: off
+Event: l1_grow_write_table; errno: 28; imm: off; once: off
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.activate_table; errno: 5; imm: off; once: on
+Event: l1_grow_activate_table; errno: 5; imm: off; once: on
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.activate_table; errno: 5; imm: off; once: off
+Event: l1_grow_activate_table; errno: 5; imm: off; once: off
Failed to flush the L2 table cache: Input/output error
Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
@@ -691,12 +691,12 @@ write failed: Input/output error
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.activate_table; errno: 28; imm: off; once: on
+Event: l1_grow_activate_table; errno: 28; imm: off; once: on
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.activate_table; errno: 28; imm: off; once: off
+Event: l1_grow_activate_table; errno: 28; imm: off; once: off
Failed to flush the L2 table cache: No space left on device
Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
diff --git a/qemu/tests/qemu-iotests/026.out.nocache b/qemu/tests/qemu-iotests/026.out.nocache
index c9d242e9e..9c2c8a948 100644
--- a/qemu/tests/qemu-iotests/026.out.nocache
+++ b/qemu/tests/qemu-iotests/026.out.nocache
@@ -14,6 +14,8 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 5; imm: off; once: off; write
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
1 leaked clusters were found on the image.
@@ -21,6 +23,8 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 5; imm: off; once: off; write -b
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
1 leaked clusters were found on the image.
@@ -38,6 +42,8 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
1 leaked clusters were found on the image.
@@ -45,6 +51,8 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l1_update; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
1 leaked clusters were found on the image.
@@ -70,7 +78,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 5; imm: off; once: off; write
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
read failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -78,7 +90,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 5; imm: off; once: off; write -b
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
read failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -102,7 +118,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 28; imm: off; once: off; write
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
read failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -110,7 +130,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_load; errno: 28; imm: off; once: off; write -b
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
read failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -118,20 +142,18 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_update; errno: 5; imm: off; once: on; write
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-127 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+No errors were found on the image.
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_update; errno: 5; imm: off; once: on; write -b
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-127 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+No errors were found on the image.
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_update; errno: 5; imm: off; once: off; write
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -140,6 +162,8 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_update; errno: 5; imm: off; once: off; write -b
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -150,20 +174,18 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_update; errno: 28; imm: off; once: on; write
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-127 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+No errors were found on the image.
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_update; errno: 28; imm: off; once: on; write -b
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-
-127 leaked clusters were found on the image.
-This means waste of disk space, but no harm to data.
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+No errors were found on the image.
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_update; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -172,6 +194,8 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: l2_update; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -179,44 +203,52 @@ wrote 131072/131072 bytes at offset 0
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 5; imm: off; once: on; write
+Event: l2_alloc_write; errno: 5; imm: off; once: on; write
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 5; imm: off; once: on; write -b
+Event: l2_alloc_write; errno: 5; imm: off; once: on; write -b
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 5; imm: off; once: off; write
+Event: l2_alloc_write; errno: 5; imm: off; once: off; write
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 5; imm: off; once: off; write -b
+Event: l2_alloc_write; errno: 5; imm: off; once: off; write -b
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
1 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 28; imm: off; once: on; write
+Event: l2_alloc_write; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 28; imm: off; once: on; write -b
+Event: l2_alloc_write; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 28; imm: off; once: off; write
+Event: l2_alloc_write; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l2_alloc.write; errno: 28; imm: off; once: off; write -b
+Event: l2_alloc_write; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
1 leaked clusters were found on the image.
@@ -234,11 +266,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: write_aio; errno: 5; imm: off; once: off; write
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: write_aio; errno: 5; imm: off; once: off; write -b
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -254,11 +290,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: write_aio; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: write_aio; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -274,11 +314,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 5; imm: off; once: off; write
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 5; imm: off; once: off; write -b
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -294,11 +338,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_load; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -314,11 +362,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 5; imm: off; once: off; write
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 5; imm: off; once: off; write -b
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -334,11 +386,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_update_part; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -354,11 +410,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 5; imm: off; once: off; write
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 5; imm: off; once: off; write -b
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -374,11 +434,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: refblock_alloc; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -394,11 +458,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 5; imm: off; once: off; write
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 5; imm: off; once: off; write -b
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
@@ -414,11 +482,15 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
Event: cluster_alloc; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
@@ -426,116 +498,136 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.hookup; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_hookup; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.hookup; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_hookup; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
55 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.hookup; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_hookup; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
251 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_write; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_write; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_write; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_write; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
-10 leaked clusters were found on the image.
+11 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_blocks; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_write_blocks; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
23 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_table; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_write_table; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_table; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_write_table; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
-10 leaked clusters were found on the image.
+11 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.write_table; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_write_table; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
23 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.switch_table; errno: 28; imm: off; once: on; write
+Event: refblock_alloc_switch_table; errno: 28; imm: off; once: on; write
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.switch_table; errno: 28; imm: off; once: on; write -b
+Event: refblock_alloc_switch_table; errno: 28; imm: off; once: on; write -b
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write
+Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
-10 leaked clusters were found on the image.
+11 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: refblock_alloc.switch_table; errno: 28; imm: off; once: off; write -b
+Event: refblock_alloc_switch_table; errno: 28; imm: off; once: off; write -b
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
23 leaked clusters were found on the image.
@@ -545,64 +637,76 @@ This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.alloc_table; errno: 5; imm: off; once: on
+Event: l1_grow_alloc_table; errno: 5; imm: off; once: on
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.alloc_table; errno: 5; imm: off; once: off
+Event: l1_grow_alloc_table; errno: 5; imm: off; once: off
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.alloc_table; errno: 28; imm: off; once: on
+Event: l1_grow_alloc_table; errno: 28; imm: off; once: on
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.alloc_table; errno: 28; imm: off; once: off
+Event: l1_grow_alloc_table; errno: 28; imm: off; once: off
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.write_table; errno: 5; imm: off; once: on
+Event: l1_grow_write_table; errno: 5; imm: off; once: on
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.write_table; errno: 5; imm: off; once: off
+Event: l1_grow_write_table; errno: 5; imm: off; once: off
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.write_table; errno: 28; imm: off; once: on
+Event: l1_grow_write_table; errno: 28; imm: off; once: on
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.write_table; errno: 28; imm: off; once: off
+Event: l1_grow_write_table; errno: 28; imm: off; once: off
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.activate_table; errno: 5; imm: off; once: on
+Event: l1_grow_activate_table; errno: 5; imm: off; once: on
write failed: Input/output error
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.activate_table; errno: 5; imm: off; once: off
+Event: l1_grow_activate_table; errno: 5; imm: off; once: off
+Failed to flush the L2 table cache: Input/output error
+Failed to flush the refcount block cache: Input/output error
write failed: Input/output error
96 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.activate_table; errno: 28; imm: off; once: on
+Event: l1_grow_activate_table; errno: 28; imm: off; once: on
write failed: No space left on device
No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
-Event: l1_grow.activate_table; errno: 28; imm: off; once: off
+Event: l1_grow_activate_table; errno: 28; imm: off; once: off
+Failed to flush the L2 table cache: No space left on device
+Failed to flush the refcount block cache: No space left on device
write failed: No space left on device
96 leaked clusters were found on the image.
diff --git a/qemu/tests/qemu-iotests/027 b/qemu/tests/qemu-iotests/027
index 3fa81b83b..08593da77 100755
--- a/qemu/tests/qemu-iotests/027
+++ b/qemu/tests/qemu-iotests/027
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/028 b/qemu/tests/qemu-iotests/028
index a1f4423d4..7783e57c7 100755
--- a/qemu/tests/qemu-iotests/028
+++ b/qemu/tests/qemu-iotests/028
@@ -28,7 +28,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -60,6 +59,9 @@ base_size=$(( image_size - 1024 * 1024 * 1024 ))
offset=$(( base_size - 32 * 1024 ))
+TEST_IMG_SAVE="$TEST_IMG"
+TEST_IMG="$TEST_IMG.base"
+
_make_test_img $base_size
echo "Filling base image"
@@ -73,7 +75,7 @@ _check_test_img
echo "Creating test image with backing file"
echo
-mv "$TEST_IMG" "$TEST_IMG.base"
+TEST_IMG="$TEST_IMG_SAVE"
_make_test_img -b "$TEST_IMG.base" $image_size
echo "Filling test image"
@@ -111,10 +113,12 @@ h=$QEMU_HANDLE
QEMU_COMM_TIMEOUT=1
# Silence output since it contains the disk image path and QEMU's readline
-# character echoing makes it very hard to filter the output
+# character echoing makes it very hard to filter the output. Plus, there
+# is no telling how many times the command will repeat before succeeding.
_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)" >/dev/null
_send_qemu_cmd $h "" "Formatting" | _filter_img_create
-qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
+qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs" >/dev/null
+_send_qemu_cmd $h "info block-jobs" "No active jobs"
_send_qemu_cmd $h 'quit' ""
# Base image sectors
diff --git a/qemu/tests/qemu-iotests/028.out b/qemu/tests/qemu-iotests/028.out
index 5db167ce7..acd2870ba 100644
--- a/qemu/tests/qemu-iotests/028.out
+++ b/qemu/tests/qemu-iotests/028.out
@@ -1,5 +1,5 @@
QA output created by 028
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=3221227008
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=3221227008
Filling base image
=== IO: pattern 195
@@ -70,7 +70,7 @@ wrote 512/512 bytes at offset 3221225984
No errors were found on the image.
Creating test image with backing file
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294968832 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294968832 backing_file=TEST_DIR/t.IMGFMT.base
Filling test image
=== IO: pattern 196
@@ -468,11 +468,8 @@ No errors were found on the image.
block-backup
-Formatting 'TEST_DIR/t.IMGFMT.copy', fmt=IMGFMT size=4294968832 backing_file='TEST_DIR/t.IMGFMT.base' backing_fmt='IMGFMT'
-(qemu)
+Formatting 'TEST_DIR/t.IMGFMT.copy', fmt=IMGFMT size=4294968832 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=IMGFMT
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block-info block-jinfo block-joinfo block-jobinfo block-jobs
-Type backup, device disk: Completed 0 of 4294968832 bytes, speed limit 0 bytes/s
-iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block-info block-jinfo block-joinfo block-jobinfo block-jobs
No active jobs
=== IO: pattern 195
read 512/512 bytes at offset 3221194240
diff --git a/qemu/tests/qemu-iotests/029 b/qemu/tests/qemu-iotests/029
index b9cd826c7..e639ac0dd 100755
--- a/qemu/tests/qemu-iotests/029
+++ b/qemu/tests/qemu-iotests/029
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/030 b/qemu/tests/qemu-iotests/030
index 952a524ec..3ac2443e5 100755
--- a/qemu/tests/qemu-iotests/030
+++ b/qemu/tests/qemu-iotests/030
@@ -35,6 +35,7 @@ class TestSingleDrive(iotests.QMPTestCase):
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, mid_img)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % mid_img, test_img)
qemu_io('-f', 'raw', '-c', 'write -P 0x1 0 512', backing_img)
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0x1 524288 512', mid_img)
self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
self.vm.launch()
@@ -90,9 +91,13 @@ class TestSingleDrive(iotests.QMPTestCase):
qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
'image file map does not match backing file after streaming')
- def test_stream_partial(self):
+ def test_stream_no_op(self):
self.assert_no_active_block_jobs()
+ # The image map is empty before the operation
+ empty_map = qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img)
+
+ # This is a no-op: no data should ever be copied from the base image
result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
self.assert_qmp(result, 'return', {})
@@ -101,6 +106,20 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
self.vm.shutdown()
+ self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
+ empty_map, 'image file map changed after a no-op')
+
+ def test_stream_partial(self):
+ self.assert_no_active_block_jobs()
+
+ result = self.vm.qmp('block-stream', device='drive0', base=backing_img)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_until_completed()
+
+ self.assert_no_active_block_jobs()
+ self.vm.shutdown()
+
self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img),
qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
'image file map does not match backing file after streaming')
@@ -245,6 +264,7 @@ class TestEIO(TestErrors):
while not completed:
for event in self.vm.get_qmp_events(wait=True):
if event['event'] == 'BLOCK_JOB_ERROR':
+ error = True
self.assert_qmp(event, 'data/device', 'drive0')
self.assert_qmp(event, 'data/operation', 'read')
@@ -257,9 +277,11 @@ class TestEIO(TestErrors):
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('query-block-jobs')
+ if result == {'return': []}:
+ # Race; likely already finished. Check.
+ continue
self.assert_qmp(result, 'return[0]/paused', False)
self.assert_qmp(result, 'return[0]/io-status', 'ok')
- error = True
elif event['event'] == 'BLOCK_JOB_COMPLETED':
self.assertTrue(error, 'job completed unexpectedly')
self.assert_qmp(event, 'data/type', 'stream')
diff --git a/qemu/tests/qemu-iotests/030.out b/qemu/tests/qemu-iotests/030.out
index fa16b5cce..6323079e0 100644
--- a/qemu/tests/qemu-iotests/030.out
+++ b/qemu/tests/qemu-iotests/030.out
@@ -1,5 +1,5 @@
-.............
+..............
----------------------------------------------------------------------
-Ran 13 tests
+Ran 14 tests
OK
diff --git a/qemu/tests/qemu-iotests/031 b/qemu/tests/qemu-iotests/031
index 2a77ba8cb..1e08abc5e 100755
--- a/qemu/tests/qemu-iotests/031
+++ b/qemu/tests/qemu-iotests/031
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/031.out b/qemu/tests/qemu-iotests/031.out
index fce3ce098..7f5050b81 100644
--- a/qemu/tests/qemu-iotests/031.out
+++ b/qemu/tests/qemu-iotests/031.out
@@ -53,11 +53,6 @@ refcount_order 4
header_length 72
Header extension:
-magic 0x6803f857
-length 144
-data <binary>
-
-Header extension:
magic 0x12345678
length 31
data 'This is a test header extension'
@@ -68,7 +63,7 @@ No errors were found on the image.
magic 0x514649fb
version 2
-backing_file_offset 0x128
+backing_file_offset 0x90
backing_file_size 0x17
cluster_bits 16
size 67108864
@@ -91,11 +86,6 @@ length 11
data 'host_device'
Header extension:
-magic 0x6803f857
-length 144
-data <binary>
-
-Header extension:
magic 0x12345678
length 31
data 'This is a test header extension'
@@ -126,6 +116,11 @@ refcount_order 4
header_length 104
Header extension:
+magic 0x6803f857
+length 144
+data <binary>
+
+Header extension:
magic 0x12345678
length 31
data 'This is a test header extension'
diff --git a/qemu/tests/qemu-iotests/032 b/qemu/tests/qemu-iotests/032
index b1ba5c321..24bcb52fc 100755
--- a/qemu/tests/qemu-iotests/032
+++ b/qemu/tests/qemu-iotests/032
@@ -27,7 +27,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/033 b/qemu/tests/qemu-iotests/033
index a61d8ced1..16edcf2f0 100755
--- a/qemu/tests/qemu-iotests/033
+++ b/qemu/tests/qemu-iotests/033
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -57,12 +56,13 @@ do_test()
} | $QEMU_IO
}
+for write_zero_cmd in "write -z" "aio_write -z"; do
for align in 512 4k; do
echo
echo "== preparing image =="
do_test $align "write -P 0xa 0x200 0x400" "$TEST_IMG" | _filter_qemu_io
do_test $align "write -P 0xa 0x20000 0x600" "$TEST_IMG" | _filter_qemu_io
- do_test $align "write -z 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io
+ do_test $align "$write_zero_cmd 0x400 0x20000" "$TEST_IMG" | _filter_qemu_io
echo
echo "== verifying patterns (1) =="
@@ -73,7 +73,7 @@ for align in 512 4k; do
echo
echo "== rewriting zeroes =="
do_test $align "write -P 0xb 0x10000 0x10000" "$TEST_IMG" | _filter_qemu_io
- do_test $align "write -z 0x10000 0x10000" "$TEST_IMG" | _filter_qemu_io
+ do_test $align "$write_zero_cmd 0x10000 0x10000" "$TEST_IMG" | _filter_qemu_io
echo
echo "== verifying patterns (2) =="
@@ -82,7 +82,7 @@ for align in 512 4k; do
echo
echo "== rewriting unaligned zeroes =="
do_test $align "write -P 0xb 0x0 0x1000" "$TEST_IMG" | _filter_qemu_io
- do_test $align "write -z 0x200 0x200" "$TEST_IMG" | _filter_qemu_io
+ do_test $align "$write_zero_cmd 0x200 0x200" "$TEST_IMG" | _filter_qemu_io
echo
echo "== verifying patterns (3) =="
@@ -92,6 +92,7 @@ for align in 512 4k; do
echo
done
+done
# success, all done
echo "*** done"
diff --git a/qemu/tests/qemu-iotests/033.out b/qemu/tests/qemu-iotests/033.out
index c3d18aa45..95929eff7 100644
--- a/qemu/tests/qemu-iotests/033.out
+++ b/qemu/tests/qemu-iotests/033.out
@@ -82,4 +82,86 @@ read 512/512 bytes at offset 512
read 3072/3072 bytes at offset 1024
3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== preparing image ==
+wrote 1024/1024 bytes at offset 512
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1536/1536 bytes at offset 131072
+1.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 1024
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying patterns (1) ==
+read 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1024
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 132096
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== rewriting zeroes ==
+wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying patterns (2) ==
+read 131072/131072 bytes at offset 1024
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== rewriting unaligned zeroes ==
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying patterns (3) ==
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 3072/3072 bytes at offset 1024
+3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+
+== preparing image ==
+wrote 1024/1024 bytes at offset 512
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1536/1536 bytes at offset 131072
+1.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 1024
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying patterns (1) ==
+read 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 131072/131072 bytes at offset 1024
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 132096
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== rewriting zeroes ==
+wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying patterns (2) ==
+read 131072/131072 bytes at offset 1024
+128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== rewriting unaligned zeroes ==
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verifying patterns (3) ==
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 3072/3072 bytes at offset 1024
+3 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
*** done
diff --git a/qemu/tests/qemu-iotests/034 b/qemu/tests/qemu-iotests/034
index 69c785858..c711cfce9 100755
--- a/qemu/tests/qemu-iotests/034
+++ b/qemu/tests/qemu-iotests/034
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -51,9 +50,13 @@ size=128M
echo
echo "== creating backing file for COW tests =="
+TEST_IMG_SAVE="$TEST_IMG"
+TEST_IMG="$TEST_IMG.base"
+
_make_test_img $size
$QEMU_IO -c "write -P 0x55 0 1M" "$TEST_IMG" | _filter_qemu_io
-mv "$TEST_IMG" "$TEST_IMG.base"
+
+TEST_IMG="$TEST_IMG_SAVE"
_make_test_img -b "$TEST_IMG.base" 6G
diff --git a/qemu/tests/qemu-iotests/034.out b/qemu/tests/qemu-iotests/034.out
index d12daf206..0764ead8b 100644
--- a/qemu/tests/qemu-iotests/034.out
+++ b/qemu/tests/qemu-iotests/034.out
@@ -1,10 +1,10 @@
QA output created by 034
== creating backing file for COW tests ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base
== zero write with backing file ==
wrote 196608/196608 bytes at offset 65536
diff --git a/qemu/tests/qemu-iotests/035 b/qemu/tests/qemu-iotests/035
index ebe9b8c92..efc38e4d4 100755
--- a/qemu/tests/qemu-iotests/035
+++ b/qemu/tests/qemu-iotests/035
@@ -26,7 +26,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/036 b/qemu/tests/qemu-iotests/036
index 392f1ef3e..ce638d607 100755
--- a/qemu/tests/qemu-iotests/036
+++ b/qemu/tests/qemu-iotests/036
@@ -28,7 +28,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -57,6 +56,7 @@ _make_test_img 64M
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
# Without feature table
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
$PYTHON qcow2.py "$TEST_IMG" dump-header
_img_info
@@ -73,6 +73,7 @@ $PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 62
$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
# Without feature table
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
_img_info
# With feature table containing bit 63
diff --git a/qemu/tests/qemu-iotests/036.out b/qemu/tests/qemu-iotests/036.out
index 5616e37b3..9b009b8c1 100644
--- a/qemu/tests/qemu-iotests/036.out
+++ b/qemu/tests/qemu-iotests/036.out
@@ -22,18 +22,18 @@ autoclear_features 0x0
refcount_order 4
header_length 104
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: 8000000000000000
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Unknown incompatible feature: 8000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Test feature
=== Image with multiple incompatible feature bits ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Unknown incompatible feature: e000000000000000
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: 6000000000000000
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: Test feature, Unknown incompatible feature: c000000000000000
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, Unknown incompatible feature: 8000000000000000
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test1, test2, test3
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'image' uses a IMGFMT feature which is not supported by this qemu version: test2, Unknown incompatible feature: a000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Unknown incompatible feature: e000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Test feature, Unknown incompatible feature: 6000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): Test feature, Unknown incompatible feature: c000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): test1, test2, Unknown incompatible feature: 8000000000000000
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): test1, test2, test3
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported IMGFMT feature(s): test2, Unknown incompatible feature: a000000000000000
=== Create image with unknown autoclear feature bit ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
@@ -56,6 +56,11 @@ autoclear_features 0x8000000000000000
refcount_order 4
header_length 104
+Header extension:
+magic 0x6803f857
+length 144
+data <binary>
+
=== Repair image ===
diff --git a/qemu/tests/qemu-iotests/037 b/qemu/tests/qemu-iotests/037
index 9171d8c8a..c476b823d 100755
--- a/qemu/tests/qemu-iotests/037
+++ b/qemu/tests/qemu-iotests/037
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -51,6 +50,9 @@ size=128M
echo
echo "== creating backing file for COW tests =="
+TEST_IMG_SAVE="$TEST_IMG"
+TEST_IMG="$TEST_IMG.base"
+
_make_test_img $size
function backing_io()
@@ -71,7 +73,7 @@ function backing_io()
backing_io 0 256 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
-mv "$TEST_IMG" "$TEST_IMG.base"
+TEST_IMG="$TEST_IMG_SAVE"
_make_test_img -b "$TEST_IMG.base" 6G
diff --git a/qemu/tests/qemu-iotests/037.out b/qemu/tests/qemu-iotests/037.out
index dc40a021a..cd6710c90 100644
--- a/qemu/tests/qemu-iotests/037.out
+++ b/qemu/tests/qemu-iotests/037.out
@@ -1,7 +1,7 @@
QA output created by 037
== creating backing file for COW tests ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 512/512 bytes at offset 512
@@ -514,7 +514,7 @@ wrote 512/512 bytes at offset 130048
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 512/512 bytes at offset 130560
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base
== COW in a single cluster ==
wrote 2048/2048 bytes at offset 0
diff --git a/qemu/tests/qemu-iotests/038 b/qemu/tests/qemu-iotests/038
index cfaf00a78..d99a1501d 100755
--- a/qemu/tests/qemu-iotests/038
+++ b/qemu/tests/qemu-iotests/038
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -48,6 +47,9 @@ size=128M
echo
echo "== creating backing file for COW tests =="
+TEST_IMG_SAVE="$TEST_IMG"
+TEST_IMG="$TEST_IMG.base"
+
_make_test_img $size
function backing_io()
@@ -68,7 +70,7 @@ function backing_io()
backing_io 0 256 write | $QEMU_IO "$TEST_IMG" | _filter_qemu_io
-mv "$TEST_IMG" "$TEST_IMG.base"
+TEST_IMG="$TEST_IMG_SAVE"
_make_test_img -b "$TEST_IMG.base" 6G
diff --git a/qemu/tests/qemu-iotests/038.out b/qemu/tests/qemu-iotests/038.out
index e1a7e9441..0bdfb19fa 100644
--- a/qemu/tests/qemu-iotests/038.out
+++ b/qemu/tests/qemu-iotests/038.out
@@ -1,7 +1,7 @@
QA output created by 038
== creating backing file for COW tests ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 65536
@@ -514,7 +514,7 @@ wrote 65536/65536 bytes at offset 16646144
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 16711680
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base
== Some concurrent requests touching the same cluster ==
wrote 65536/65536 bytes at offset XXX
diff --git a/qemu/tests/qemu-iotests/039 b/qemu/tests/qemu-iotests/039
index 859705f84..1f4833969 100755
--- a/qemu/tests/qemu-iotests/039
+++ b/qemu/tests/qemu-iotests/039
@@ -28,7 +28,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -47,13 +46,6 @@ _supported_os Linux
_default_cache_mode "writethrough"
_supported_cache_modes "writethrough"
-_subshell_exec()
-{
- # Executing crashing commands in a subshell prevents information like the
- # "Killed" line from being lost
- (exec "$@")
-}
-
size=128M
echo
@@ -74,8 +66,8 @@ echo "== Creating a dirty image file =="
IMGOPTS="compat=1.1,lazy_refcounts=on"
_make_test_img $size
-_subshell_exec $QEMU_IO -c "write -P 0x5a 0 512" \
- -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
+$QEMU_IO -c "write -P 0x5a 0 512" \
+ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
| _filter_qemu_io
# The dirty bit must be set
@@ -109,8 +101,8 @@ echo "== Opening a dirty image read/write should repair it =="
IMGOPTS="compat=1.1,lazy_refcounts=on"
_make_test_img $size
-_subshell_exec $QEMU_IO -c "write -P 0x5a 0 512" \
- -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
+$QEMU_IO -c "write -P 0x5a 0 512" \
+ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
| _filter_qemu_io
# The dirty bit must be set
@@ -127,8 +119,8 @@ echo "== Creating an image file with lazy_refcounts=off =="
IMGOPTS="compat=1.1,lazy_refcounts=off"
_make_test_img $size
-_subshell_exec $QEMU_IO -c "write -P 0x5a 0 512" \
- -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
+$QEMU_IO -c "write -P 0x5a 0 512" \
+ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
| _filter_qemu_io
# The dirty bit must not be set since lazy_refcounts=off
@@ -154,6 +146,33 @@ $PYTHON qcow2.py "$TEST_IMG".base dump-header | grep incompatible_features
_check_test_img
TEST_IMG="$TEST_IMG".base _check_test_img
+echo
+echo "== Changing lazy_refcounts setting at runtime =="
+
+IMGOPTS="compat=1.1,lazy_refcounts=off"
+_make_test_img $size
+
+$QEMU_IO -c "reopen -o lazy-refcounts=on" \
+ -c "write -P 0x5a 0 512" \
+ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
+ | _filter_qemu_io
+
+# The dirty bit must be set
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+_check_test_img
+
+IMGOPTS="compat=1.1,lazy_refcounts=on"
+_make_test_img $size
+
+$QEMU_IO -c "reopen -o lazy-refcounts=off" \
+ -c "write -P 0x5a 0 512" \
+ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 \
+ | _filter_qemu_io
+
+# The dirty bit must not be set
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+_check_test_img
+
# success, all done
echo "*** done"
diff --git a/qemu/tests/qemu-iotests/039.out b/qemu/tests/qemu-iotests/039.out
index d09751f9c..32c884694 100644
--- a/qemu/tests/qemu-iotests/039.out
+++ b/qemu/tests/qemu-iotests/039.out
@@ -11,7 +11,11 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-./039: Killed ( exec "$@" )
+./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+else
+ exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+fi )
incompatible_features 0x1
ERROR cluster 5 refcount=0 reference=1
ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
@@ -46,7 +50,11 @@ read 512/512 bytes at offset 0
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-./039: Killed ( exec "$@" )
+./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+else
+ exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+fi )
incompatible_features 0x1
ERROR cluster 5 refcount=0 reference=1
Rebuilding refcount structure
@@ -60,13 +68,17 @@ incompatible_features 0x0
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-./039: Killed ( exec "$@" )
+./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+else
+ exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+fi )
incompatible_features 0x0
No errors were found on the image.
== Committing to a backing file with lazy_refcounts=on ==
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
wrote 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Image committed.
@@ -74,4 +86,30 @@ incompatible_features 0x0
incompatible_features 0x0
No errors were found on the image.
No errors were found on the image.
+
+== Changing lazy_refcounts setting at runtime ==
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+else
+ exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+fi )
+incompatible_features 0x1
+ERROR cluster 5 refcount=0 reference=1
+ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
+
+2 errors were found on the image.
+Data may be corrupted, or further writes to the image may corrupt it.
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+else
+ exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+fi )
+incompatible_features 0x0
+No errors were found on the image.
*** done
diff --git a/qemu/tests/qemu-iotests/040 b/qemu/tests/qemu-iotests/040
index ea2f98e51..5bdaf3d48 100755
--- a/qemu/tests/qemu-iotests/040
+++ b/qemu/tests/qemu-iotests/040
@@ -41,6 +41,7 @@ class ImageCommitTestCase(iotests.QMPTestCase):
while not completed:
for event in self.vm.get_qmp_events(wait=True):
if event['event'] == 'BLOCK_JOB_COMPLETED':
+ self.assert_qmp_absent(event, 'data/error')
self.assert_qmp(event, 'data/type', 'commit')
self.assert_qmp(event, 'data/device', 'drive0')
self.assert_qmp(event, 'data/offset', event['data']['len'])
@@ -251,5 +252,34 @@ class TestSetSpeed(ImageCommitTestCase):
class TestActiveZeroLengthImage(TestSingleDrive):
image_len = 0
+class TestReopenOverlay(ImageCommitTestCase):
+ image_len = 1024 * 1024
+ img0 = os.path.join(iotests.test_dir, '0.img')
+ img1 = os.path.join(iotests.test_dir, '1.img')
+ img2 = os.path.join(iotests.test_dir, '2.img')
+ img3 = os.path.join(iotests.test_dir, '3.img')
+
+ def setUp(self):
+ iotests.create_image(self.img0, self.image_len)
+ qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.img0, self.img1)
+ qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.img1, self.img2)
+ qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % self.img2, self.img3)
+ qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xab 0 128K', self.img1)
+ self.vm = iotests.VM().add_drive(self.img3)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(self.img0)
+ os.remove(self.img1)
+ os.remove(self.img2)
+ os.remove(self.img3)
+
+ # This tests what happens when the overlay image of the 'top' node
+ # needs to be reopened in read-write mode in order to update the
+ # backing image string.
+ def test_reopen_overlay(self):
+ self.run_commit_test(self.img1, self.img0)
+
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/qemu/tests/qemu-iotests/040.out b/qemu/tests/qemu-iotests/040.out
index 42314e9c0..4fd1c2dcd 100644
--- a/qemu/tests/qemu-iotests/040.out
+++ b/qemu/tests/qemu-iotests/040.out
@@ -1,5 +1,5 @@
-........................
+.........................
----------------------------------------------------------------------
-Ran 24 tests
+Ran 25 tests
OK
diff --git a/qemu/tests/qemu-iotests/041 b/qemu/tests/qemu-iotests/041
index 3d46ed705..b1c542f99 100755
--- a/qemu/tests/qemu-iotests/041
+++ b/qemu/tests/qemu-iotests/041
@@ -34,14 +34,18 @@ quorum_img3 = os.path.join(iotests.test_dir, 'quorum3.img')
quorum_repair_img = os.path.join(iotests.test_dir, 'quorum_repair.img')
quorum_snapshot_file = os.path.join(iotests.test_dir, 'quorum_snapshot.img')
-
class TestSingleDrive(iotests.QMPTestCase):
image_len = 1 * 1024 * 1024 # MB
+ qmp_cmd = 'drive-mirror'
+ qmp_target = target_img
+ not_found_error = 'DeviceNotFound'
def setUp(self):
iotests.create_image(backing_img, self.image_len)
qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
self.vm = iotests.VM().add_drive(test_img)
+ if iotests.qemu_default_machine == 'pc':
+ self.vm.add_drive(None, 'media=cdrom', 'ide')
self.vm.launch()
def tearDown(self):
@@ -56,8 +60,8 @@ class TestSingleDrive(iotests.QMPTestCase):
def test_complete(self):
self.assert_no_active_block_jobs()
- result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
- target=target_img)
+ result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
+ target=self.qmp_target)
self.assert_qmp(result, 'return', {})
self.complete_and_wait()
@@ -70,8 +74,8 @@ class TestSingleDrive(iotests.QMPTestCase):
def test_cancel(self):
self.assert_no_active_block_jobs()
- result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
- target=target_img)
+ result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
+ target=self.qmp_target)
self.assert_qmp(result, 'return', {})
self.cancel_and_wait(force=True)
@@ -82,8 +86,8 @@ class TestSingleDrive(iotests.QMPTestCase):
def test_cancel_after_ready(self):
self.assert_no_active_block_jobs()
- result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
- target=target_img)
+ result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
+ target=self.qmp_target)
self.assert_qmp(result, 'return', {})
self.wait_ready_and_cancel()
@@ -96,8 +100,8 @@ class TestSingleDrive(iotests.QMPTestCase):
def test_pause(self):
self.assert_no_active_block_jobs()
- result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
- target=target_img)
+ result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
+ target=self.qmp_target)
self.assert_qmp(result, 'return', {})
result = self.vm.qmp('block-job-pause', device='drive0')
@@ -123,8 +127,8 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
# A small buffer is rounded up automatically
- result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
- buf_size=4096, target=target_img)
+ result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
+ buf_size=4096, target=self.qmp_target)
self.assert_qmp(result, 'return', {})
self.complete_and_wait()
@@ -139,8 +143,8 @@ class TestSingleDrive(iotests.QMPTestCase):
qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,size=%d'
% (self.image_len, self.image_len), target_img)
- result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
- buf_size=65536, mode='existing', target=target_img)
+ result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
+ buf_size=65536, mode='existing', target=self.qmp_target)
self.assert_qmp(result, 'return', {})
self.complete_and_wait()
@@ -155,8 +159,8 @@ class TestSingleDrive(iotests.QMPTestCase):
qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,backing_file=%s'
% (self.image_len, backing_img), target_img)
- result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
- mode='existing', target=target_img)
+ result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
+ mode='existing', target=self.qmp_target)
self.assert_qmp(result, 'return', {})
self.complete_and_wait()
@@ -167,30 +171,85 @@ class TestSingleDrive(iotests.QMPTestCase):
'target image does not match source after mirroring')
def test_medium_not_found(self):
- result = self.vm.qmp('drive-mirror', device='ide1-cd0', sync='full',
- target=target_img)
- self.assert_qmp(result, 'error/class', 'GenericError')
+ if iotests.qemu_default_machine != 'pc':
+ return
+
+ result = self.vm.qmp(self.qmp_cmd, device='ide1-cd0', sync='full',
+ target=self.qmp_target)
+ self.assert_qmp(result, 'error/class', self.not_found_error)
def test_image_not_found(self):
- result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
- mode='existing', target=target_img)
+ result = self.vm.qmp(self.qmp_cmd, device='drive0', sync='full',
+ mode='existing', target=self.qmp_target)
self.assert_qmp(result, 'error/class', 'GenericError')
def test_device_not_found(self):
- result = self.vm.qmp('drive-mirror', device='nonexistent', sync='full',
- target=target_img)
- self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+ result = self.vm.qmp(self.qmp_cmd, device='nonexistent', sync='full',
+ target=self.qmp_target)
+ self.assert_qmp(result, 'error/class', self.not_found_error)
+
+class TestSingleBlockdev(TestSingleDrive):
+ qmp_cmd = 'blockdev-mirror'
+ qmp_target = 'node1'
+ not_found_error = 'GenericError'
+
+ def setUp(self):
+ TestSingleDrive.setUp(self)
+ qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img)
+ args = {'options':
+ {'driver': iotests.imgfmt,
+ 'node-name': self.qmp_target,
+ 'file': { 'filename': target_img, 'driver': 'file' } } }
+ result = self.vm.qmp("blockdev-add", **args)
+ self.assert_qmp(result, 'return', {})
+
+ test_large_cluster = None
+ test_image_not_found = None
+ test_small_buffer2 = None
+
+class TestBlockdevAttached(iotests.QMPTestCase):
+ image_len = 1 * 1024 * 1024 # MB
+
+ def setUp(self):
+ iotests.create_image(backing_img, self.image_len)
+ qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, test_img)
+ qemu_img('create', '-f', iotests.imgfmt, '-o', 'backing_file=%s' % backing_img, target_img)
+ self.vm = iotests.VM().add_drive(test_img)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(test_img)
+ os.remove(target_img)
+
+ def test_blockdev_attached(self):
+ self.assert_no_active_block_jobs()
+ args = {'options':
+ {'driver': iotests.imgfmt,
+ 'id': 'drive1',
+ 'file': { 'filename': target_img, 'driver': 'file' } } }
+ result = self.vm.qmp("blockdev-add", **args)
+ self.assert_qmp(result, 'return', {})
+ result = self.vm.qmp('blockdev-mirror', device='drive0', sync='full',
+ target='drive1')
+ self.assert_qmp(result, 'error/class', 'GenericError')
class TestSingleDriveZeroLength(TestSingleDrive):
image_len = 0
test_small_buffer2 = None
test_large_cluster = None
+class TestSingleBlockdevZeroLength(TestSingleBlockdev):
+ image_len = 0
+
class TestSingleDriveUnalignedLength(TestSingleDrive):
image_len = 1025 * 1024
test_small_buffer2 = None
test_large_cluster = None
+class TestSingleBlockdevUnalignedLength(TestSingleBlockdev):
+ image_len = 1025 * 1024
+
class TestMirrorNoBacking(iotests.QMPTestCase):
image_len = 2 * 1024 * 1024 # MB
@@ -707,6 +766,9 @@ class TestRepairQuorum(iotests.QMPTestCase):
def setUp(self):
self.vm = iotests.VM()
+ if iotests.qemu_default_machine == 'pc':
+ self.vm.add_drive(None, 'media=cdrom', 'ide')
+
# Add each individual quorum images
for i in self.IMAGES:
qemu_img('create', '-f', iotests.imgfmt, i,
@@ -748,8 +810,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {})
self.complete_and_wait(drive="quorum0")
- result = self.vm.qmp('query-named-block-nodes')
- self.assert_qmp(result, 'return[0]/file', quorum_repair_img)
+ self.assert_has_block_node("repair0", quorum_repair_img)
# TODO: a better test requiring some QEMU infrastructure will be added
# to check that this file is really driven by quorum
self.vm.shutdown()
@@ -771,8 +832,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
self.cancel_and_wait(drive="quorum0", force=True)
# here we check that the last registered quorum file has not been
# swapped out and unref
- result = self.vm.qmp('query-named-block-nodes')
- self.assert_qmp(result, 'return[0]/file', quorum_img3)
+ self.assert_has_block_node(None, quorum_img3)
self.vm.shutdown()
def test_cancel_after_ready(self):
@@ -788,10 +848,9 @@ class TestRepairQuorum(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {})
self.wait_ready_and_cancel(drive="quorum0")
- result = self.vm.qmp('query-named-block-nodes')
# here we check that the last registered quorum file has not been
# swapped out and unref
- self.assert_qmp(result, 'return[0]/file', quorum_img3)
+ self.assert_has_block_node(None, quorum_img3)
self.vm.shutdown()
self.assertTrue(iotests.compare_images(quorum_img2, quorum_repair_img),
'target image does not match source after mirroring')
@@ -831,7 +890,11 @@ class TestRepairQuorum(iotests.QMPTestCase):
if not self.has_quorum():
return
- result = self.vm.qmp('drive-mirror', device='ide1-cd0', sync='full',
+ if iotests.qemu_default_machine != 'pc':
+ return
+
+ result = self.vm.qmp('drive-mirror', device='drive0', # CD-ROM
+ sync='full',
node_name='repair0',
replaces='img1',
target=quorum_repair_img, format=iotests.imgfmt)
@@ -877,7 +940,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
target=quorum_repair_img, format=iotests.imgfmt)
self.assert_qmp(result, 'error/class', 'GenericError')
- def test_unexistant_replaces(self):
+ def test_nonexistent_replaces(self):
if not self.has_quorum():
return
@@ -908,8 +971,7 @@ class TestRepairQuorum(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {})
self.complete_and_wait(drive="quorum0")
- result = self.vm.qmp('query-named-block-nodes')
- self.assert_qmp(result, 'return[0]/file', quorum_repair_img)
+ self.assert_has_block_node("repair0", quorum_repair_img)
# TODO: a better test requiring some QEMU infrastructure will be added
# to check that this file is really driven by quorum
self.vm.shutdown()
diff --git a/qemu/tests/qemu-iotests/041.out b/qemu/tests/qemu-iotests/041.out
index 24093bc63..b67d0504a 100644
--- a/qemu/tests/qemu-iotests/041.out
+++ b/qemu/tests/qemu-iotests/041.out
@@ -1,5 +1,5 @@
-......................................................
+............................................................................
----------------------------------------------------------------------
-Ran 54 tests
+Ran 76 tests
OK
diff --git a/qemu/tests/qemu-iotests/042 b/qemu/tests/qemu-iotests/042
index 94ce3a9cc..351b2830a 100755
--- a/qemu/tests/qemu-iotests/042
+++ b/qemu/tests/qemu-iotests/042
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/043 b/qemu/tests/qemu-iotests/043
index b316b97c0..1c6c22d92 100755
--- a/qemu/tests/qemu-iotests/043
+++ b/qemu/tests/qemu-iotests/043
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/043.out b/qemu/tests/qemu-iotests/043.out
index 012cc008e..b37d2a380 100644
--- a/qemu/tests/qemu-iotests/043.out
+++ b/qemu/tests/qemu-iotests/043.out
@@ -4,20 +4,20 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
== backing file references self ==
qemu-img: Backing file 'TEST_DIR/t.IMGFMT' creates an infinite loop.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
== parent references self ==
qemu-img: Backing file 'TEST_DIR/t.IMGFMT' creates an infinite loop.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.1.base'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.2.base'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.3.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.1.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.2.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.3.base
== ancestor references another ancestor ==
qemu-img: Backing file 'TEST_DIR/t.IMGFMT.2.base' creates an infinite loop.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.1.base'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.2.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.1.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.2.base
== finite chain of length 3 (human) ==
image: TEST_DIR/t.IMGFMT
@@ -44,6 +44,7 @@ cluster_size: 65536
"filename": "TEST_DIR/t.IMGFMT",
"cluster-size": 65536,
"format": "IMGFMT",
+ "full-backing-filename": "TEST_DIR/t.IMGFMT.2.base",
"backing-filename": "TEST_DIR/t.IMGFMT.2.base",
"dirty-flag": false
},
@@ -52,6 +53,7 @@ cluster_size: 65536
"filename": "TEST_DIR/t.IMGFMT.2.base",
"cluster-size": 65536,
"format": "IMGFMT",
+ "full-backing-filename": "TEST_DIR/t.IMGFMT.1.base",
"backing-filename": "TEST_DIR/t.IMGFMT.1.base",
"dirty-flag": false
},
diff --git a/qemu/tests/qemu-iotests/046 b/qemu/tests/qemu-iotests/046
index e0be46cf2..e528b67cc 100755
--- a/qemu/tests/qemu-iotests/046
+++ b/qemu/tests/qemu-iotests/046
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/046.out b/qemu/tests/qemu-iotests/046.out
index 9d18af53a..ca2c7404a 100644
--- a/qemu/tests/qemu-iotests/046.out
+++ b/qemu/tests/qemu-iotests/046.out
@@ -66,7 +66,7 @@ wrote 65536/65536 bytes at offset 1966080
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 2031616
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=6442450944 backing_file=TEST_DIR/t.IMGFMT.base
== Some concurrent requests touching the same cluster ==
blkdebug: Suspended request 'A'
diff --git a/qemu/tests/qemu-iotests/047 b/qemu/tests/qemu-iotests/047
index c35cd096b..1b8f3d4a6 100755
--- a/qemu/tests/qemu-iotests/047
+++ b/qemu/tests/qemu-iotests/047
@@ -26,7 +26,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/049 b/qemu/tests/qemu-iotests/049
index 93aa0ea55..fff07604f 100755
--- a/qemu/tests/qemu-iotests/049
+++ b/qemu/tests/qemu-iotests/049
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/049.out b/qemu/tests/qemu-iotests/049.out
index 9f93666c5..4673b67f3 100644
--- a/qemu/tests/qemu-iotests/049.out
+++ b/qemu/tests/qemu-iotests/049.out
@@ -95,17 +95,15 @@ qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1024
qemu-img: Image size must be less than 8 EiB!
qemu-img create -f qcow2 -o size=-1024 TEST_DIR/t.qcow2
-qemu-img: qcow2 doesn't support shrinking images yet
-qemu-img: TEST_DIR/t.qcow2: Could not resize image: Operation not supported
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+qemu-img: Parameter 'size' expects a non-negative number below 2^64
+qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- -1k
qemu-img: Image size must be less than 8 EiB!
qemu-img create -f qcow2 -o size=-1k TEST_DIR/t.qcow2
-qemu-img: qcow2 doesn't support shrinking images yet
-qemu-img: TEST_DIR/t.qcow2: Could not resize image: Operation not supported
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=-1024 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+qemu-img: Parameter 'size' expects a non-negative number below 2^64
+qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'
qemu-img create -f qcow2 TEST_DIR/t.qcow2 -- 1kilobyte
qemu-img: Invalid image size specified! You may use k, M, G, T, P or E suffixes for
@@ -120,6 +118,7 @@ qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
qemu-img create -f qcow2 -o size=foobar TEST_DIR/t.qcow2
qemu-img: Parameter 'size' expects a size
+You may use k, M, G or T suffixes for kilobytes, megabytes, gigabytes and terabytes.
qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'
== Check correct interpretation of suffixes for cluster size ==
@@ -157,30 +156,30 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_si
== Check compat level option ==
qemu-img create -f qcow2 -o compat=0.10 TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o compat=1.1 TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o compat=0.42 TEST_DIR/t.qcow2 64M
qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: '0.42'
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.42' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.42 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o compat=foobar TEST_DIR/t.qcow2 64M
qemu-img: TEST_DIR/t.qcow2: Invalid compatibility level: 'foobar'
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='foobar' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=foobar encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
== Check preallocation option ==
qemu-img create -f qcow2 -o preallocation=off TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='off' lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation=off lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o preallocation=metadata TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='metadata' lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation=metadata lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o preallocation=1234 TEST_DIR/t.qcow2 64M
qemu-img: TEST_DIR/t.qcow2: invalid parameter value: 1234
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation='1234' lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 preallocation=1234 lazy_refcounts=off refcount_bits=16
== Check encryption option ==
@@ -188,27 +187,21 @@ qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o encryption=on TEST_DIR/t.qcow2 64M
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on cluster_size=65536 lazy_refcounts=off refcount_bits=16
== Check lazy_refcounts option (only with v3) ==
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=off TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o compat=1.1,lazy_refcounts=on TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='1.1' encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=1.1 encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=off TEST_DIR/t.qcow2 64M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
qemu-img create -f qcow2 -o compat=0.10,lazy_refcounts=on TEST_DIR/t.qcow2 64M
qemu-img: TEST_DIR/t.qcow2: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat='0.10' encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 compat=0.10 encryption=off cluster_size=65536 lazy_refcounts=on refcount_bits=16
*** done
diff --git a/qemu/tests/qemu-iotests/050 b/qemu/tests/qemu-iotests/050
index 07802bc49..03b4a5d62 100755
--- a/qemu/tests/qemu-iotests/050
+++ b/qemu/tests/qemu-iotests/050
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -51,14 +50,19 @@ fi
echo
echo "== Creating images =="
+TEST_IMG_SAVE="$TEST_IMG"
+TEST_IMG="$TEST_IMG.old"
+
size=10M
_make_test_img $size
$QEMU_IO -c "write -P 0x40 0 1048576" "$TEST_IMG" | _filter_qemu_io
-mv "$TEST_IMG" "$TEST_IMG.old"
+
+TEST_IMG="$TEST_IMG_SAVE.new"
_make_test_img $size
$QEMU_IO -c "write -P 0x5a 0 1048576" "$TEST_IMG" | _filter_qemu_io
-mv "$TEST_IMG" "$TEST_IMG.new"
+
+TEST_IMG="$TEST_IMG_SAVE"
_make_test_img -b "$TEST_IMG.old" $size
$QEMU_IO -c "write -z 0 1048576" "$TEST_IMG" | _filter_qemu_io
diff --git a/qemu/tests/qemu-iotests/050.out b/qemu/tests/qemu-iotests/050.out
index a6cb2e686..3602d580d 100644
--- a/qemu/tests/qemu-iotests/050.out
+++ b/qemu/tests/qemu-iotests/050.out
@@ -1,13 +1,13 @@
QA output created by 050
== Creating images ==
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760
+Formatting 'TEST_DIR/t.IMGFMT.old', fmt=IMGFMT size=10485760
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760
+Formatting 'TEST_DIR/t.IMGFMT.new', fmt=IMGFMT size=10485760
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 backing_file='TEST_DIR/t.IMGFMT.old'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=10485760 backing_file=TEST_DIR/t.IMGFMT.old
wrote 1048576/1048576 bytes at offset 0
1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/qemu/tests/qemu-iotests/051 b/qemu/tests/qemu-iotests/051
index 4a8055b67..630cb7a11 100755
--- a/qemu/tests/qemu-iotests/051
+++ b/qemu/tests/qemu-iotests/051
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -61,10 +60,11 @@ function do_run_qemu()
function run_qemu()
{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_generated_node_ids
}
size=128M
+device_id="drive0"
_make_test_img $size
cp "$TEST_IMG" "$TEST_IMG.orig"
@@ -75,10 +75,10 @@ echo
echo === Unknown option ===
echo
-run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=
-run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=on
-run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=1234
-run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=foo
+run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=,if=none,id=$device_id
+run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=on,if=none,id=$device_id
+run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=1234,if=none,id=$device_id
+run_qemu -drive file="$TEST_IMG",format=qcow2,unknown_opt=foo,if=none,id=$device_id
echo
echo === Unknown protocol option ===
@@ -108,7 +108,8 @@ echo
echo === Overriding backing file ===
echo
-echo "info block" | run_qemu -drive file="$TEST_IMG",driver=qcow2,backing.file.filename="$TEST_IMG.orig" -nodefaults
+echo "info block" | run_qemu -drive file="$TEST_IMG",driver=qcow2,backing.file.filename="$TEST_IMG.orig",if=none,id=$device_id -nodefaults\
+ | _filter_generated_node_ids
# Drivers that don't support backing files
run_qemu -drive file="$TEST_IMG",driver=raw,backing.file.filename="$TEST_IMG.orig"
@@ -139,41 +140,63 @@ echo
echo === No medium ===
echo
-run_qemu -drive if=floppy
-run_qemu -drive if=ide,media=cdrom
-run_qemu -drive if=scsi,media=cdrom
+case "$QEMU_DEFAULT_MACHINE" in
+ pc)
+ run_qemu -drive if=floppy
+ run_qemu -drive if=ide,media=cdrom
+ run_qemu -drive if=scsi,media=cdrom
+ run_qemu -drive if=ide
+ run_qemu -drive if=scsi
+ ;;
+ *)
+ ;;
+esac
-run_qemu -drive if=ide
run_qemu -drive if=virtio
-run_qemu -drive if=scsi
-run_qemu -drive if=none,id=disk -device ide-cd,drive=disk
-run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
-
-run_qemu -drive if=none,id=disk -device ide-drive,drive=disk
-run_qemu -drive if=none,id=disk -device ide-hd,drive=disk
-run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
-run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
+case "$QEMU_DEFAULT_MACHINE" in
+ pc)
+ run_qemu -drive if=none,id=disk -device ide-cd,drive=disk
+ run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
+ run_qemu -drive if=none,id=disk -device ide-drive,drive=disk
+ run_qemu -drive if=none,id=disk -device ide-hd,drive=disk
+ run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
+ run_qemu -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
+ ;;
+ *)
+ ;;
+esac
echo
echo === Read-only ===
echo
-run_qemu -drive file="$TEST_IMG",if=floppy,readonly=on
-run_qemu -drive file="$TEST_IMG",if=ide,media=cdrom,readonly=on
-run_qemu -drive file="$TEST_IMG",if=scsi,media=cdrom,readonly=on
+case "$QEMU_DEFAULT_MACHINE" in
+ pc)
+ run_qemu -drive file="$TEST_IMG",if=floppy,readonly=on
+ run_qemu -drive file="$TEST_IMG",if=ide,media=cdrom,readonly=on
+ run_qemu -drive file="$TEST_IMG",if=scsi,media=cdrom,readonly=on
+ run_qemu -drive file="$TEST_IMG",if=ide,readonly=on
+ run_qemu -drive file="$TEST_IMG",if=scsi,readonly=on
+ ;;
+ *)
+ ;;
+esac
-run_qemu -drive file="$TEST_IMG",if=ide,readonly=on
run_qemu -drive file="$TEST_IMG",if=virtio,readonly=on
-run_qemu -drive file="$TEST_IMG",if=scsi,readonly=on
-
-run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-cd,drive=disk
-run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
-run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-drive,drive=disk
-run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-hd,drive=disk
-run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
-run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
+case "$QEMU_DEFAULT_MACHINE" in
+ pc)
+ run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-cd,drive=disk
+ run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
+ run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-drive,drive=disk
+ run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device ide-hd,drive=disk
+ run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
+ run_qemu -drive file="$TEST_IMG",if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
+ ;;
+ *)
+ ;;
+esac
echo
echo === Cache modes ===
@@ -182,12 +205,20 @@ echo
# Cannot use the test image because cache=none might not work on the host FS
# Use cdrom so that we won't get errors about missing media
-run_qemu -drive media=cdrom,cache=none
-run_qemu -drive media=cdrom,cache=directsync
-run_qemu -drive media=cdrom,cache=writeback
-run_qemu -drive media=cdrom,cache=writethrough
-run_qemu -drive media=cdrom,cache=unsafe
-run_qemu -drive media=cdrom,cache=invalid_value
+run_qemu -drive driver=null-co,cache=none
+run_qemu -drive driver=null-co,cache=directsync
+run_qemu -drive driver=null-co,cache=writeback
+run_qemu -drive driver=null-co,cache=writethrough
+run_qemu -drive driver=null-co,cache=unsafe
+run_qemu -drive driver=null-co,cache=invalid_value
+
+# Can't test direct=on here because O_DIRECT might not be supported on this FS
+# Test 142 checks the direct=on cases
+
+for cache in writeback writethrough unsafe invalid_value; do
+ echo -e "info block\ninfo block file\ninfo block backing\ninfo block backing-file" | \
+ run_qemu -drive file="$TEST_IMG",cache=$cache,backing.file.filename="$TEST_IMG.base",backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=$device_id -nodefaults
+done
echo
echo === Specifying the protocol layer ===
@@ -231,6 +262,24 @@ run_qemu -drive file="$TEST_IMG",iops_size=1234,throttling.iops-size=5678
run_qemu -drive file="$TEST_IMG",readonly=on,read-only=off
echo
+echo === Catching negative/large throttling values ===
+echo
+
+run_qemu -drive file="$TEST_IMG",iops=-1
+run_qemu -drive file="$TEST_IMG",bps=-2
+run_qemu -drive file="$TEST_IMG",bps_rd=-3
+run_qemu -drive file="$TEST_IMG",bps_rd_max=-3
+run_qemu -drive file="$TEST_IMG",throttling.iops-total=-4
+run_qemu -drive file="$TEST_IMG",throttling.bps-total=-5
+# These are accepted
+run_qemu -drive file="$TEST_IMG",bps=0
+run_qemu -drive file="$TEST_IMG",bps=1
+run_qemu -drive file="$TEST_IMG",bps=1000000000000000
+# While these are not
+run_qemu -drive file="$TEST_IMG",bps=1000000000000001
+run_qemu -drive file="$TEST_IMG",bps=9999999999999999
+
+echo
echo === Parsing protocol from file name ===
echo
@@ -252,26 +301,30 @@ echo
$QEMU_IO -c "write -P 0x11 0 4k" "$TEST_IMG" | _filter_qemu_io
-echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG" -snapshot | _filter_qemu_io
-echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io
-echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2,snapshot=on | _filter_qemu_io
-echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2 -snapshot | _filter_qemu_io
-echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="file:$TEST_IMG" -snapshot | _filter_qemu_io
-echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="file:$TEST_IMG",snapshot=on | _filter_qemu_io
+
+echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",if=none,id=$device_id -snapshot | _filter_qemu_io
+echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id | _filter_qemu_io
+echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2,snapshot=on,if=none,id=$device_id\
+ | _filter_qemu_io
+echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file.filename="$TEST_IMG",driver=qcow2,if=none,id=$device_id -snapshot\
+ | _filter_qemu_io
+echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="file:$TEST_IMG",if=none,id=$device_id -snapshot | _filter_qemu_io
+echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="file:$TEST_IMG",snapshot=on,if=none,id=$device_id | _filter_qemu_io
# Opening a read-only file r/w with snapshot=on
chmod u-w "$TEST_IMG"
-echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG" -snapshot | _filter_qemu_io
-echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io
+echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",if=none,id=$device_id -snapshot | _filter_qemu_io
+echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id | _filter_qemu_io
chmod u+w "$TEST_IMG"
$QEMU_IO -c "read -P 0x11 0 4k" "$TEST_IMG" | _filter_qemu_io
-echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",snapshot=off | _filter_qemu_io
+echo "qemu-io $device_id \"write -P 0x22 0 4k\"" | run_qemu -drive file="$TEST_IMG",snapshot=off,if=none,id=$device_id | _filter_qemu_io
$QEMU_IO -c "read -P 0x22 0 4k" "$TEST_IMG" | _filter_qemu_io
-echo -e 'qemu-io ide0-hd0 "write -P 0x33 0 4k"\ncommit ide0-hd0' | run_qemu -drive file="$TEST_IMG",snapshot=on | _filter_qemu_io
+echo -e "qemu-io $device_id \"write -P 0x33 0 4k\"\ncommit $device_id" | run_qemu -drive file="$TEST_IMG",snapshot=on,if=none,id=$device_id\
+ | _filter_qemu_io
$QEMU_IO -c "read -P 0x33 0 4k" "$TEST_IMG" | _filter_qemu_io
diff --git a/qemu/tests/qemu-iotests/051.out b/qemu/tests/qemu-iotests/051.out
index 23c282357..408d613bc 100644
--- a/qemu/tests/qemu-iotests/051.out
+++ b/qemu/tests/qemu-iotests/051.out
@@ -1,20 +1,20 @@
QA output created by 051
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
=== Unknown option ===
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=,if=none,id=drive0
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=,if=none,id=drive0: Block format 'qcow2' does not support the option 'unknown_opt'
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on,if=none,id=drive0
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on,if=none,id=drive0: Block format 'qcow2' does not support the option 'unknown_opt'
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234,if=none,id=drive0
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234,if=none,id=drive0: Block format 'qcow2' does not support the option 'unknown_opt'
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: Block format 'qcow2' used by device 'ide0-hd0' doesn't support the option 'unknown_opt'
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo,if=none,id=drive0
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo,if=none,id=drive0: Block format 'qcow2' does not support the option 'unknown_opt'
=== Unknown protocol option ===
@@ -56,10 +56,11 @@ QEMU X.Y.Z monitor - type 'help' for more information
=== Overriding backing file ===
-Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig -nodefaults
+Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
-ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
+drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+ Removable device: not locked, tray closed
Cache mode: writeback
Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
(qemu) qququiquit
@@ -107,136 +108,105 @@ QEMU X.Y.Z monitor - type 'help' for more information
=== No medium ===
-Testing: -drive if=floppy
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
-
-Testing: -drive if=ide,media=cdrom
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
-
-Testing: -drive if=scsi,media=cdrom
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
-
-Testing: -drive if=ide
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) QEMU_PROG: Device needs media, but drive is empty
-QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
-
Testing: -drive if=virtio
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
-Testing: -drive if=scsi
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) QEMU_PROG: Initialization of device lsi53c895a failed: Device needs media, but drive is empty
-Testing: -drive if=none,id=disk -device ide-cd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
+=== Read-only ===
-Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
+Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
-Testing: -drive if=none,id=disk -device ide-drive,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
-QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
-
-Testing: -drive if=none,id=disk -device ide-hd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
-QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
-
-Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty
-
-Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty
+=== Cache modes ===
-=== Read-only ===
-
-Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
-
-Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on
+Testing: -drive driver=null-co,cache=none
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
-Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on
+Testing: -drive driver=null-co,cache=directsync
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
-Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) QEMU_PROG: Can't use a read-only drive
-QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
-
-Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
+Testing: -drive driver=null-co,cache=writeback
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
-Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
+Testing: -drive driver=null-co,cache=writethrough
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
-Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk
+Testing: -drive driver=null-co,cache=unsafe
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) qququiquit
-Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
+Testing: -drive driver=null-co,cache=invalid_value
+QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
-Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk
+Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive
-QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
+drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+ Removable device: not locked, tray closed
+ Cache mode: writeback
+ Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
-Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive
-QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
+file: TEST_DIR/t.qcow2 (file)
+ Cache mode: writeback
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
+backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
+ Cache mode: writeback, ignore flushes
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
-Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
-QEMU X.Y.Z monitor - type 'help' for more information
+backing-file: TEST_DIR/t.qcow2.base (file, read-only)
+ Cache mode: writeback, ignore flushes
(qemu) qququiquit
-Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
+Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
-
-
-=== Cache modes ===
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
+drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+ Removable device: not locked, tray closed
+ Cache mode: writethrough
+ Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
-Testing: -drive media=cdrom,cache=none
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
+file: TEST_DIR/t.qcow2 (file)
+ Cache mode: writeback
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
+backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
+ Cache mode: writeback, ignore flushes
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
-Testing: -drive media=cdrom,cache=directsync
-QEMU X.Y.Z monitor - type 'help' for more information
+backing-file: TEST_DIR/t.qcow2.base (file, read-only)
+ Cache mode: writeback, ignore flushes
(qemu) qququiquit
-Testing: -drive media=cdrom,cache=writeback
+Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
+drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+ Removable device: not locked, tray closed
+ Cache mode: writeback, ignore flushes
+ Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
-Testing: -drive media=cdrom,cache=writethrough
-QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qququiquit
+file: TEST_DIR/t.qcow2 (file)
+ Cache mode: writeback, ignore flushes
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
+backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
+ Cache mode: writeback, ignore flushes
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
-Testing: -drive media=cdrom,cache=unsafe
-QEMU X.Y.Z monitor - type 'help' for more information
+backing-file: TEST_DIR/t.qcow2.base (file, read-only)
+ Cache mode: writeback, ignore flushes
(qemu) qququiquit
-Testing: -drive media=cdrom,cache=invalid_value
-QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option
+Testing: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0: invalid cache option
=== Specifying the protocol layer ===
@@ -315,6 +285,45 @@ Testing: -drive file=TEST_DIR/t.qcow2,readonly=on,read-only=off
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,readonly=on,read-only=off: 'read-only' and its alias 'readonly' can't be used at the same time
+=== Catching negative/large throttling values ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,iops=-1
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops=-1: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=-2
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=-2: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps_rd=-3
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_rd=-3: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps_rd_max=-3
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_rd_max=-3: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,throttling.iops-total=-4
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,throttling.iops-total=-4: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,throttling.bps-total=-5
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,throttling.bps-total=-5: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=0
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=1
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=1000000000000000
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=1000000000000001
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=1000000000000001: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=9999999999999999
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=9999999999999999: bps/iops/max values must be within [0, 1000000000000000]
+
+
=== Parsing protocol from file name ===
Testing: -hda foo:bar
@@ -342,79 +351,79 @@ QEMU_PROG: -drive file.filename=file:TEST_DIR/t.qcow2: Could not open 'file:TEST
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Testing: -drive file=TEST_DIR/t.qcow2 -snapshot
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
-Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
-Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,snapshot=on
+Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,snapshot=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
-Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2 -snapshot
+Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,if=none,id=drive0 -snapshot
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
-Testing: -drive file=file:TEST_DIR/t.qcow2 -snapshot
+Testing: -drive file=file:TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
-Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on
+Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
-Testing: -drive file=TEST_DIR/t.qcow2 -snapshot
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
-Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Testing: -drive file=TEST_DIR/t.qcow2,snapshot=off
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=off,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x2qemu-io ide0-hd0 "write -P 0x22qemu-io ide0-hd0 "write -P 0x22 qemu-io ide0-hd0 "write -P 0x22 0qemu-io ide0-hd0 "write -P 0x22 0 qemu-io ide0-hd0 "write -P 0x22 0 4qemu-io ide0-hd0 "write -P 0x22 0 4kqemu-io ide0-hd0 "write -P 0x22 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
(qemu) qququiquit
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io iqemu-io idqemu-io ideqemu-io ide0qemu-io ide0-qemu-io ide0-hqemu-io ide0-hdqemu-io ide0-hd0qemu-io ide0-hd0 qemu-io ide0-hd0 "qemu-io ide0-hd0 "wqemu-io ide0-hd0 "wrqemu-io ide0-hd0 "wriqemu-io ide0-hd0 "writqemu-io ide0-hd0 "writeqemu-io ide0-hd0 "write qemu-io ide0-hd0 "write -qemu-io ide0-hd0 "write -Pqemu-io ide0-hd0 "write -P qemu-io ide0-hd0 "write -P 0qemu-io ide0-hd0 "write -P 0xqemu-io ide0-hd0 "write -P 0x3qemu-io ide0-hd0 "write -P 0x33qemu-io ide0-hd0 "write -P 0x33 qemu-io ide0-hd0 "write -P 0x33 0qemu-io ide0-hd0 "write -P 0x33 0 qemu-io ide0-hd0 "write -P 0x33 0 4qemu-io ide0-hd0 "write -P 0x33 0 4kqemu-io ide0-hd0 "write -P 0x33 0 4k"
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x3qemu-io drive0 "write -P 0x33qemu-io drive0 "write -P 0x33 qemu-io drive0 "write -P 0x33 0qemu-io drive0 "write -P 0x33 0 qemu-io drive0 "write -P 0x33 0 4qemu-io drive0 "write -P 0x33 0 4kqemu-io drive0 "write -P 0x33 0 4k"
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-(qemu) ccocomcommcommicommitcommit commit icommit idcommit idecommit ide0commit ide0-commit ide0-hcommit ide0-hdcommit ide0-hd0
+(qemu) ccocomcommcommicommitcommit commit dcommit drcommit dricommit drivcommit drivecommit drive0
(qemu) qququiquit
read 4096/4096 bytes at offset 0
diff --git a/qemu/tests/qemu-iotests/051.pc.out b/qemu/tests/qemu-iotests/051.pc.out
new file mode 100644
index 000000000..ec6d22229
--- /dev/null
+++ b/qemu/tests/qemu-iotests/051.pc.out
@@ -0,0 +1,525 @@
+QA output created by 051
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
+
+=== Unknown option ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=,if=none,id=drive0
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=,if=none,id=drive0: Block format 'qcow2' does not support the option 'unknown_opt'
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on,if=none,id=drive0
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=on,if=none,id=drive0: Block format 'qcow2' does not support the option 'unknown_opt'
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234,if=none,id=drive0
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=1234,if=none,id=drive0: Block format 'qcow2' does not support the option 'unknown_opt'
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo,if=none,id=drive0
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo,if=none,id=drive0: Block format 'qcow2' does not support the option 'unknown_opt'
+
+
+=== Unknown protocol option ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=: Block protocol 'file' doesn't support the option 'unknown_opt'
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=on
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=on: Block protocol 'file' doesn't support the option 'unknown_opt'
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=1234
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=1234: Block protocol 'file' doesn't support the option 'unknown_opt'
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=foo
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,file.unknown_opt=foo: Block protocol 'file' doesn't support the option 'unknown_opt'
+
+
+=== Invalid format ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=foo
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=foo: Unknown driver 'foo'
+
+Testing: -drive file=TEST_DIR/t.qcow2,driver=foo
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: Unknown driver 'foo'
+
+Testing: -drive file=TEST_DIR/t.qcow2,driver=raw,format=qcow2
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=raw,format=qcow2: Cannot specify both 'driver' and 'format'
+
+Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=qcow2,format=qcow2: Cannot specify both 'driver' and 'format'
+
+
+=== Device without drive ===
+
+Testing: -device virtio-scsi-pci -device scsi-hd
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device scsi-hd: drive property not set
+
+
+=== Overriding backing file ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,driver=qcow2,backing.file.filename=TEST_DIR/t.qcow2.orig,if=none,id=drive0 -nodefaults
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
+drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+ Removable device: not locked, tray closed
+ Cache mode: writeback
+ Backing file: TEST_DIR/t.qcow2.orig (chain depth: 1)
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,driver=raw,backing.file.filename=TEST_DIR/t.qcow2.orig
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=raw,backing.file.filename=TEST_DIR/t.qcow2.orig: Driver doesn't support backing files
+
+Testing: -drive file=TEST_DIR/t.qcow2,file.backing.driver=file,file.backing.filename=TEST_DIR/t.qcow2.orig
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=file,file.backing.filename=TEST_DIR/t.qcow2.orig: Driver doesn't support backing files
+
+Testing: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.file.filename=TEST_DIR/t.qcow2.orig
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.backing.driver=qcow2,file.backing.file.filename=TEST_DIR/t.qcow2.orig: Driver doesn't support backing files
+
+
+=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=: Parameter 'lazy-refcounts' expects 'on' or 'off'
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=42: Parameter 'lazy-refcounts' expects 'on' or 'off'
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=foo: Parameter 'lazy-refcounts' expects 'on' or 'off'
+
+
+=== With version 2 images enabling lazy refcounts must fail ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=on: Lazy refcounts require a qcow2 image with at least qemu 1.1 compatibility level
+
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy-refcounts=off
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+
+=== No medium ===
+
+Testing: -drive if=floppy
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive if=ide,media=cdrom
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive if=scsi,media=cdrom
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive if=ide
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: Device needs media, but drive is empty
+QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
+
+Testing: -drive if=scsi
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: Initialization of device lsi53c895a failed: Device needs media, but drive is empty
+
+Testing: -drive if=virtio
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty
+
+Testing: -drive if=none,id=disk -device ide-cd,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive if=none,id=disk -device ide-drive,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty
+QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
+
+Testing: -drive if=none,id=disk -device ide-hd,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty
+QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
+
+Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty
+
+Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty
+
+
+=== Read-only ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: Can't use a read-only drive
+QEMU_PROG: Initialization of device ide-hd failed: Device initialization failed.
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive
+QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed.
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive
+QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed.
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+
+=== Cache modes ===
+
+Testing: -drive driver=null-co,cache=none
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive driver=null-co,cache=directsync
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive driver=null-co,cache=writeback
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive driver=null-co,cache=writethrough
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive driver=null-co,cache=unsafe
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive driver=null-co,cache=invalid_value
+QEMU_PROG: -drive driver=null-co,cache=invalid_value: invalid cache option
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
+drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+ Removable device: not locked, tray closed
+ Cache mode: writeback
+ Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
+
+file: TEST_DIR/t.qcow2 (file)
+ Cache mode: writeback
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
+backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
+ Cache mode: writeback, ignore flushes
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
+
+backing-file: TEST_DIR/t.qcow2.base (file, read-only)
+ Cache mode: writeback, ignore flushes
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
+drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+ Removable device: not locked, tray closed
+ Cache mode: writethrough
+ Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
+
+file: TEST_DIR/t.qcow2 (file)
+ Cache mode: writeback
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
+backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
+ Cache mode: writeback, ignore flushes
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
+
+backing-file: TEST_DIR/t.qcow2.base (file, read-only)
+ Cache mode: writeback, ignore flushes
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo block
+drive0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2)
+ Removable device: not locked, tray closed
+ Cache mode: writeback, ignore flushes
+ Backing file: TEST_DIR/t.qcow2.base (chain depth: 1)
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block finfo block fiinfo block filinfo block file
+
+file: TEST_DIR/t.qcow2 (file)
+ Cache mode: writeback, ignore flushes
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backing
+backing: TEST_DIR/t.qcow2.base (qcow2, read-only)
+ Cache mode: writeback, ignore flushes
+(qemu) iininfinfoinfo info binfo blinfo bloinfo blocinfo blockinfo block info block binfo block bainfo block bacinfo block backinfo block backiinfo block backininfo block backinginfo block backing-info block backing-finfo block backing-fiinfo block backing-filinfo block backing-file
+
+backing-file: TEST_DIR/t.qcow2.base (file, read-only)
+ Cache mode: writeback, ignore flushes
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0 -nodefaults
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value,backing.file.filename=TEST_DIR/t.qcow2.base,backing.cache.no-flush=on,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,if=none,id=drive0: invalid cache option
+
+
+=== Specifying the protocol layer ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+
+=== Leaving out required options ===
+
+Testing: -drive driver=file
+QEMU_PROG: -drive driver=file: The 'file' block driver requires a file name
+
+Testing: -drive driver=nbd
+QEMU_PROG: -drive driver=nbd: one of path and host must be specified.
+
+Testing: -drive driver=raw
+QEMU_PROG: -drive driver=raw: Can't use 'raw' as a block driver for the protocol level
+
+Testing: -drive file.driver=file
+QEMU_PROG: -drive file.driver=file: The 'file' block driver requires a file name
+
+Testing: -drive file.driver=nbd
+QEMU_PROG: -drive file.driver=nbd: one of path and host must be specified.
+
+Testing: -drive file.driver=raw
+QEMU_PROG: -drive file.driver=raw: Can't use 'raw' as a block driver for the protocol level
+
+Testing: -drive foo=bar
+QEMU_PROG: -drive foo=bar: Must specify either driver or file
+
+
+=== Specifying both an option and its legacy alias ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,iops=1234,throttling.iops-total=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops=1234,throttling.iops-total=5678: 'throttling.iops-total' and its alias 'iops' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,iops_rd=1234,throttling.iops-read=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_rd=1234,throttling.iops-read=5678: 'throttling.iops-read' and its alias 'iops_rd' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,iops_wr=1234,throttling.iops-write=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_wr=1234,throttling.iops-write=5678: 'throttling.iops-write' and its alias 'iops_wr' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=1234,throttling.bps-total=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=1234,throttling.bps-total=5678: 'throttling.bps-total' and its alias 'bps' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps_rd=1234,throttling.bps-read=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_rd=1234,throttling.bps-read=5678: 'throttling.bps-read' and its alias 'bps_rd' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps_wr=1234,throttling.bps-write=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_wr=1234,throttling.bps-write=5678: 'throttling.bps-write' and its alias 'bps_wr' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,iops_max=1234,throttling.iops-total-max=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_max=1234,throttling.iops-total-max=5678: 'throttling.iops-total-max' and its alias 'iops_max' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,iops_rd_max=1234,throttling.iops-read-max=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_rd_max=1234,throttling.iops-read-max=5678: 'throttling.iops-read-max' and its alias 'iops_rd_max' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,iops_wr_max=1234,throttling.iops-write-max=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_wr_max=1234,throttling.iops-write-max=5678: 'throttling.iops-write-max' and its alias 'iops_wr_max' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps_max=1234,throttling.bps-total-max=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_max=1234,throttling.bps-total-max=5678: 'throttling.bps-total-max' and its alias 'bps_max' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps_rd_max=1234,throttling.bps-read-max=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_rd_max=1234,throttling.bps-read-max=5678: 'throttling.bps-read-max' and its alias 'bps_rd_max' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps_wr_max=1234,throttling.bps-write-max=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_wr_max=1234,throttling.bps-write-max=5678: 'throttling.bps-write-max' and its alias 'bps_wr_max' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,iops_size=1234,throttling.iops-size=5678
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops_size=1234,throttling.iops-size=5678: 'throttling.iops-size' and its alias 'iops_size' can't be used at the same time
+
+Testing: -drive file=TEST_DIR/t.qcow2,readonly=on,read-only=off
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,readonly=on,read-only=off: 'read-only' and its alias 'readonly' can't be used at the same time
+
+
+=== Catching negative/large throttling values ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,iops=-1
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,iops=-1: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=-2
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=-2: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps_rd=-3
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_rd=-3: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps_rd_max=-3
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps_rd_max=-3: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,throttling.iops-total=-4
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,throttling.iops-total=-4: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,throttling.bps-total=-5
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,throttling.bps-total=-5: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=0
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=1
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=1000000000000000
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=1000000000000001
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=1000000000000001: bps/iops/max values must be within [0, 1000000000000000]
+
+Testing: -drive file=TEST_DIR/t.qcow2,bps=9999999999999999
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,bps=9999999999999999: bps/iops/max values must be within [0, 1000000000000000]
+
+
+=== Parsing protocol from file name ===
+
+Testing: -hda foo:bar
+QEMU_PROG: -hda foo:bar: Unknown protocol 'foo'
+
+Testing: -drive file=foo:bar
+QEMU_PROG: -drive file=foo:bar: Unknown protocol 'foo'
+
+Testing: -drive file.filename=foo:bar
+QEMU_PROG: -drive file.filename=foo:bar: Could not open 'foo:bar': No such file or directory
+
+Testing: -hda file:TEST_DIR/t.qcow2
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=file:TEST_DIR/t.qcow2
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file.filename=file:TEST_DIR/t.qcow2
+QEMU_PROG: -drive file.filename=file:TEST_DIR/t.qcow2: Could not open 'file:TEST_DIR/t.qcow2': No such file or directory
+
+
+=== Snapshot mode ===
+
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,snapshot=on,if=none,id=drive0
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file.filename=TEST_DIR/t.qcow2,driver=qcow2,if=none,id=drive0 -snapshot
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file=file:TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file=file:TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0 -snapshot
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+read 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=off,if=none,id=drive0
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x2qemu-io drive0 "write -P 0x22qemu-io drive0 "write -P 0x22 qemu-io drive0 "write -P 0x22 0qemu-io drive0 "write -P 0x22 0 qemu-io drive0 "write -P 0x22 0 4qemu-io drive0 "write -P 0x22 0 4kqemu-io drive0 "write -P 0x22 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) qququiquit
+
+read 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,if=none,id=drive0
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qqeqemqemuqemu-qemu-iqemu-ioqemu-io qemu-io dqemu-io drqemu-io driqemu-io drivqemu-io driveqemu-io drive0qemu-io drive0 qemu-io drive0 "qemu-io drive0 "wqemu-io drive0 "wrqemu-io drive0 "wriqemu-io drive0 "writqemu-io drive0 "writeqemu-io drive0 "write qemu-io drive0 "write -qemu-io drive0 "write -Pqemu-io drive0 "write -P qemu-io drive0 "write -P 0qemu-io drive0 "write -P 0xqemu-io drive0 "write -P 0x3qemu-io drive0 "write -P 0x33qemu-io drive0 "write -P 0x33 qemu-io drive0 "write -P 0x33 0qemu-io drive0 "write -P 0x33 0 qemu-io drive0 "write -P 0x33 0 4qemu-io drive0 "write -P 0x33 0 4kqemu-io drive0 "write -P 0x33 0 4k"
+wrote 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+(qemu) ccocomcommcommicommitcommit commit dcommit drcommit dricommit drivcommit drivecommit drive0
+(qemu) qququiquit
+
+read 4096/4096 bytes at offset 0
+4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/qemu/tests/qemu-iotests/052 b/qemu/tests/qemu-iotests/052
index 61959e286..4b647242d 100755
--- a/qemu/tests/qemu-iotests/052
+++ b/qemu/tests/qemu-iotests/052
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/053 b/qemu/tests/qemu-iotests/053
index e589e5f12..2a04f5f55 100755
--- a/qemu/tests/qemu-iotests/053
+++ b/qemu/tests/qemu-iotests/053
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/054 b/qemu/tests/qemu-iotests/054
index bd94153d6..bf47ef9fa 100755
--- a/qemu/tests/qemu-iotests/054
+++ b/qemu/tests/qemu-iotests/054
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/055 b/qemu/tests/qemu-iotests/055
index 017a609f3..c8e357870 100755
--- a/qemu/tests/qemu-iotests/055
+++ b/qemu/tests/qemu-iotests/055
@@ -42,6 +42,8 @@ class TestSingleDrive(iotests.QMPTestCase):
qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
+ if iotests.qemu_default_machine == 'pc':
+ self.vm.add_drive(None, 'media=cdrom', 'ide')
self.vm.launch()
def tearDown(self):
@@ -104,12 +106,18 @@ class TestSingleDrive(iotests.QMPTestCase):
self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
def test_medium_not_found(self):
- result = self.vm.qmp('drive-backup', device='ide1-cd0',
+ if iotests.qemu_default_machine != 'pc':
+ return
+
+ result = self.vm.qmp('drive-backup', device='drive2', # CD-ROM
target=target_img, sync='full')
self.assert_qmp(result, 'error/class', 'GenericError')
def test_medium_not_found_blockdev_backup(self):
- result = self.vm.qmp('blockdev-backup', device='ide1-cd0',
+ if iotests.qemu_default_machine != 'pc':
+ return
+
+ result = self.vm.qmp('blockdev-backup', device='drive2', # CD-ROM
target='drive1', sync='full')
self.assert_qmp(result, 'error/class', 'GenericError')
@@ -249,6 +257,8 @@ class TestSingleTransaction(iotests.QMPTestCase):
qemu_img('create', '-f', iotests.imgfmt, blockdev_target_img, str(TestSingleDrive.image_len))
self.vm = iotests.VM().add_drive(test_img).add_drive(blockdev_target_img)
+ if iotests.qemu_default_machine == 'pc':
+ self.vm.add_drive(None, 'media=cdrom', 'ide')
self.vm.launch()
def tearDown(self):
@@ -323,9 +333,12 @@ class TestSingleTransaction(iotests.QMPTestCase):
self.do_test_pause('blockdev-backup', 'drive1', blockdev_target_img)
def do_test_medium_not_found(self, cmd, target):
+ if iotests.qemu_default_machine != 'pc':
+ return
+
result = self.vm.qmp('transaction', actions=[{
'type': cmd,
- 'data': { 'device': 'ide1-cd0',
+ 'data': { 'device': 'drive2', # CD-ROM
'target': target,
'sync': 'full' },
}
diff --git a/qemu/tests/qemu-iotests/056 b/qemu/tests/qemu-iotests/056
index 54e4bd069..04f2c3c84 100755
--- a/qemu/tests/qemu-iotests/056
+++ b/qemu/tests/qemu-iotests/056
@@ -82,6 +82,31 @@ class TestSyncModesNoneAndTop(iotests.QMPTestCase):
time.sleep(1)
self.assertEqual(-1, qemu_io('-c', 'read -P0x41 0 512', target_img).find("verification failed"))
+class TestBeforeWriteNotifier(iotests.QMPTestCase):
+ def setUp(self):
+ self.vm = iotests.VM().add_drive_raw("file=blkdebug::null-co://,id=drive0,align=65536,driver=blkdebug")
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(target_img)
+
+ def test_before_write_notifier(self):
+ self.vm.pause_drive("drive0")
+ result = self.vm.qmp('drive-backup', device='drive0',
+ sync='full', target=target_img,
+ format="file", speed=1)
+ self.assert_qmp(result, 'return', {})
+ result = self.vm.qmp('block-job-pause', device="drive0")
+ self.assert_qmp(result, 'return', {})
+ # Speed is low enough that this must be an uncopied range, which will
+ # trigger the before write notifier
+ self.vm.hmp_qemu_io('drive0', 'aio_write -P 1 512512 512')
+ self.vm.resume_drive("drive0")
+ result = self.vm.qmp('block-job-resume', device="drive0")
+ self.assert_qmp(result, 'return', {})
+ event = self.cancel_and_wait()
+ self.assert_qmp(event, 'data/type', 'backup')
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/qemu/tests/qemu-iotests/056.out b/qemu/tests/qemu-iotests/056.out
index fbc63e62f..8d7e99670 100644
--- a/qemu/tests/qemu-iotests/056.out
+++ b/qemu/tests/qemu-iotests/056.out
@@ -1,5 +1,5 @@
-..
+...
----------------------------------------------------------------------
-Ran 2 tests
+Ran 3 tests
OK
diff --git a/qemu/tests/qemu-iotests/058 b/qemu/tests/qemu-iotests/058
index f2bdd0bff..2253c6a6d 100755
--- a/qemu/tests/qemu-iotests/058
+++ b/qemu/tests/qemu-iotests/058
@@ -27,16 +27,21 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
nbd_unix_socket=$TEST_DIR/test_qemu_nbd_socket
nbd_snapshot_img="nbd:unix:$nbd_unix_socket"
+rm -f "${TEST_DIR}/qemu-nbd.pid"
_cleanup_nbd()
{
- if [ -n "$NBD_SNAPSHOT_PID" ]; then
- kill "$NBD_SNAPSHOT_PID"
+ local NBD_SNAPSHOT_PID
+ if [ -f "${TEST_DIR}/qemu-nbd.pid" ]; then
+ read NBD_SNAPSHOT_PID < "${TEST_DIR}/qemu-nbd.pid"
+ rm -f "${TEST_DIR}/qemu-nbd.pid"
+ if [ -n "$NBD_SNAPSHOT_PID" ]; then
+ kill "$NBD_SNAPSHOT_PID"
+ fi
fi
rm -f "$nbd_unix_socket"
}
@@ -60,7 +65,6 @@ _export_nbd_snapshot()
{
_cleanup_nbd
$QEMU_NBD -v -t -k "$nbd_unix_socket" "$TEST_IMG" -l $1 &
- NBD_SNAPSHOT_PID=$!
_wait_for_nbd
}
@@ -68,7 +72,6 @@ _export_nbd_snapshot1()
{
_cleanup_nbd
$QEMU_NBD -v -t -k "$nbd_unix_socket" "$TEST_IMG" -l snapshot.name=$1 &
- NBD_SNAPSHOT_PID=$!
_wait_for_nbd
}
diff --git a/qemu/tests/qemu-iotests/059 b/qemu/tests/qemu-iotests/059
index 0ded0c3da..6655aaf38 100755
--- a/qemu/tests/qemu-iotests/059
+++ b/qemu/tests/qemu-iotests/059
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -133,6 +132,16 @@ $QEMU_IO -c "write -P 0xa 900G 512" "$TEST_IMG" | _filter_qemu_io
$QEMU_IO -c "read -v 900G 1024" "$TEST_IMG" | _filter_qemu_io
echo
+echo "=== Testing qemu-img map on extents ==="
+for fmt in monolithicSparse twoGbMaxExtentSparse; do
+ IMGOPTS="subformat=$fmt" _make_test_img 31G
+ $QEMU_IO -c "write 65024 1k" "$TEST_IMG" | _filter_qemu_io
+ $QEMU_IO -c "write 2147483136 1k" "$TEST_IMG" | _filter_qemu_io
+ $QEMU_IO -c "write 5G 1k" "$TEST_IMG" | _filter_qemu_io
+ $QEMU_IMG map "$TEST_IMG" | _filter_testdir
+done
+
+echo
echo "=== Testing afl image with a very large capacity ==="
_use_sample_img afl9.vmdk.bz2
_img_info
diff --git a/qemu/tests/qemu-iotests/059.out b/qemu/tests/qemu-iotests/059.out
index 67e3cf57e..678adb437 100644
--- a/qemu/tests/qemu-iotests/059.out
+++ b/qemu/tests/qemu-iotests/059.out
@@ -2,31 +2,31 @@ QA output created by 059
=== Testing invalid granularity ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.vmdk: Invalid granularity, image may be corrupt
+can't open device TEST_DIR/t.vmdk: Invalid granularity, image may be corrupt
no file open, try 'help open'
=== Testing too big L2 table size ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.vmdk: L2 table size too big
+can't open device TEST_DIR/t.vmdk: L2 table size too big
no file open, try 'help open'
=== Testing too big L1 table size ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.vmdk: L1 size too big
+can't open device TEST_DIR/t.vmdk: L1 size too big
no file open, try 'help open'
=== Testing monolithicFlat creation and opening ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 subformat=monolithicFlat
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 2.0G (2147483648 bytes)
=== Testing monolithicFlat with zeroed_grain ===
qemu-img: TEST_DIR/t.IMGFMT: Flat image can't enable zeroed grain
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=2147483648 subformat=monolithicFlat
=== Testing big twoGbMaxExtentFlat ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMaxExtentFlat
image: TEST_DIR/t.vmdk
file format: vmdk
virtual size: 1.0T (1073741824000 bytes)
@@ -2038,12 +2038,10 @@ Format specific information:
format: FLAT
=== Testing malformed VMFS extent description line ===
-qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Invalid extent lines:
-RW 12582912 VMFS "dummy.IMGFMT" 1
-
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Invalid extent line: RW 12582912 VMFS "dummy.IMGFMT" 1
=== Testing truncated sparse ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=107374182400
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=107374182400 subformat=monolithicSparse
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': File truncated, expecting at least 13172736 bytes
=== Converting to streamOptimized from image with small cluster size===
@@ -2054,8 +2052,8 @@ wrote 512/512 bytes at offset 10240
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Testing monolithicFlat with internally generated JSON file name ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open: Cannot use relative extent paths with VMDK descriptor file 'json:{"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "read_aio"}'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 subformat=monolithicFlat
+can't open: Cannot use relative extent paths with VMDK descriptor file 'json:{"image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "inject-error.0.event": "read_aio"}'
=== Testing version 3 ===
image: TEST_DIR/iotest-version3.IMGFMT
@@ -2264,7 +2262,7 @@ read 512/512 bytes at offset 64931328
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Testing 4TB monolithicFlat creation and IO ===
-Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=4398046511104
+Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=4398046511104 subformat=monolithicFlat
image: TEST_DIR/iotest-version3.IMGFMT
file format: IMGFMT
virtual size: 4.0T (4398046511104 bytes)
@@ -2337,6 +2335,31 @@ e1000003f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
read 1024/1024 bytes at offset 966367641600
1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== Testing qemu-img map on extents ===
+Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=33285996544 subformat=monolithicSparse
+wrote 1024/1024 bytes at offset 65024
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 2147483136
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 5368709120
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Offset Length Mapped to File
+0 0x20000 0x3f0000 TEST_DIR/iotest-version3.vmdk
+0x7fff0000 0x20000 0x410000 TEST_DIR/iotest-version3.vmdk
+0x140000000 0x10000 0x430000 TEST_DIR/iotest-version3.vmdk
+Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=33285996544 subformat=twoGbMaxExtentSparse
+wrote 1024/1024 bytes at offset 65024
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 2147483136
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 1024/1024 bytes at offset 5368709120
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Offset Length Mapped to File
+0 0x20000 0x50000 TEST_DIR/iotest-version3-s001.vmdk
+0x7fff0000 0x10000 0x70000 TEST_DIR/iotest-version3-s001.vmdk
+0x80000000 0x10000 0x50000 TEST_DIR/iotest-version3-s002.vmdk
+0x140000000 0x10000 0x50000 TEST_DIR/iotest-version3-s003.vmdk
+
=== Testing afl image with a very large capacity ===
qemu-img: Can't get size of device 'image': File too large
*** done
diff --git a/qemu/tests/qemu-iotests/060 b/qemu/tests/qemu-iotests/060
index c81319c16..8e95c450e 100755
--- a/qemu/tests/qemu-iotests/060
+++ b/qemu/tests/qemu-iotests/060
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/060.out b/qemu/tests/qemu-iotests/060.out
index 751118951..5d40206ef 100644
--- a/qemu/tests/qemu-iotests/060.out
+++ b/qemu/tests/qemu-iotests/060.out
@@ -20,7 +20,7 @@ Format specific information:
lazy refcounts: false
refcount bits: 16
corrupt: true
-qemu-io: can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write
+can't open device TEST_DIR/t.IMGFMT: IMGFMT: Image is corrupt; cannot be opened read/write
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/qemu/tests/qemu-iotests/061 b/qemu/tests/qemu-iotests/061
index 8d37f8a65..f5678b10c 100755
--- a/qemu/tests/qemu-iotests/061
+++ b/qemu/tests/qemu-iotests/061
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -58,7 +57,8 @@ echo
echo "=== Testing dirty version downgrade ==="
echo
IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
-$QEMU_IO -c "write -P 0x2a 0 128k" -c flush -c abort "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x2a 0 128k" -c flush \
+ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io
$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
$PYTHON qcow2.py "$TEST_IMG" dump-header
@@ -91,7 +91,8 @@ echo
echo "=== Testing dirty lazy_refcounts=off ==="
echo
IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
-$QEMU_IO -c "write -P 0x2a 0 128k" -c flush -c abort "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x2a 0 128k" -c flush \
+ -c "sigraise $(kill -l KILL)" "$TEST_IMG" 2>&1 | _filter_qemu_io
$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IMG amend -o "lazy_refcounts=off" "$TEST_IMG"
$PYTHON qcow2.py "$TEST_IMG" dump-header
diff --git a/qemu/tests/qemu-iotests/061.out b/qemu/tests/qemu-iotests/061.out
index 5ec248f79..a03732e19 100644
--- a/qemu/tests/qemu-iotests/061.out
+++ b/qemu/tests/qemu-iotests/061.out
@@ -24,6 +24,11 @@ autoclear_features 0x0
refcount_order 4
header_length 104
+Header extension:
+magic 0x6803f857
+length 144
+data <binary>
+
magic 0x514649fb
version 2
backing_file_offset 0x0
@@ -43,11 +48,6 @@ autoclear_features 0x0
refcount_order 4
header_length 72
-Header extension:
-magic 0x6803f857
-length 144
-data <binary>
-
read 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
@@ -57,6 +57,11 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+else
+ exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+fi )
magic 0x514649fb
version 3
backing_file_offset 0x0
@@ -76,6 +81,11 @@ autoclear_features 0x0
refcount_order 4
header_length 104
+Header extension:
+magic 0x6803f857
+length 144
+data <binary>
+
ERROR cluster 5 refcount=0 reference=1
ERROR cluster 6 refcount=0 reference=1
Rebuilding refcount structure
@@ -100,11 +110,6 @@ autoclear_features 0x0
refcount_order 4
header_length 72
-Header extension:
-magic 0x6803f857
-length 144
-data <binary>
-
read 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
@@ -131,6 +136,11 @@ autoclear_features 0x40000000000
refcount_order 4
header_length 104
+Header extension:
+magic 0x6803f857
+length 144
+data <binary>
+
magic 0x514649fb
version 2
backing_file_offset 0x0
@@ -150,11 +160,6 @@ autoclear_features 0x0
refcount_order 4
header_length 72
-Header extension:
-magic 0x6803f857
-length 144
-data <binary>
-
No errors were found on the image.
=== Testing version upgrade and resize ===
@@ -214,6 +219,11 @@ No errors were found on the image.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+else
+ exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+fi )
magic 0x514649fb
version 3
backing_file_offset 0x0
@@ -233,6 +243,11 @@ autoclear_features 0x0
refcount_order 4
header_length 104
+Header extension:
+magic 0x6803f857
+length 144
+data <binary>
+
ERROR cluster 5 refcount=0 reference=1
ERROR cluster 6 refcount=0 reference=1
Rebuilding refcount structure
@@ -281,18 +296,18 @@ No errors were found on the image.
=== Testing invalid configurations ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
+qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
qemu-img: Error while amending options: Invalid argument
-Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
+qemu-img: Lazy refcounts only supported with compatibility level 1.1 and above (use compat=1.1 or greater)
qemu-img: Error while amending options: Invalid argument
-Unknown compatibility level 0.42.
+qemu-img: Unknown compatibility level 0.42
qemu-img: Error while amending options: Invalid argument
qemu-img: Invalid parameter 'foo'
-Changing the cluster size is not supported.
+qemu-img: Changing the cluster size is not supported
qemu-img: Error while amending options: Operation not supported
-Changing the encryption flag is not supported.
+qemu-img: Changing the encryption flag is not supported
qemu-img: Error while amending options: Operation not supported
-Cannot change preallocation mode.
+qemu-img: Cannot change preallocation mode
qemu-img: Error while amending options: Operation not supported
=== Testing correct handling of unset value ===
@@ -300,7 +315,7 @@ qemu-img: Error while amending options: Operation not supported
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Should work:
Should not work:
-Changing the cluster size is not supported.
+qemu-img: Changing the cluster size is not supported
qemu-img: Error while amending options: Operation not supported
=== Testing zero expansion on inactive clusters ===
@@ -334,7 +349,7 @@ read 131072/131072 bytes at offset 0
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
read 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 0
@@ -350,7 +365,7 @@ read 65536/65536 bytes at offset 65536
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 0
@@ -369,7 +384,7 @@ read 65536/65536 bytes at offset 65536
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 131072/131072 bytes at offset 0
128 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
@@ -393,7 +408,7 @@ read 67108864/67108864 bytes at offset 0
=== Testing progress report without snapshot ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4294967296
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 1073741824
@@ -408,7 +423,7 @@ No errors were found on the image.
=== Testing progress report with snapshot ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=4294967296
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 65536/65536 bytes at offset 1073741824
diff --git a/qemu/tests/qemu-iotests/062 b/qemu/tests/qemu-iotests/062
index 0511246de..051fb9f41 100755
--- a/qemu/tests/qemu-iotests/062
+++ b/qemu/tests/qemu-iotests/062
@@ -26,7 +26,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/063 b/qemu/tests/qemu-iotests/063
index a47493a07..352e78c77 100755
--- a/qemu/tests/qemu-iotests/063
+++ b/qemu/tests/qemu-iotests/063
@@ -26,7 +26,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/064 b/qemu/tests/qemu-iotests/064
index 7564563ab..5792fbbc9 100755
--- a/qemu/tests/qemu-iotests/064
+++ b/qemu/tests/qemu-iotests/064
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/066 b/qemu/tests/qemu-iotests/066
index 1c2452b0c..364166d3b 100755
--- a/qemu/tests/qemu-iotests/066
+++ b/qemu/tests/qemu-iotests/066
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/067 b/qemu/tests/qemu-iotests/067
index 83eefa394..c1df48ede 100755
--- a/qemu/tests/qemu-iotests/067
+++ b/qemu/tests/qemu-iotests/067
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
# get standard environment, filters and checks
@@ -45,10 +44,20 @@ function do_run_qemu()
echo
}
+# Remove QMP events from (pretty-printed) output. Doesn't handle
+# nested dicts correctly, but we don't get any of those in this test.
+_filter_qmp_events()
+{
+ tr '\n' '\t' | sed -e \
+ 's/{\s*"timestamp":\s*{[^}]*},\s*"event":[^,}]*\(,\s*"data":\s*{[^}]*}\)\?\s*}\s*//g' \
+ | tr '\t' '\n'
+}
+
function run_qemu()
{
do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | _filter_qemu \
- | sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g'
+ | sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g' \
+ | _filter_generated_node_ids | _filter_qmp_events
}
size=128M
@@ -59,7 +68,7 @@ echo
echo === -drive/-device and device_del ===
echo
-run_qemu -drive file=$TEST_IMG,format=$IMGFMT,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0 <<EOF
+run_qemu -drive file=$TEST_IMG,format=$IMGFMT,if=none,id=disk -device virtio-blk,drive=disk,id=virtio0 <<EOF
{ "execute": "qmp_capabilities" }
{ "execute": "query-block" }
{ "execute": "device_del", "arguments": { "id": "virtio0" } }
@@ -76,7 +85,7 @@ run_qemu -drive file=$TEST_IMG,format=$IMGFMT,if=none,id=disk <<EOF
{ "execute": "qmp_capabilities" }
{ "execute": "query-block" }
{ "execute": "device_add",
- "arguments": { "driver": "virtio-blk-pci", "drive": "disk",
+ "arguments": { "driver": "virtio-blk", "drive": "disk",
"id": "virtio0" } }
{ "execute": "device_del", "arguments": { "id": "virtio0" } }
{ "execute": "system_reset" }
@@ -94,7 +103,7 @@ run_qemu <<EOF
"arguments": { "command-line": "drive_add 0 file=$TEST_IMG,format=$IMGFMT,if=none,id=disk" } }
{ "execute": "query-block" }
{ "execute": "device_add",
- "arguments": { "driver": "virtio-blk-pci", "drive": "disk",
+ "arguments": { "driver": "virtio-blk", "drive": "disk",
"id": "virtio0" } }
{ "execute": "device_del", "arguments": { "id": "virtio0" } }
{ "execute": "system_reset" }
@@ -122,7 +131,7 @@ run_qemu <<EOF
}
{ "execute": "query-block" }
{ "execute": "device_add",
- "arguments": { "driver": "virtio-blk-pci", "drive": "disk",
+ "arguments": { "driver": "virtio-blk", "drive": "disk",
"id": "virtio0" } }
{ "execute": "device_del", "arguments": { "id": "virtio0" } }
{ "execute": "system_reset" }
diff --git a/qemu/tests/qemu-iotests/067.out b/qemu/tests/qemu-iotests/067.out
index 6ff41bc7a..7e25a4902 100644
--- a/qemu/tests/qemu-iotests/067.out
+++ b/qemu/tests/qemu-iotests/067.out
@@ -3,7 +3,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
=== -drive/-device and device_del ===
-Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0
+Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virtio-blk,drive=disk,id=virtio0
{
QMP_VERSION
}
@@ -40,6 +40,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
},
"iops_wr": 0,
"ro": false,
+ "node-name": "NODE_NAME",
"backing_file_depth": 0,
"drv": "qcow2",
"iops": 0,
@@ -57,28 +58,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
"encryption_key_missing": false
},
"type": "unknown"
- },
- {
- "io-status": "ok",
- "device": "ide1-cd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "floppy0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "sd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
}
]
}
@@ -91,93 +70,13 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virti
}
}
{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_DELETED",
- "data": {
- "path": "/machine/peripheral/virtio0/virtio-backend"
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_DELETED",
- "data": {
- "device": "virtio0",
- "path": "/machine/peripheral/virtio0"
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "RESET"
-}
-{
"return": [
- {
- "io-status": "ok",
- "device": "ide1-cd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "floppy0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "sd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- }
]
}
{
"return": {
}
}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "SHUTDOWN"
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_TRAY_MOVED",
- "data": {
- "device": "ide1-cd0",
- "tray-open": true
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_TRAY_MOVED",
- "data": {
- "device": "floppy0",
- "tray-open": true
- }
-}
-
=== -drive/device_add and device_del ===
@@ -217,6 +116,7 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
},
"iops_wr": 0,
"ro": false,
+ "node-name": "NODE_NAME",
"backing_file_depth": 0,
"drv": "qcow2",
"iops": 0,
@@ -233,29 +133,6 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
- "tray_open": false,
- "type": "unknown"
- },
- {
- "io-status": "ok",
- "device": "ide1-cd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "floppy0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "sd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
"type": "unknown"
}
]
@@ -273,93 +150,13 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
}
}
{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_DELETED",
- "data": {
- "path": "/machine/peripheral/virtio0/virtio-backend"
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_DELETED",
- "data": {
- "device": "virtio0",
- "path": "/machine/peripheral/virtio0"
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "RESET"
-}
-{
"return": [
- {
- "io-status": "ok",
- "device": "ide1-cd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "floppy0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "sd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- }
]
}
{
"return": {
}
}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "SHUTDOWN"
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_TRAY_MOVED",
- "data": {
- "device": "ide1-cd0",
- "tray-open": true
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_TRAY_MOVED",
- "data": {
- "device": "floppy0",
- "tray-open": true
- }
-}
-
=== drive_add/device_add and device_del ===
@@ -377,28 +174,6 @@ Testing:
{
"return": [
{
- "io-status": "ok",
- "device": "ide1-cd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "floppy0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "sd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
"device": "disk",
"locked": false,
"removable": true,
@@ -424,6 +199,7 @@ Testing:
},
"iops_wr": 0,
"ro": false,
+ "node-name": "NODE_NAME",
"backing_file_depth": 0,
"drv": "qcow2",
"iops": 0,
@@ -440,7 +216,6 @@ Testing:
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
- "tray_open": false,
"type": "unknown"
}
]
@@ -458,93 +233,13 @@ Testing:
}
}
{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_DELETED",
- "data": {
- "path": "/machine/peripheral/virtio0/virtio-backend"
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_DELETED",
- "data": {
- "device": "virtio0",
- "path": "/machine/peripheral/virtio0"
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "RESET"
-}
-{
"return": [
- {
- "io-status": "ok",
- "device": "ide1-cd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "floppy0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "sd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- }
]
}
{
"return": {
}
}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "SHUTDOWN"
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_TRAY_MOVED",
- "data": {
- "device": "ide1-cd0",
- "tray-open": true
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_TRAY_MOVED",
- "data": {
- "device": "floppy0",
- "tray-open": true
- }
-}
-
=== blockdev_add/device_add and device_del ===
@@ -563,28 +258,6 @@ Testing:
{
"return": [
{
- "io-status": "ok",
- "device": "ide1-cd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "floppy0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "sd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
"device": "disk",
"locked": false,
"removable": true,
@@ -610,6 +283,7 @@ Testing:
},
"iops_wr": 0,
"ro": false,
+ "node-name": "NODE_NAME",
"backing_file_depth": 0,
"drv": "qcow2",
"iops": 0,
@@ -626,7 +300,6 @@ Testing:
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
- "tray_open": false,
"type": "unknown"
}
]
@@ -644,59 +317,9 @@ Testing:
}
}
{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_DELETED",
- "data": {
- "path": "/machine/peripheral/virtio0/virtio-backend"
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_DELETED",
- "data": {
- "device": "virtio0",
- "path": "/machine/peripheral/virtio0"
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "RESET"
-}
-{
"return": [
{
"io-status": "ok",
- "device": "ide1-cd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "floppy0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "device": "sd0",
- "locked": false,
- "removable": true,
- "tray_open": false,
- "type": "unknown"
- },
- {
- "io-status": "ok",
"device": "disk",
"locked": false,
"removable": true,
@@ -722,6 +345,7 @@ Testing:
},
"iops_wr": 0,
"ro": false,
+ "node-name": "NODE_NAME",
"backing_file_depth": 0,
"drv": "qcow2",
"iops": 0,
@@ -738,7 +362,6 @@ Testing:
"file": "TEST_DIR/t.qcow2",
"encryption_key_missing": false
},
- "tray_open": false,
"type": "unknown"
}
]
@@ -747,34 +370,4 @@ Testing:
"return": {
}
}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "SHUTDOWN"
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_TRAY_MOVED",
- "data": {
- "device": "ide1-cd0",
- "tray-open": true
- }
-}
-{
- "timestamp": {
- "seconds": TIMESTAMP,
- "microseconds": TIMESTAMP
- },
- "event": "DEVICE_TRAY_MOVED",
- "data": {
- "device": "floppy0",
- "tray-open": true
- }
-}
-
*** done
diff --git a/qemu/tests/qemu-iotests/068 b/qemu/tests/qemu-iotests/068
index b72e55599..68f6e825d 100755
--- a/qemu/tests/qemu-iotests/068
+++ b/qemu/tests/qemu-iotests/068
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -50,13 +49,23 @@ echo
echo "=== Saving and reloading a VM state to/from a qcow2 image ==="
echo
_make_test_img $IMG_SIZE
+
+case "$QEMU_DEFAULT_MACHINE" in
+ s390-ccw-virtio)
+ platform_parm="-no-shutdown"
+ ;;
+ *)
+ platform_parm=""
+ ;;
+esac
+
# Give qemu some time to boot before saving the VM state
bash -c 'sleep 1; echo -e "savevm 0\nquit"' |\
- $QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" |\
+ $QEMU $platform_parm -nographic -monitor stdio -serial none -hda "$TEST_IMG" |\
_filter_qemu
# Now try to continue from that VM state (this should just work)
echo quit |\
- $QEMU -nographic -monitor stdio -serial none -hda "$TEST_IMG" -loadvm 0 |\
+ $QEMU $platform_parm -nographic -monitor stdio -serial none -hda "$TEST_IMG" -loadvm 0 |\
_filter_qemu
# success, all done
diff --git a/qemu/tests/qemu-iotests/069 b/qemu/tests/qemu-iotests/069
index ce9e0541b..96e55ef21 100755
--- a/qemu/tests/qemu-iotests/069
+++ b/qemu/tests/qemu-iotests/069
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/069.out b/qemu/tests/qemu-iotests/069.out
index 4d7e63cf8..f97585677 100644
--- a/qemu/tests/qemu-iotests/069.out
+++ b/qemu/tests/qemu-iotests/069.out
@@ -3,6 +3,6 @@ QA output created by 069
=== Creating an image with a backing file and deleting that file ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=131072
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file='TEST_DIR/t.IMGFMT.base'
-qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open backing file: Could not open 'TEST_DIR/t.IMGFMT.base': No such file or directory
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072 backing_file=TEST_DIR/t.IMGFMT.base
+can't open device TEST_DIR/t.IMGFMT: Could not open backing file: Could not open 'TEST_DIR/t.IMGFMT.base': No such file or directory
*** done
diff --git a/qemu/tests/qemu-iotests/070 b/qemu/tests/qemu-iotests/070
index d649ddf9b..8d08d74ff 100755
--- a/qemu/tests/qemu-iotests/070
+++ b/qemu/tests/qemu-iotests/070
@@ -26,7 +26,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/070.out b/qemu/tests/qemu-iotests/070.out
index ca743831c..131a5b17d 100644
--- a/qemu/tests/qemu-iotests/070.out
+++ b/qemu/tests/qemu-iotests/070.out
@@ -1,8 +1,9 @@
QA output created by 070
=== Verify open image read-only fails, due to dirty log ===
-qemu-io: can't open device TEST_DIR/iotest-dirtylog-10G-4M.vhdx: VHDX image file 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx' opened read-only, but contains a log that needs to be replayed. To replay the log, execute:
- qemu-img check -r all 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx': Operation not permitted
+can't open device TEST_DIR/iotest-dirtylog-10G-4M.vhdx: VHDX image file 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx' opened read-only, but contains a log that needs to be replayed
+To replay the log, run:
+qemu-img check -r all 'TEST_DIR/iotest-dirtylog-10G-4M.vhdx'
no file open, try 'help open'
=== Verify open image replays log ===
read 18874368/18874368 bytes at offset 0
diff --git a/qemu/tests/qemu-iotests/071 b/qemu/tests/qemu-iotests/071
index 9eaa49b41..bdfd91fef 100755
--- a/qemu/tests/qemu-iotests/071
+++ b/qemu/tests/qemu-iotests/071
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -104,11 +103,20 @@ echo
echo "=== Testing blkdebug on existing block device ==="
echo
-run_qemu -drive "file=$TEST_IMG,format=raw,if=none,id=drive0" <<EOF
+run_qemu <<EOF
{ "execute": "qmp_capabilities" }
{ "execute": "blockdev-add",
"arguments": {
"options": {
+ "node-name": "drive0",
+ "driver": "file",
+ "filename": "$TEST_IMG"
+ }
+ }
+}
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
"driver": "$IMGFMT",
"id": "drive0-debug",
"file": {
@@ -133,20 +141,29 @@ echo
echo "=== Testing blkverify on existing block device ==="
echo
-run_qemu -drive "file=$TEST_IMG,format=$IMGFMT,if=none,id=drive0" <<EOF
+run_qemu <<EOF
{ "execute": "qmp_capabilities" }
{ "execute": "blockdev-add",
"arguments": {
"options": {
+ "node-name": "drive0",
+ "driver": "$IMGFMT",
+ "file": {
+ "driver": "file",
+ "filename": "$TEST_IMG"
+ }
+ }
+ }
+}
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
"driver": "blkverify",
"id": "drive0-verify",
"test": "drive0",
"raw": {
- "driver": "raw",
- "file": {
- "driver": "file",
- "filename": "$TEST_IMG.base"
- }
+ "driver": "file",
+ "filename": "$TEST_IMG.base"
}
}
}
@@ -163,11 +180,20 @@ echo
echo "=== Testing blkverify on existing raw block device ==="
echo
-run_qemu -drive "file=$TEST_IMG.base,format=raw,if=none,id=drive0" <<EOF
+run_qemu <<EOF
{ "execute": "qmp_capabilities" }
{ "execute": "blockdev-add",
"arguments": {
"options": {
+ "node-name": "drive0",
+ "driver": "file",
+ "filename": "$TEST_IMG.base"
+ }
+ }
+}
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
"driver": "blkverify",
"id": "drive0-verify",
"test": {
@@ -193,11 +219,20 @@ echo
echo "=== Testing blkdebug's set-state through QMP ==="
echo
-run_qemu -drive "file=$TEST_IMG,format=raw,if=none,id=drive0" <<EOF
+run_qemu <<EOF
{ "execute": "qmp_capabilities" }
{ "execute": "blockdev-add",
"arguments": {
"options": {
+ "node-name": "drive0",
+ "driver": "file",
+ "filename": "$TEST_IMG"
+ }
+ }
+}
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
"driver": "$IMGFMT",
"id": "drive0-debug",
"file": {
diff --git a/qemu/tests/qemu-iotests/071.out b/qemu/tests/qemu-iotests/071.out
index 9205ce251..2b40eadae 100644
--- a/qemu/tests/qemu-iotests/071.out
+++ b/qemu/tests/qemu-iotests/071.out
@@ -42,44 +42,46 @@ read failed: Input/output error
=== Testing blkdebug on existing block device ===
-Testing: -drive file=TEST_DIR/t.IMGFMT,format=raw,if=none,id=drive0
+Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
+{"return": {}}
read failed: Input/output error
{"return": ""}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
QEMU_PROG: Failed to flush the L2 table cache: Input/output error
QEMU_PROG: Failed to flush the refcount block cache: Input/output error
=== Testing blkverify on existing block device ===
-Testing: -drive file=TEST_DIR/t.IMGFMT,format=IMGFMT,if=none,id=drive0
+Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
+{"return": {}}
blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0
=== Testing blkverify on existing raw block device ===
-Testing: -drive file=TEST_DIR/t.IMGFMT.base,format=raw,if=none,id=drive0
+Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
+{"return": {}}
blkverify: read sector_num=0 nb_sectors=1 contents mismatch in sector 0
=== Testing blkdebug's set-state through QMP ===
-Testing: -drive file=TEST_DIR/t.IMGFMT,format=raw,if=none,id=drive0
+Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
+{"return": {}}
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
@@ -90,8 +92,6 @@ read failed: Input/output error
{"return": ""}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
QEMU_PROG: Failed to flush the L2 table cache: Input/output error
QEMU_PROG: Failed to flush the refcount block cache: Input/output error
diff --git a/qemu/tests/qemu-iotests/072 b/qemu/tests/qemu-iotests/072
index e4a723d73..aa027c7d2 100755
--- a/qemu/tests/qemu-iotests/072
+++ b/qemu/tests/qemu-iotests/072
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/073 b/qemu/tests/qemu-iotests/073
index 392db5499..ad37a617b 100755
--- a/qemu/tests/qemu-iotests/073
+++ b/qemu/tests/qemu-iotests/073
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/073.out b/qemu/tests/qemu-iotests/073.out
index 733d79ca9..de5452492 100644
--- a/qemu/tests/qemu-iotests/073.out
+++ b/qemu/tests/qemu-iotests/073.out
@@ -2,7 +2,7 @@ QA output created by 073
== creating backing file ==
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
wrote 134217728/134217728 bytes at offset 0
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/qemu/tests/qemu-iotests/075 b/qemu/tests/qemu-iotests/075
index 6117660c5..770d51c6c 100755
--- a/qemu/tests/qemu-iotests/075
+++ b/qemu/tests/qemu-iotests/075
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/075.out b/qemu/tests/qemu-iotests/075.out
index 5f1d6c120..87beae4e3 100644
--- a/qemu/tests/qemu-iotests/075.out
+++ b/qemu/tests/qemu-iotests/075.out
@@ -9,30 +9,30 @@ read 512/512 bytes at offset 1048064
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== block_size must be a multiple of 512 ==
-qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 513 must be a multiple of 512
+can't open device TEST_DIR/simple-pattern.cloop: block_size 513 must be a multiple of 512
no file open, try 'help open'
== block_size cannot be zero ==
-qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size cannot be zero
+can't open device TEST_DIR/simple-pattern.cloop: block_size cannot be zero
no file open, try 'help open'
== huge block_size ===
-qemu-io: can't open device TEST_DIR/simple-pattern.cloop: block_size 4294966784 must be 64 MB or less
+can't open device TEST_DIR/simple-pattern.cloop: block_size 4294966784 must be 64 MB or less
no file open, try 'help open'
== offsets_size overflow ===
-qemu-io: can't open device TEST_DIR/simple-pattern.cloop: n_blocks 4294967295 must be 536870911 or less
+can't open device TEST_DIR/simple-pattern.cloop: n_blocks 4294967295 must be 536870911 or less
no file open, try 'help open'
== refuse images that require too many offsets ===
-qemu-io: can't open device TEST_DIR/simple-pattern.cloop: image requires too many offsets, try increasing block size
+can't open device TEST_DIR/simple-pattern.cloop: image requires too many offsets, try increasing block size
no file open, try 'help open'
== refuse images with non-monotonically increasing offsets ==
-qemu-io: can't open device TEST_DIR/simple-pattern.cloop: offsets not monotonically increasing at index 1, image file is corrupt
+can't open device TEST_DIR/simple-pattern.cloop: offsets not monotonically increasing at index 1, image file is corrupt
no file open, try 'help open'
== refuse images with invalid compressed block size ==
-qemu-io: can't open device TEST_DIR/simple-pattern.cloop: invalid compressed block size at index 1, image file is corrupt
+can't open device TEST_DIR/simple-pattern.cloop: invalid compressed block size at index 1, image file is corrupt
no file open, try 'help open'
*** done
diff --git a/qemu/tests/qemu-iotests/076 b/qemu/tests/qemu-iotests/076
index c9b55a980..ef9e6a4ff 100755
--- a/qemu/tests/qemu-iotests/076
+++ b/qemu/tests/qemu-iotests/076
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/076.out b/qemu/tests/qemu-iotests/076.out
index b0000aeed..72645b252 100644
--- a/qemu/tests/qemu-iotests/076.out
+++ b/qemu/tests/qemu-iotests/076.out
@@ -5,15 +5,15 @@ read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Negative catalog size ==
-qemu-io: can't open device TEST_DIR/parallels-v1: Catalog too large
+can't open device TEST_DIR/parallels-v1: Catalog too large
no file open, try 'help open'
== Overflow in catalog allocation ==
-qemu-io: can't open device TEST_DIR/parallels-v1: Catalog too large
+can't open device TEST_DIR/parallels-v1: Catalog too large
no file open, try 'help open'
== Zero sectors per track ==
-qemu-io: can't open device TEST_DIR/parallels-v1: Invalid image: Zero sectors per track
+can't open device TEST_DIR/parallels-v1: Invalid image: Zero sectors per track
no file open, try 'help open'
== Read from a valid v2 image ==
diff --git a/qemu/tests/qemu-iotests/077 b/qemu/tests/qemu-iotests/077
index 42a90850c..4dc680b7f 100755
--- a/qemu/tests/qemu-iotests/077
+++ b/qemu/tests/qemu-iotests/077
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -63,7 +62,7 @@ EOF
off=0x1000
for ev in "head" "after_head" "tail" "after_tail"; do
cat <<EOF
-break pwritev_rmw.$ev A
+break pwritev_rmw_$ev A
aio_write -P 10 $((off + 0x200)) 0x200
wait_break A
aio_write -P 11 $((off + 0x400)) 0x200
@@ -76,7 +75,7 @@ done
# Chained dependencies
cat <<EOF
-break pwritev_rmw.after_tail A
+break pwritev_rmw_after_tail A
aio_write -P 10 0x5000 0x200
wait_break A
aio_write -P 11 0x5200 0x200
@@ -93,10 +92,10 @@ EOF
# Overlapping multiple requests
cat <<EOF
-break pwritev_rmw.after_tail A
+break pwritev_rmw_after_tail A
aio_write -P 10 0x6000 0x200
wait_break A
-break pwritev_rmw.after_head B
+break pwritev_rmw_after_head B
aio_write -P 10 0x7e00 0x200
wait_break B
aio_write -P 11 0x6800 0x1000
@@ -107,10 +106,10 @@ aio_flush
EOF
cat <<EOF
-break pwritev_rmw.after_tail A
+break pwritev_rmw_after_tail A
aio_write -P 10 0x8000 0x200
wait_break A
-break pwritev_rmw.after_head B
+break pwritev_rmw_after_head B
aio_write -P 10 0x9e00 0x200
wait_break B
aio_write -P 11 0x8800 0x1000
@@ -121,11 +120,11 @@ aio_flush
EOF
cat <<EOF
-break pwritev_rmw.after_tail A
+break pwritev_rmw_after_tail A
aio_write -P 10 0xa000 0x200
wait_break A
aio_write -P 11 0xa800 0x1000
-break pwritev_rmw.after_head B
+break pwritev_rmw_after_head B
aio_write -P 10 0xbe00 0x200
wait_break B
resume A
@@ -135,11 +134,11 @@ aio_flush
EOF
cat <<EOF
-break pwritev_rmw.after_tail A
+break pwritev_rmw_after_tail A
aio_write -P 10 0xc000 0x200
wait_break A
aio_write -P 11 0xc800 0x1000
-break pwritev_rmw.after_head B
+break pwritev_rmw_after_head B
aio_write -P 10 0xde00 0x200
wait_break B
resume B
@@ -150,7 +149,7 @@ EOF
# Only RMW for the tail part
cat <<EOF
-break pwritev_rmw.after_tail A
+break pwritev_rmw_after_tail A
aio_write -P 10 0xe000 0x1800
wait_break A
aio_write -P 11 0xf000 0xc00
@@ -163,7 +162,7 @@ cat <<EOF
break pwritev A
aio_write -P 10 0x10000 0x800
wait_break A
-break pwritev_rmw.after_tail B
+break pwritev_rmw_after_tail B
aio_write -P 11 0x10000 0x400
break pwritev_done C
resume A
diff --git a/qemu/tests/qemu-iotests/078 b/qemu/tests/qemu-iotests/078
index 7be2c3f69..f333e9ac8 100755
--- a/qemu/tests/qemu-iotests/078
+++ b/qemu/tests/qemu-iotests/078
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/078.out b/qemu/tests/qemu-iotests/078.out
index ca18d2ea3..42b8a8301 100644
--- a/qemu/tests/qemu-iotests/078.out
+++ b/qemu/tests/qemu-iotests/078.out
@@ -5,24 +5,24 @@ read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Negative catalog size ==
-qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too large
+can't open device TEST_DIR/empty.bochs: Catalog size is too large
no file open, try 'help open'
== Overflow for catalog size * sizeof(uint32_t) ==
-qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too large
+can't open device TEST_DIR/empty.bochs: Catalog size is too large
no file open, try 'help open'
== Too small catalog bitmap for image size ==
-qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
+can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
+can't open device TEST_DIR/empty.bochs: Catalog size is too small for this disk size
no file open, try 'help open'
== Negative extent size ==
-qemu-io: can't open device TEST_DIR/empty.bochs: Extent size 2147483648 is too large
+can't open device TEST_DIR/empty.bochs: Extent size 2147483648 is too large
no file open, try 'help open'
== Zero extent size ==
-qemu-io: can't open device TEST_DIR/empty.bochs: Extent size must be at least 512
+can't open device TEST_DIR/empty.bochs: Extent size must be at least 512
no file open, try 'help open'
*** done
diff --git a/qemu/tests/qemu-iotests/079 b/qemu/tests/qemu-iotests/079
index ade6efa0d..b2e3f7426 100755
--- a/qemu/tests/qemu-iotests/079
+++ b/qemu/tests/qemu-iotests/079
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/079.out b/qemu/tests/qemu-iotests/079.out
index 6dc5d5763..aab922fb3 100644
--- a/qemu/tests/qemu-iotests/079.out
+++ b/qemu/tests/qemu-iotests/079.out
@@ -1,14 +1,14 @@
QA output created by 079
=== Check option preallocation and cluster_size ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata
qemu-img: TEST_DIR/t.IMGFMT: Cluster size must be a power of two between 512 and 2048k
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation='metadata'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=4294967296 preallocation=metadata
*** done
diff --git a/qemu/tests/qemu-iotests/080 b/qemu/tests/qemu-iotests/080
index a2c58aebd..55044c700 100755
--- a/qemu/tests/qemu-iotests/080
+++ b/qemu/tests/qemu-iotests/080
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/080.out b/qemu/tests/qemu-iotests/080.out
index 6061d8443..0daac48b1 100644
--- a/qemu/tests/qemu-iotests/080.out
+++ b/qemu/tests/qemu-iotests/080.out
@@ -2,46 +2,46 @@ QA output created by 080
== Huge header size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
+can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
+can't open device TEST_DIR/t.qcow2: qcow2 header exceeds cluster size
no file open, try 'help open'
== Huge unknown header extension ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow2: Invalid backing file offset
+can't open device TEST_DIR/t.qcow2: Invalid backing file offset
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large
+can't open device TEST_DIR/t.qcow2: Header extension too large
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: Header extension too large
+can't open device TEST_DIR/t.qcow2: Header extension too large
no file open, try 'help open'
== Huge refcount table size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large
+can't open device TEST_DIR/t.qcow2: Reference count table too large
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: Reference count table too large
+can't open device TEST_DIR/t.qcow2: Reference count table too large
no file open, try 'help open'
== Misaligned refcount table ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
+can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
no file open, try 'help open'
== Huge refcount offset ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
+can't open device TEST_DIR/t.qcow2: Invalid reference count table offset
no file open, try 'help open'
== Invalid snapshot table ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow2: Too many snapshots
+can't open device TEST_DIR/t.qcow2: Too many snapshots
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: Too many snapshots
+can't open device TEST_DIR/t.qcow2: Too many snapshots
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
+can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
+can't open device TEST_DIR/t.qcow2: Invalid snapshot table offset
no file open, try 'help open'
== Hitting snapshot table size limit ==
@@ -52,13 +52,13 @@ read 512/512 bytes at offset 0
== Invalid L1 table ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow2: Active L1 table too large
+can't open device TEST_DIR/t.qcow2: Active L1 table too large
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: Active L1 table too large
+can't open device TEST_DIR/t.qcow2: Active L1 table too large
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
+can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
+can't open device TEST_DIR/t.qcow2: Invalid L1 table offset
no file open, try 'help open'
== Invalid L1 table (with internal snapshot in the image) ==
@@ -67,7 +67,7 @@ qemu-img: Could not open 'TEST_DIR/t.IMGFMT': L1 table is too small
== Invalid backing file size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow2: Backing file name too long
+can't open device TEST_DIR/t.qcow2: Backing file name too long
no file open, try 'help open'
== Invalid L2 entry (huge physical offset) ==
diff --git a/qemu/tests/qemu-iotests/081 b/qemu/tests/qemu-iotests/081
index d9b042cfc..d89fabcdb 100755
--- a/qemu/tests/qemu-iotests/081
+++ b/qemu/tests/qemu-iotests/081
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -53,7 +52,8 @@ function do_run_qemu()
function run_qemu()
{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp | _filter_qemu_io
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu | _filter_qmp\
+ | _filter_qemu_io | _filter_generated_node_ids
}
test_quorum=$($QEMU_IMG --help|grep quorum)
@@ -101,17 +101,29 @@ $QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
echo
echo "== checking mixed reference/option specification =="
-run_qemu -drive "file=$TEST_DIR/2.raw,format=$IMGFMT,if=none,id=drive2" <<EOF
+run_qemu <<EOF
{ "execute": "qmp_capabilities" }
{ "execute": "blockdev-add",
"arguments": {
"options": {
+ "node-name": "drive2",
+ "driver": "$IMGFMT",
+ "file": {
+ "driver": "file",
+ "filename": "$TEST_DIR/2.raw"
+ }
+ }
+ }
+}
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
"driver": "quorum",
"id": "drive0-quorum",
"vote-threshold": 2,
"children": [
{
- "driver": "raw",
+ "driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_DIR/1.raw"
@@ -119,7 +131,7 @@ run_qemu -drive "file=$TEST_DIR/2.raw,format=$IMGFMT,if=none,id=drive2" <<EOF
},
"drive2",
{
- "driver": "raw",
+ "driver": "$IMGFMT",
"file": {
"driver": "file",
"filename": "$TEST_DIR/3.raw"
diff --git a/qemu/tests/qemu-iotests/081.out b/qemu/tests/qemu-iotests/081.out
index 9f57d9d3b..97df69d71 100644
--- a/qemu/tests/qemu-iotests/081.out
+++ b/qemu/tests/qemu-iotests/081.out
@@ -26,18 +26,17 @@ read 10485760/10485760 bytes at offset 0
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== checking mixed reference/option specification ==
-Testing: -drive file=TEST_DIR/2.IMGFMT,format=IMGFMT,if=none,id=drive2
+Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "QUORUM_REPORT_BAD", "data": {"node-name": "", "sectors-count": 20480, "sector-num": 0}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "QUORUM_REPORT_BAD", "data": {"node-name": "drive2", "sectors-count": 20480, "sector-num": 0, "type": "read"}}
read 10485760/10485760 bytes at offset 0
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
{"return": ""}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
== using quorum rewrite corrupted mode ==
diff --git a/qemu/tests/qemu-iotests/082 b/qemu/tests/qemu-iotests/082
index c83e01e7c..ad1d9fadc 100755
--- a/qemu/tests/qemu-iotests/082
+++ b/qemu/tests/qemu-iotests/082
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/082.out b/qemu/tests/qemu-iotests/082.out
index 3a749b825..a952330ba 100644
--- a/qemu/tests/qemu-iotests/082.out
+++ b/qemu/tests/qemu-iotests/082.out
@@ -147,10 +147,10 @@ refcount_bits Width of a reference count entry in bits
nocow Turn off copy-on-write (valid only on btrfs)
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 128M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,help' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,help encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,? TEST_DIR/t.qcow2 128M
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2,?' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2,,? encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2, -o help TEST_DIR/t.qcow2 128M
qemu-img: Invalid option list: backing_file=TEST_DIR/t.qcow2,
diff --git a/qemu/tests/qemu-iotests/083 b/qemu/tests/qemu-iotests/083
index 1b2d3f115..bc724ae05 100755
--- a/qemu/tests/qemu-iotests/083
+++ b/qemu/tests/qemu-iotests/083
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
# get standard environment, filters and checks
@@ -49,17 +48,6 @@ wait_for_tcp_port() {
done
}
-filter_nbd() {
- # nbd.c error messages contain function names and line numbers that are prone
- # to change. Message ordering depends on timing between send and receive
- # callbacks sometimes, making them unreliable.
- #
- # Filter out the TCP port number since this changes between runs.
- sed -e 's#^.*nbd\.c:.*##g' \
- -e 's#nbd:127\.0\.0\.1:[^:]*:#nbd:127\.0\.0\.1:PORT:#g' \
- -e 's#\(exportname=foo\|PORT\): Failed to .*$#\1#'
-}
-
check_disconnect() {
event=$1
when=$2
@@ -84,7 +72,7 @@ EOF
$PYTHON nbd-fault-injector.py $extra_args "127.0.0.1:$port" "$TEST_DIR/nbd-fault-injector.conf" 2>&1 >/dev/null &
wait_for_tcp_port "127\\.0\\.0\\.1:$port"
- $QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | filter_nbd
+ $QEMU_IO -c "read 0 512" "$nbd_url" 2>&1 | _filter_qemu_io | _filter_nbd
echo
}
diff --git a/qemu/tests/qemu-iotests/083.out b/qemu/tests/qemu-iotests/083.out
index 8c1441bf4..ef3d1e32a 100644
--- a/qemu/tests/qemu-iotests/083.out
+++ b/qemu/tests/qemu-iotests/083.out
@@ -1,138 +1,128 @@
QA output created by 083
=== Check disconnect before neg1 ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect after neg1 ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect 8 neg1 ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect 16 neg1 ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect before export ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect after export ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect 4 export ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect 12 export ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect 16 export ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect before neg2 ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect after neg2 ===
-
read failed: Input/output error
=== Check disconnect 8 neg2 ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect 10 neg2 ===
-qemu-io: can't open device nbd:127.0.0.1:PORT:exportname=foo
+can't open device nbd:127.0.0.1:PORT:exportname=foo
no file open, try 'help open'
=== Check disconnect before request ===
-
read failed: Input/output error
=== Check disconnect after request ===
-
read failed: Input/output error
=== Check disconnect before reply ===
-
read failed: Input/output error
=== Check disconnect after reply ===
-
read failed: Input/output error
=== Check disconnect 4 reply ===
-
read failed: Input/output error
=== Check disconnect 8 reply ===
-
read failed: Input/output error
=== Check disconnect before data ===
-
read failed: Input/output error
=== Check disconnect after data ===
-
read 512/512 bytes at offset 0
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
=== Check disconnect before neg-classic ===
-qemu-io: can't open device nbd:127.0.0.1:PORT
+can't open device nbd:127.0.0.1:PORT
no file open, try 'help open'
=== Check disconnect 8 neg-classic ===
-qemu-io: can't open device nbd:127.0.0.1:PORT
+can't open device nbd:127.0.0.1:PORT
no file open, try 'help open'
=== Check disconnect 16 neg-classic ===
-qemu-io: can't open device nbd:127.0.0.1:PORT
+can't open device nbd:127.0.0.1:PORT
no file open, try 'help open'
=== Check disconnect 24 neg-classic ===
-qemu-io: can't open device nbd:127.0.0.1:PORT
+can't open device nbd:127.0.0.1:PORT
no file open, try 'help open'
=== Check disconnect 28 neg-classic ===
-qemu-io: can't open device nbd:127.0.0.1:PORT
+can't open device nbd:127.0.0.1:PORT
no file open, try 'help open'
=== Check disconnect after neg-classic ===
-
read failed: Input/output error
*** done
diff --git a/qemu/tests/qemu-iotests/084 b/qemu/tests/qemu-iotests/084
index 733018d4a..04f2aa9d7 100755
--- a/qemu/tests/qemu-iotests/084
+++ b/qemu/tests/qemu-iotests/084
@@ -26,7 +26,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/085 b/qemu/tests/qemu-iotests/085
index 56cd6f89b..aa77eca77 100755
--- a/qemu/tests/qemu-iotests/085
+++ b/qemu/tests/qemu-iotests/085
@@ -7,6 +7,7 @@
# snapshots are performed.
#
# Copyright (C) 2014 Red Hat, Inc.
+# Copyright (C) 2015 Igalia, S.L.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -34,17 +35,17 @@ status=1 # failure is the default!
snapshot_virt0="snapshot-v0.qcow2"
snapshot_virt1="snapshot-v1.qcow2"
-MAX_SNAPSHOTS=10
+SNAPSHOTS=10
_cleanup()
{
_cleanup_qemu
- for i in $(seq 1 ${MAX_SNAPSHOTS})
+ for i in $(seq 1 ${SNAPSHOTS})
do
rm -f "${TEST_DIR}/${i}-${snapshot_virt0}"
rm -f "${TEST_DIR}/${i}-${snapshot_virt1}"
done
- _cleanup_test_img
+ rm -f "${TEST_IMG}.1" "${TEST_IMG}.2"
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -64,7 +65,7 @@ function create_single_snapshot()
{
cmd="{ 'execute': 'blockdev-snapshot-sync',
'arguments': { 'device': 'virtio0',
- 'snapshot-file':'"${TEST_DIR}/${1}-${snapshot_virt0}"',
+ 'snapshot-file':'${TEST_DIR}/${1}-${snapshot_virt0}',
'format': 'qcow2' } }"
_send_qemu_cmd $h "${cmd}" "return"
}
@@ -76,27 +77,60 @@ function create_group_snapshot()
{'actions': [
{ 'type': 'blockdev-snapshot-sync', 'data' :
{ 'device': 'virtio0',
- 'snapshot-file': '"${TEST_DIR}/${1}-${snapshot_virt0}"' } },
+ 'snapshot-file': '${TEST_DIR}/${1}-${snapshot_virt0}' } },
{ 'type': 'blockdev-snapshot-sync', 'data' :
{ 'device': 'virtio1',
- 'snapshot-file': '"${TEST_DIR}/${1}-${snapshot_virt1}"' } } ]
+ 'snapshot-file': '${TEST_DIR}/${1}-${snapshot_virt1}' } } ]
} }"
_send_qemu_cmd $h "${cmd}" "return"
}
+# ${1}: unique identifier for the snapshot filename
+# ${2}: true: open backing images; false: don't open them (default)
+function add_snapshot_image()
+{
+ if [ "${2}" = "true" ]; then
+ extra_params=""
+ else
+ extra_params="'backing': '', "
+ fi
+ base_image="${TEST_DIR}/$((${1}-1))-${snapshot_virt0}"
+ snapshot_file="${TEST_DIR}/${1}-${snapshot_virt0}"
+ _make_test_img -b "${base_image}" "$size"
+ mv "${TEST_IMG}" "${snapshot_file}"
+ cmd="{ 'execute': 'blockdev-add', 'arguments':
+ { 'options':
+ { 'driver': 'qcow2', 'node-name': 'snap_${1}', ${extra_params}
+ 'file':
+ { 'driver': 'file', 'filename': '${snapshot_file}',
+ 'node-name': 'file_${1}' } } } }"
+ _send_qemu_cmd $h "${cmd}" "return"
+}
+
+# ${1}: unique identifier for the snapshot filename
+# ${2}: expected response, defaults to 'return'
+function blockdev_snapshot()
+{
+ cmd="{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node': 'virtio0',
+ 'overlay':'snap_${1}' } }"
+ _send_qemu_cmd $h "${cmd}" "${2:-return}"
+}
+
size=128M
_make_test_img $size
-mv "${TEST_IMG}" "${TEST_IMG}.orig"
+mv "${TEST_IMG}" "${TEST_IMG}.1"
_make_test_img $size
+mv "${TEST_IMG}" "${TEST_IMG}.2"
echo
echo === Running QEMU ===
echo
qemu_comm_method="qmp"
-_launch_qemu -drive file="${TEST_IMG}.orig",if=virtio -drive file="${TEST_IMG}",if=virtio
+_launch_qemu -drive file="${TEST_IMG}.1",if=virtio -drive file="${TEST_IMG}.2",if=virtio
h=$QEMU_HANDLE
echo
@@ -105,6 +139,8 @@ echo
_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return"
+# Tests for the blockdev-snapshot-sync command
+
echo
echo === Create a single snapshot on virtio0 ===
echo
@@ -117,7 +153,7 @@ echo === Invalid command - missing device and nodename ===
echo
_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
- 'arguments': { 'snapshot-file':'"${TEST_DIR}/1-${snapshot_virt0}"',
+ 'arguments': { 'snapshot-file':'${TEST_DIR}/1-${snapshot_virt0}',
'format': 'qcow2' } }" "error"
echo
@@ -132,11 +168,75 @@ echo
echo === Create several transactional group snapshots ===
echo
-for i in $(seq 2 ${MAX_SNAPSHOTS})
+for i in $(seq 2 ${SNAPSHOTS})
do
create_group_snapshot ${i}
done
+# Tests for the blockdev-snapshot command
+
+echo
+echo === Create a couple of snapshots using blockdev-snapshot ===
+echo
+
+SNAPSHOTS=$((${SNAPSHOTS}+1))
+add_snapshot_image ${SNAPSHOTS}
+blockdev_snapshot ${SNAPSHOTS}
+
+SNAPSHOTS=$((${SNAPSHOTS}+1))
+add_snapshot_image ${SNAPSHOTS}
+blockdev_snapshot ${SNAPSHOTS}
+
+echo
+echo === Invalid command - cannot create a snapshot using a file BDS ===
+echo
+
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'virtio0',
+ 'overlay':'file_${SNAPSHOTS}' }
+ }" "error"
+
+echo
+echo === Invalid command - snapshot node used as active layer ===
+echo
+
+blockdev_snapshot ${SNAPSHOTS} error
+
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'virtio0',
+ 'overlay':'virtio0' }
+ }" "error"
+
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'virtio0',
+ 'overlay':'virtio1' }
+ }" "error"
+
+echo
+echo === Invalid command - snapshot node used as backing hd ===
+echo
+
+blockdev_snapshot $((${SNAPSHOTS}-1)) error
+
+echo
+echo === Invalid command - snapshot node has a backing image ===
+echo
+
+SNAPSHOTS=$((${SNAPSHOTS}+1))
+add_snapshot_image ${SNAPSHOTS} true
+blockdev_snapshot ${SNAPSHOTS} error
+
+echo
+echo === Invalid command - The node does not exist ===
+echo
+
+blockdev_snapshot $((${SNAPSHOTS}+1)) error
+
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot',
+ 'arguments': { 'node':'nodevice',
+ 'overlay':'snap_${SNAPSHOTS}' }
+ }" "error"
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/qemu/tests/qemu-iotests/085.out b/qemu/tests/qemu-iotests/085.out
index 5eb8b947c..01c78d689 100644
--- a/qemu/tests/qemu-iotests/085.out
+++ b/qemu/tests/qemu-iotests/085.out
@@ -11,7 +11,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
=== Create a single snapshot on virtio0 ===
-Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2.orig' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.1 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
=== Invalid command - missing device and nodename ===
@@ -25,31 +25,65 @@ Formatting 'TEST_DIR/1-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file
=== Create several transactional group snapshots ===
-Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/1-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/t.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/2-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/1-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/2-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/t.qcow2.2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
-Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/2-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/2-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/3-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/3-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/2-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
-Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/3-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/3-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/4-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/4-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/3-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
-Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/4-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/4-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/5-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/5-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/4-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
-Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/5-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/5-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/6-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/6-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/5-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
-Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/6-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/6-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/7-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/7-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/6-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
-Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/7-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/7-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/8-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/8-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/7-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
-Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/8-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/8-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/9-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/9-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/8-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
-Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/9-snapshot-v0.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
-Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file='TEST_DIR/9-snapshot-v1.qcow2' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/10-snapshot-v0.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v0.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/10-snapshot-v1.qcow2', fmt=qcow2 size=134217728 backing_file=TEST_DIR/9-snapshot-v1.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
{"return": {}}
+
+=== Create a couple of snapshots using blockdev-snapshot ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/10-snapshot-v0.IMGFMT
+{"return": {}}
+{"return": {}}
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/11-snapshot-v0.IMGFMT
+{"return": {}}
+{"return": {}}
+
+=== Invalid command - cannot create a snapshot using a file BDS ===
+
+{"error": {"class": "GenericError", "desc": "The snapshot does not support backing images"}}
+
+=== Invalid command - snapshot node used as active layer ===
+
+{"error": {"class": "GenericError", "desc": "The snapshot is already in use by virtio0"}}
+{"error": {"class": "GenericError", "desc": "The snapshot is already in use by virtio0"}}
+{"error": {"class": "GenericError", "desc": "The snapshot is already in use by virtio1"}}
+
+=== Invalid command - snapshot node used as backing hd ===
+
+{"error": {"class": "GenericError", "desc": "Node 'snap_11' is busy: node is used as backing hd of 'virtio0'"}}
+
+=== Invalid command - snapshot node has a backing image ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/12-snapshot-v0.IMGFMT
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "The snapshot already has a backing image"}}
+
+=== Invalid command - The node does not exist ===
+
+{"error": {"class": "GenericError", "desc": "Cannot find device=snap_14 nor node_name=snap_14"}}
+{"error": {"class": "GenericError", "desc": "Cannot find device=nodevice nor node_name=nodevice"}}
*** done
diff --git a/qemu/tests/qemu-iotests/086 b/qemu/tests/qemu-iotests/086
index 234eb9a91..cd4494a66 100755
--- a/qemu/tests/qemu-iotests/086
+++ b/qemu/tests/qemu-iotests/086
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -38,7 +37,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
-_supported_fmt qcow2
+_supported_fmt qcow2 raw
_supported_proto file nfs
_supported_os Linux
diff --git a/qemu/tests/qemu-iotests/087 b/qemu/tests/qemu-iotests/087
index 869474994..e7bca37ef 100755
--- a/qemu/tests/qemu-iotests/087
+++ b/qemu/tests/qemu-iotests/087
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
# get standard environment, filters and checks
@@ -45,7 +44,8 @@ function do_run_qemu()
function run_qemu()
{
- do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | _filter_qemu \
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp \
+ | _filter_qemu | _filter_imgfmt \
| sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g'
}
@@ -54,7 +54,7 @@ size=128M
_make_test_img $size
echo
-echo === Missing ID ===
+echo === Missing ID and node-name ===
echo
run_qemu <<EOF
diff --git a/qemu/tests/qemu-iotests/087.out b/qemu/tests/qemu-iotests/087.out
index c71bb3aa4..055c553cd 100644
--- a/qemu/tests/qemu-iotests/087.out
+++ b/qemu/tests/qemu-iotests/087.out
@@ -1,16 +1,14 @@
QA output created by 087
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-=== Missing ID ===
+=== Missing ID and node-name ===
Testing:
QMP_VERSION
{"return": {}}
-{"error": {"class": "GenericError", "desc": "Block device needs an ID"}}
+{"error": {"class": "GenericError", "desc": "'id' and/or 'node-name' need to be specified for the root node"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
=== Duplicate ID ===
@@ -23,11 +21,9 @@ QMP_VERSION
{"error": {"class": "GenericError", "desc": "Device name 'test-node' conflicts with an existing node name"}}
{"error": {"class": "GenericError", "desc": "node-name=disk is conflicting with a device id"}}
{"error": {"class": "GenericError", "desc": "Duplicate node name"}}
-{"error": {"class": "GenericError", "desc": "node-name=disk3 is conflicting with a device id"}}
+{"error": {"class": "GenericError", "desc": "Device name 'disk3' conflicts with an existing node name"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
=== aio=native without O_DIRECT ===
@@ -38,52 +34,36 @@ QMP_VERSION
{"error": {"class": "GenericError", "desc": "aio=native requires cache.direct=true"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
=== Encrypted image ===
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
Testing: -S
QMP_VERSION
{"return": {}}
-Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
+IMGFMT built-in AES encryption is deprecated
+Support for it will be removed in a future release.
+You can use 'qemu-img convert' to switch to an
+unencrypted IMGFMT image, or a LUKS raw image.
{"error": {"class": "GenericError", "desc": "blockdev-add doesn't support encrypted devices"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
Testing:
QMP_VERSION
{"return": {}}
-Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
+IMGFMT built-in AES encryption is deprecated
+Support for it will be removed in a future release.
+You can use 'qemu-img convert' to switch to an
+unencrypted IMGFMT image, or a LUKS raw image.
{"error": {"class": "GenericError", "desc": "Guest must be stopped for opening of encrypted image"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
=== Missing driver ===
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
Testing: -S
QMP_VERSION
@@ -91,7 +71,5 @@ QMP_VERSION
{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'driver', expected: string"}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "ide1-cd0", "tray-open": true}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
*** done
diff --git a/qemu/tests/qemu-iotests/088 b/qemu/tests/qemu-iotests/088
index f9c312918..b8076f216 100755
--- a/qemu/tests/qemu-iotests/088
+++ b/qemu/tests/qemu-iotests/088
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/088.out b/qemu/tests/qemu-iotests/088.out
index 6e6bfcaf9..a2a83b8a1 100644
--- a/qemu/tests/qemu-iotests/088.out
+++ b/qemu/tests/qemu-iotests/088.out
@@ -2,16 +2,16 @@ QA output created by 088
== Invalid block size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 0
+can't open device TEST_DIR/t.vpc: Invalid block size 0
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 0
+can't open device TEST_DIR/t.vpc: Invalid block size 0
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 128
+can't open device TEST_DIR/t.vpc: Invalid block size 128
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 128
+can't open device TEST_DIR/t.vpc: Invalid block size 128
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 305419896
+can't open device TEST_DIR/t.vpc: Invalid block size 305419896
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.vpc: Invalid block size 305419896
+can't open device TEST_DIR/t.vpc: Invalid block size 305419896
no file open, try 'help open'
*** done
diff --git a/qemu/tests/qemu-iotests/089 b/qemu/tests/qemu-iotests/089
index 3e0038dde..9bfe2307b 100755
--- a/qemu/tests/qemu-iotests/089
+++ b/qemu/tests/qemu-iotests/089
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/090 b/qemu/tests/qemu-iotests/090
index 70b5a6fd7..7380503d5 100755
--- a/qemu/tests/qemu-iotests/090
+++ b/qemu/tests/qemu-iotests/090
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/092 b/qemu/tests/qemu-iotests/092
index 52c529bae..5bbdd071d 100755
--- a/qemu/tests/qemu-iotests/092
+++ b/qemu/tests/qemu-iotests/092
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/092.out b/qemu/tests/qemu-iotests/092.out
index c5c60f917..e18f54c20 100644
--- a/qemu/tests/qemu-iotests/092.out
+++ b/qemu/tests/qemu-iotests/092.out
@@ -2,37 +2,37 @@ QA output created by 092
== Invalid cluster size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
+can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
+can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
+can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
+can't open device TEST_DIR/t.qcow: Cluster size must be between 512 and 64k
no file open, try 'help open'
== Invalid L2 table size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
+can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
+can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
+can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
+can't open device TEST_DIR/t.qcow: L2 table size must be between 512 and 64k
no file open, try 'help open'
== Invalid size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow: Image too large
+can't open device TEST_DIR/t.qcow: Image too large
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow: Image too large
+can't open device TEST_DIR/t.qcow: Image too large
no file open, try 'help open'
== Invalid backing file length ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-io: can't open device TEST_DIR/t.qcow: Backing file name too long
+can't open device TEST_DIR/t.qcow: Backing file name too long
no file open, try 'help open'
-qemu-io: can't open device TEST_DIR/t.qcow: Backing file name too long
+can't open device TEST_DIR/t.qcow: Backing file name too long
no file open, try 'help open'
*** done
diff --git a/qemu/tests/qemu-iotests/093 b/qemu/tests/qemu-iotests/093
index c0e9e2b0b..ce8e13cb4 100755
--- a/qemu/tests/qemu-iotests/093
+++ b/qemu/tests/qemu-iotests/093
@@ -3,7 +3,7 @@
# Tests for IO throttling
#
# Copyright (C) 2015 Red Hat, Inc.
-# Copyright (C) 2015 Igalia, S.L.
+# Copyright (C) 2015-2016 Igalia, S.L.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,6 +21,8 @@
import iotests
+nsec_per_sec = 1000000000
+
class ThrottleTestCase(iotests.QMPTestCase):
test_img = "null-aio://"
max_drives = 3
@@ -42,16 +44,7 @@ class ThrottleTestCase(iotests.QMPTestCase):
def tearDown(self):
self.vm.shutdown()
- def do_test_throttle(self, ndrives, seconds, params):
- def check_limit(limit, num):
- # IO throttling algorithm is discrete, allow 10% error so the test
- # is more robust
- return limit == 0 or \
- (num < seconds * limit * 1.1 / ndrives
- and num > seconds * limit * 0.9 / ndrives)
-
- nsec_per_sec = 1000000000
-
+ def configure_throttle(self, ndrives, params):
params['group'] = 'test'
# Set the I/O throttling parameters to all drives
@@ -60,13 +53,21 @@ class ThrottleTestCase(iotests.QMPTestCase):
result = self.vm.qmp("block_set_io_throttle", conv_keys=False, **params)
self.assert_qmp(result, 'return', {})
+ def do_test_throttle(self, ndrives, seconds, params):
+ def check_limit(limit, num):
+ # IO throttling algorithm is discrete, allow 10% error so the test
+ # is more robust
+ return limit == 0 or \
+ (num < seconds * limit * 1.1 / ndrives
+ and num > seconds * limit * 0.9 / ndrives)
+
# Set vm clock to a known value
ns = seconds * nsec_per_sec
self.vm.qtest("clock_step %d" % ns)
- # Submit enough requests. They will drain bps_max and iops_max, but the
- # rest requests won't get executed until we advance the virtual clock
- # with qtest interface
+ # Submit enough requests so the throttling mechanism kicks
+ # in. The throttled requests won't be executed until we
+ # advance the virtual clock.
rq_size = 512
rd_nr = max(params['bps'] / rq_size / 2,
params['bps_rd'] / rq_size,
@@ -142,8 +143,44 @@ class ThrottleTestCase(iotests.QMPTestCase):
for tk in params:
limits = dict([(k, 0) for k in params])
limits[tk] = params[tk] * ndrives
+ self.configure_throttle(ndrives, limits)
self.do_test_throttle(ndrives, 5, limits)
+ def test_burst(self):
+ params = {"bps": 4096,
+ "bps_rd": 4096,
+ "bps_wr": 4096,
+ "iops": 10,
+ "iops_rd": 10,
+ "iops_wr": 10,
+ }
+ ndrives = 1
+ # Pick each out of all possible params and test
+ for tk in params:
+ rate = params[tk] * ndrives
+ burst_rate = rate * 7
+ burst_length = 4
+
+ # Configure the throttling settings
+ settings = dict([(k, 0) for k in params])
+ settings[tk] = rate
+ settings['%s_max' % tk] = burst_rate
+ settings['%s_max_length' % tk] = burst_length
+ self.configure_throttle(ndrives, settings)
+
+ # Wait for the bucket to empty so we can do bursts
+ wait_ns = nsec_per_sec * burst_length * burst_rate / rate
+ self.vm.qtest("clock_step %d" % wait_ns)
+
+ # Test I/O at the max burst rate
+ limits = dict([(k, 0) for k in params])
+ limits[tk] = burst_rate
+ self.do_test_throttle(ndrives, burst_length, limits)
+
+ # Now test I/O at the normal rate
+ limits[tk] = rate
+ self.do_test_throttle(ndrives, 5, limits)
+
class ThrottleTestCoroutine(ThrottleTestCase):
test_img = "null-co://"
diff --git a/qemu/tests/qemu-iotests/093.out b/qemu/tests/qemu-iotests/093.out
index fbc63e62f..89968f35d 100644
--- a/qemu/tests/qemu-iotests/093.out
+++ b/qemu/tests/qemu-iotests/093.out
@@ -1,5 +1,5 @@
-..
+....
----------------------------------------------------------------------
-Ran 2 tests
+Ran 4 tests
OK
diff --git a/qemu/tests/qemu-iotests/094 b/qemu/tests/qemu-iotests/094
index 27a2be256..0ba0b0c36 100755
--- a/qemu/tests/qemu-iotests/094
+++ b/qemu/tests/qemu-iotests/094
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Test case for drive-mirror to NBD (especially bdrv_swap() on NBD BDS)
+# Test case for drive-mirror to NBD
#
# Copyright (C) 2015 Red Hat, Inc.
#
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
trap "exit \$status" 0 1 2 3 15
@@ -50,8 +49,10 @@ _send_qemu_cmd $QEMU_HANDLE \
"{'execute': 'qmp_capabilities'}" \
'return'
-# 'format': 'nbd' is not actually "correct", but this is probably the only way
-# to test bdrv_swap() on an NBD BDS
+# 'format': 'nbd' is not actually "correct", but this was the only way to
+# test the bug fixed in commit f53a829. Though the bug's related code
+# bdrv_swap() was replaced later, let's make sure we don't fall in the same
+# pit again.
_send_qemu_cmd $QEMU_HANDLE \
"{'execute': 'drive-mirror',
'arguments': {'device': 'src',
diff --git a/qemu/tests/qemu-iotests/095 b/qemu/tests/qemu-iotests/095
index 6630181a7..dad04b9ac 100755
--- a/qemu/tests/qemu-iotests/095
+++ b/qemu/tests/qemu-iotests/095
@@ -50,17 +50,15 @@ _supported_os Linux
size_smaller=5M
size_larger=100M
-_make_test_img $size_smaller
-mv "${TEST_IMG}" "${TEST_IMG}.base"
+TEST_IMG="$TEST_IMG.base" _make_test_img $size_smaller
-_make_test_img -b "${TEST_IMG}.base" $size_larger
-mv "${TEST_IMG}" "${TEST_IMG}.snp1"
+TEST_IMG="$TEST_IMG.snp1" _make_test_img -b "$TEST_IMG.base" $size_larger
_make_test_img -b "${TEST_IMG}.snp1" $size_larger
echo
echo "=== Base image info before commit and resize ==="
-TEST_IMG="${TEST_IMG}.base" _img_info
+TEST_IMG="${TEST_IMG}.base" _img_info | _filter_img_info
echo
echo === Running QEMU Live Commit Test ===
@@ -78,7 +76,7 @@ _send_qemu_cmd $h "{ 'execute': 'block-commit',
echo
echo "=== Base image info after commit and resize ==="
-TEST_IMG="${TEST_IMG}.base" _img_info
+TEST_IMG="${TEST_IMG}.base" _img_info | _filter_img_info
# success, all done
echo "*** done"
diff --git a/qemu/tests/qemu-iotests/095.out b/qemu/tests/qemu-iotests/095.out
index 267c4836e..73875cab4 100644
--- a/qemu/tests/qemu-iotests/095.out
+++ b/qemu/tests/qemu-iotests/095.out
@@ -1,13 +1,12 @@
QA output created by 095
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=5242880
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=104857600 backing_file='TEST_DIR/t.IMGFMT.base'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=104857600 backing_file='TEST_DIR/t.IMGFMT.snp1'
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=5242880
+Formatting 'TEST_DIR/t.IMGFMT.snp1', fmt=IMGFMT size=104857600 backing_file=TEST_DIR/t.IMGFMT.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=104857600 backing_file=TEST_DIR/t.IMGFMT.snp1
=== Base image info before commit and resize ===
image: TEST_DIR/t.IMGFMT.base
file format: IMGFMT
virtual size: 5.0M (5242880 bytes)
-cluster_size: 65536
=== Running QEMU Live Commit Test ===
@@ -19,5 +18,4 @@ cluster_size: 65536
image: TEST_DIR/t.IMGFMT.base
file format: IMGFMT
virtual size: 100M (104857600 bytes)
-cluster_size: 65536
*** done
diff --git a/qemu/tests/qemu-iotests/096 b/qemu/tests/qemu-iotests/096
new file mode 100644
index 000000000..e34204b8f
--- /dev/null
+++ b/qemu/tests/qemu-iotests/096
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# Test that snapshots move the throttling configuration to the active
+# layer
+#
+# Copyright (C) 2015 Igalia, S.L.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import iotests
+import os
+
+class TestLiveSnapshot(iotests.QMPTestCase):
+ base_img = os.path.join(iotests.test_dir, 'base.img')
+ target_img = os.path.join(iotests.test_dir, 'target.img')
+ group = 'mygroup'
+ iops = 6000
+ iops_size = 1024
+
+ def setUp(self):
+ opts = []
+ opts.append('node-name=base')
+ opts.append('throttling.group=%s' % self.group)
+ opts.append('throttling.iops-total=%d' % self.iops)
+ opts.append('throttling.iops-size=%d' % self.iops_size)
+ iotests.qemu_img('create', '-f', iotests.imgfmt, self.base_img, '100M')
+ self.vm = iotests.VM().add_drive(self.base_img, ','.join(opts))
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(self.base_img)
+ os.remove(self.target_img)
+
+ def checkConfig(self, active_layer):
+ result = self.vm.qmp('query-named-block-nodes')
+ for r in result['return']:
+ if r['node-name'] == active_layer:
+ self.assertEqual(r['group'], self.group)
+ self.assertEqual(r['iops'], self.iops)
+ self.assertEqual(r['iops_size'], self.iops_size)
+ else:
+ self.assertFalse(r.has_key('group'))
+ self.assertEqual(r['iops'], 0)
+ self.assertFalse(r.has_key('iops_size'))
+
+ def testSnapshot(self):
+ self.checkConfig('base')
+ self.vm.qmp('blockdev-snapshot-sync',
+ node_name = 'base',
+ snapshot_node_name = 'target',
+ snapshot_file = self.target_img,
+ format = iotests.imgfmt)
+ self.checkConfig('target')
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=['qcow2'])
diff --git a/qemu/tests/qemu-iotests/096.out b/qemu/tests/qemu-iotests/096.out
new file mode 100644
index 000000000..ae1213e6f
--- /dev/null
+++ b/qemu/tests/qemu-iotests/096.out
@@ -0,0 +1,5 @@
+.
+----------------------------------------------------------------------
+Ran 1 tests
+
+OK
diff --git a/qemu/tests/qemu-iotests/097 b/qemu/tests/qemu-iotests/097
index c7a613b7e..01d8dd033 100755
--- a/qemu/tests/qemu-iotests/097
+++ b/qemu/tests/qemu-iotests/097
@@ -26,7 +26,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/097.out b/qemu/tests/qemu-iotests/097.out
index 81651f496..48abd2e64 100644
--- a/qemu/tests/qemu-iotests/097.out
+++ b/qemu/tests/qemu-iotests/097.out
@@ -3,8 +3,8 @@ QA output created by 097
=== Test pass 0 ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd'
+Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.itmd
wrote 196608/196608 bytes at offset 0
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 65536
@@ -32,8 +32,8 @@ Offset Length File
=== Test pass 1 ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd'
+Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.itmd
wrote 196608/196608 bytes at offset 0
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 65536
@@ -62,8 +62,8 @@ Offset Length File
=== Test pass 2 ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd'
+Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.itmd
wrote 196608/196608 bytes at offset 0
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 65536
@@ -92,8 +92,8 @@ Offset Length File
=== Test pass 3 ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.itmd'
+Formatting 'TEST_DIR/t.IMGFMT.itmd', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.itmd
wrote 196608/196608 bytes at offset 0
192 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
wrote 131072/131072 bytes at offset 65536
diff --git a/qemu/tests/qemu-iotests/098 b/qemu/tests/qemu-iotests/098
index e2230ad60..b002e969b 100755
--- a/qemu/tests/qemu-iotests/098
+++ b/qemu/tests/qemu-iotests/098
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/098.out b/qemu/tests/qemu-iotests/098.out
index e08a189b4..7634d0e8b 100644
--- a/qemu/tests/qemu-iotests/098.out
+++ b/qemu/tests/qemu-iotests/098.out
@@ -3,7 +3,7 @@ QA output created by 098
=== l1_update ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
@@ -12,7 +12,7 @@ No errors were found on the image.
=== empty_image_prepare ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
@@ -25,7 +25,7 @@ No errors were found on the image.
=== reftable_update ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
@@ -39,7 +39,7 @@ No errors were found on the image.
=== refblock_alloc ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
qemu-img: Could not empty blkdebug:TEST_DIR/blkdebug.conf:TEST_DIR/t.IMGFMT: Input/output error
diff --git a/qemu/tests/qemu-iotests/099 b/qemu/tests/qemu-iotests/099
index 80f3d9aaf..caaf58eee 100755
--- a/qemu/tests/qemu-iotests/099
+++ b/qemu/tests/qemu-iotests/099
@@ -26,7 +26,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/100 b/qemu/tests/qemu-iotests/100
index 7c1b235b5..5b2fb3333 100755
--- a/qemu/tests/qemu-iotests/100
+++ b/qemu/tests/qemu-iotests/100
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/101 b/qemu/tests/qemu-iotests/101
index 70fbf25f6..ea53f8b8d 100755
--- a/qemu/tests/qemu-iotests/101
+++ b/qemu/tests/qemu-iotests/101
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/102 b/qemu/tests/qemu-iotests/102
index 161b1974c..64b4af944 100755
--- a/qemu/tests/qemu-iotests/102
+++ b/qemu/tests/qemu-iotests/102
@@ -25,7 +25,6 @@ seq=$(basename $0)
echo "QA output created by $seq"
here=$PWD
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/103 b/qemu/tests/qemu-iotests/103
index fa9a3c1fc..ecbd8ebd7 100755
--- a/qemu/tests/qemu-iotests/103
+++ b/qemu/tests/qemu-iotests/103
@@ -25,7 +25,6 @@ seq=$(basename $0)
echo "QA output created by $seq"
here=$PWD
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/103.out b/qemu/tests/qemu-iotests/103.out
index d05f49fdb..b7aaadf89 100644
--- a/qemu/tests/qemu-iotests/103.out
+++ b/qemu/tests/qemu-iotests/103.out
@@ -5,10 +5,10 @@ wrote 65536/65536 bytes at offset 0
=== Testing invalid option combinations ===
-qemu-io: can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set the same time
-qemu-io: can't open device TEST_DIR/t.IMGFMT: l2-cache-size may not exceed cache-size
-qemu-io: can't open device TEST_DIR/t.IMGFMT: refcount-cache-size may not exceed cache-size
-qemu-io: can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set the same time
+can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set the same time
+can't open device TEST_DIR/t.IMGFMT: l2-cache-size may not exceed cache-size
+can't open device TEST_DIR/t.IMGFMT: refcount-cache-size may not exceed cache-size
+can't open device TEST_DIR/t.IMGFMT: cache-size, l2-cache-size and refcount-cache-size may not be set the same time
=== Testing valid option combinations ===
diff --git a/qemu/tests/qemu-iotests/104 b/qemu/tests/qemu-iotests/104
index 2e35ea80d..726d46705 100755
--- a/qemu/tests/qemu-iotests/104
+++ b/qemu/tests/qemu-iotests/104
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
trap "exit \$status" 0 1 2 3 15
diff --git a/qemu/tests/qemu-iotests/105 b/qemu/tests/qemu-iotests/105
index 9bae49e32..3db4ce3cf 100755
--- a/qemu/tests/qemu-iotests/105
+++ b/qemu/tests/qemu-iotests/105
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/107 b/qemu/tests/qemu-iotests/107
index 986203046..d7222dc1c 100755
--- a/qemu/tests/qemu-iotests/107
+++ b/qemu/tests/qemu-iotests/107
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/108 b/qemu/tests/qemu-iotests/108
index ce447498e..2355d98c1 100755
--- a/qemu/tests/qemu-iotests/108
+++ b/qemu/tests/qemu-iotests/108
@@ -26,7 +26,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/109 b/qemu/tests/qemu-iotests/109
index 0b668da85..f980b0c9e 100755
--- a/qemu/tests/qemu-iotests/109
+++ b/qemu/tests/qemu-iotests/109
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/109.out b/qemu/tests/qemu-iotests/109.out
index 7db92c9ce..38bc073a3 100644
--- a/qemu/tests/qemu-iotests/109.out
+++ b/qemu/tests/qemu-iotests/109.out
@@ -2,8 +2,8 @@ QA output created by 109
=== Writing a qcow header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -23,15 +23,15 @@ Images are identical.
=== Writing a qcow2 header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 197120, "offset": 512, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
{"return": []}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -44,15 +44,15 @@ Images are identical.
=== Writing a qed header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_ERROR", "data": {"device": "src", "operation": "write", "action": "report"}}
-{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 0, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 327680, "offset": 262144, "speed": 0, "type": "mirror", "error": "Operation not permitted"}}
{"return": []}
read 65536/65536 bytes at offset 0
64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -65,8 +65,8 @@ Images are identical.
=== Writing a vdi header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -86,8 +86,8 @@ Images are identical.
=== Writing a vmdk header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -107,8 +107,8 @@ Images are identical.
=== Writing a vpc header into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.raw.src', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -128,7 +128,7 @@ Images are identical.
=== Copying sample image empty.bochs into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -149,7 +149,7 @@ Images are identical.
=== Copying sample image iotest-dirtylog-10G-4M.vhdx into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -170,7 +170,7 @@ Images are identical.
=== Copying sample image parallels-v1 into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -191,7 +191,7 @@ Images are identical.
=== Copying sample image simple-pattern.cloop into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
@@ -212,7 +212,7 @@ Images are identical.
=== Write legitimate MBR into raw ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
{"return": {}}
WARNING: Image format was not specified for 'TEST_DIR/t.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
diff --git a/qemu/tests/qemu-iotests/110 b/qemu/tests/qemu-iotests/110
index a687f9567..9de7369f3 100755
--- a/qemu/tests/qemu-iotests/110
+++ b/qemu/tests/qemu-iotests/110
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/110.out b/qemu/tests/qemu-iotests/110.out
index 152bacf41..b3584ff87 100644
--- a/qemu/tests/qemu-iotests/110.out
+++ b/qemu/tests/qemu-iotests/110.out
@@ -3,7 +3,7 @@ QA output created by 110
=== Reconstructable filename ===
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 64M (67108864 bytes)
@@ -11,9 +11,12 @@ backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)
=== Non-reconstructable filename ===
-qemu-img: Cannot use relative backing file names for 'json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}'
+image: json:{"driver": "IMGFMT", "file": {"set-state.0.event": "read_aio", "image": {"driver": "file", "filename": "TEST_DIR/t.IMGFMT"}, "driver": "blkdebug", "set-state.0.new_state": 42}}
+file format: IMGFMT
+virtual size: 64M (67108864 bytes)
+backing file: t.IMGFMT.base (cannot determine actual path)
=== Backing name is always relative to the backed image ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.base
*** done
diff --git a/qemu/tests/qemu-iotests/111 b/qemu/tests/qemu-iotests/111
index 6011c94b7..a1c152d0c 100755
--- a/qemu/tests/qemu-iotests/111
+++ b/qemu/tests/qemu-iotests/111
@@ -26,7 +26,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/112 b/qemu/tests/qemu-iotests/112
index 3f054a3fc..28eb9aae9 100755
--- a/qemu/tests/qemu-iotests/112
+++ b/qemu/tests/qemu-iotests/112
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -180,6 +179,115 @@ $QEMU_IMG snapshot -c foo "$TEST_IMG"
# leaked (refcount=UINT64_MAX reference=1)
_check_test_img
+echo
+echo '=== Amend from refcount_bits=16 to refcount_bits=1 ==='
+echo
+
+_make_test_img 64M
+print_refcount_bits
+
+$QEMU_IO -c 'write 16M 32M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IMG amend -o refcount_bits=1 "$TEST_IMG"
+_check_test_img
+print_refcount_bits
+
+echo
+echo '=== Amend from refcount_bits=1 to refcount_bits=64 ==='
+echo
+
+$QEMU_IMG amend -o refcount_bits=64 "$TEST_IMG"
+_check_test_img
+print_refcount_bits
+
+echo
+echo '=== Amend to compat=0.10 ==='
+echo
+
+# Should not work because refcount_bits needs to be 16 for compat=0.10
+$QEMU_IMG amend -o compat=0.10 "$TEST_IMG"
+print_refcount_bits
+# Should work
+$QEMU_IMG amend -o compat=0.10,refcount_bits=16 "$TEST_IMG"
+_check_test_img
+print_refcount_bits
+
+# Get back to compat=1.1 and refcount_bits=16
+$QEMU_IMG amend -o compat=1.1 "$TEST_IMG"
+print_refcount_bits
+# Should not work
+$QEMU_IMG amend -o refcount_bits=32,compat=0.10 "$TEST_IMG"
+print_refcount_bits
+
+echo
+echo '=== Amend with snapshot ==='
+echo
+
+$QEMU_IMG snapshot -c foo "$TEST_IMG"
+# Just to have different refcounts across the image
+$QEMU_IO -c 'write 0 16M' "$TEST_IMG" | _filter_qemu_io
+
+# Should not work (may work in the future by first decreasing all refcounts so
+# they fit into the target range by copying them)
+$QEMU_IMG amend -o refcount_bits=1 "$TEST_IMG"
+_check_test_img
+print_refcount_bits
+
+# Should work
+$QEMU_IMG amend -o refcount_bits=2 "$TEST_IMG"
+_check_test_img
+print_refcount_bits
+
+echo
+echo '=== Testing too many references for check ==='
+echo
+
+IMGOPTS="$IMGOPTS,refcount_bits=1" _make_test_img 64M
+print_refcount_bits
+
+# This cluster should be created at 0x50000
+$QEMU_IO -c 'write 0 64k' "$TEST_IMG" | _filter_qemu_io
+# Now make the second L2 entry (the L2 table should be at 0x40000) point to that
+# cluster, so we have two references
+poke_file "$TEST_IMG" $((0x40008)) "\x80\x00\x00\x00\x00\x05\x00\x00"
+
+# This should say "please use amend"
+_check_test_img -r all
+
+# So we do that
+$QEMU_IMG amend -o refcount_bits=2 "$TEST_IMG"
+print_refcount_bits
+
+# And try again
+_check_test_img -r all
+
+echo
+echo '=== Multiple walks necessary during amend ==='
+echo
+
+IMGOPTS="$IMGOPTS,refcount_bits=1,cluster_size=512" _make_test_img 64k
+
+# Cluster 0 is the image header, clusters 1 to 4 are used by the L1 table, a
+# single L2 table, the reftable and a single refblock. This creates 58 data
+# clusters (actually, the L2 table is created here, too), so in total there are
+# then 63 used clusters in the image. With a refcount width of 64, one refblock
+# describes 64 clusters (512 bytes / 64 bits/entry = 64 entries), so this will
+# make the first refblock in the amended image have exactly one free entry.
+$QEMU_IO -c "write 0 $((58 * 512))" "$TEST_IMG" | _filter_qemu_io
+
+# Now change the refcount width; since the first new refblock will have exactly
+# one free entry, that entry will be used to store its own reference. No other
+# refblocks are needed, so then the new reftable will be allocated; since the
+# first new refblock is completely filled up, this will require a new refblock
+# which is why the refcount width changing function will need to run through
+# everything one more time until the allocations are stable.
+# Having more walks than usual should be visible as regressing progress (from
+# 66.67 % (2/3 walks) to 50.00 % (2/4 walks)).
+$QEMU_IMG amend -o refcount_bits=64 -p "$TEST_IMG" | tr '\r' '\n' \
+ | grep -A 1 '66.67'
+print_refcount_bits
+
+_check_test_img
+
# success, all done
echo '*** done'
diff --git a/qemu/tests/qemu-iotests/112.out b/qemu/tests/qemu-iotests/112.out
index 9a98633f6..81b04d145 100644
--- a/qemu/tests/qemu-iotests/112.out
+++ b/qemu/tests/qemu-iotests/112.out
@@ -21,9 +21,9 @@ refcount bits: 16
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
refcount bits: 16
-qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater)
+qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use or greater)
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
-qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater)
+qemu-img: TEST_DIR/t.IMGFMT: Different refcount widths than 16 bits require compatibility level 1.1 or above (use or greater)
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
=== Snapshot limit on refcount_bits=1 ===
@@ -81,4 +81,75 @@ Leaked cluster 6 refcount=1 reference=0
2 leaked clusters were found on the image.
This means waste of disk space, but no harm to data.
+
+=== Amend from refcount_bits=16 to refcount_bits=1 ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+refcount bits: 16
+wrote 33554432/33554432 bytes at offset 16777216
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+No errors were found on the image.
+refcount bits: 1
+
+=== Amend from refcount_bits=1 to refcount_bits=64 ===
+
+No errors were found on the image.
+refcount bits: 64
+
+=== Amend to compat=0.10 ===
+
+qemu-img: compat=0.10 requires refcount_bits=16
+qemu-img: Error while amending options: Operation not supported
+refcount bits: 64
+No errors were found on the image.
+refcount bits: 16
+refcount bits: 16
+qemu-img: Different refcount widths than 16 bits require compatibility level 1.1 or above (use compat=1.1 or greater)
+qemu-img: Error while amending options: Invalid argument
+refcount bits: 16
+
+=== Amend with snapshot ===
+
+wrote 16777216/16777216 bytes at offset 0
+16 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-img: Cannot decrease refcount entry width to 1 bits: Cluster at offset 0x50000 has a refcount of 2
+qemu-img: Error while amending options: Invalid argument
+No errors were found on the image.
+refcount bits: 16
+No errors were found on the image.
+refcount bits: 2
+
+=== Testing too many references for check ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+refcount bits: 1
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ERROR: overflow cluster offset=0x50000
+Use qemu-img amend to increase the refcount entry width or qemu-img convert to create a clean copy if the image cannot be opened for writing
+
+1 errors were found on the image.
+Data may be corrupted, or further writes to the image may corrupt it.
+refcount bits: 2
+ERROR cluster 5 refcount=1 reference=2
+Repairing cluster 5 refcount=1 reference=2
+Repairing OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=2
+Repairing OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=2
+The following inconsistencies were found and repaired:
+
+ 0 leaked clusters
+ 3 corruptions
+
+Double checking the fixed image now...
+No errors were found on the image.
+
+=== Multiple walks necessary during amend ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
+wrote 29696/29696 bytes at offset 0
+29 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+ (66.67/100%)
+ (50.00/100%)
+refcount bits: 64
+No errors were found on the image.
*** done
diff --git a/qemu/tests/qemu-iotests/113 b/qemu/tests/qemu-iotests/113
index a2cd96b17..19b68b272 100755
--- a/qemu/tests/qemu-iotests/113
+++ b/qemu/tests/qemu-iotests/113
@@ -26,7 +26,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/114 b/qemu/tests/qemu-iotests/114
index d02e7ffbe..f110d4f65 100755
--- a/qemu/tests/qemu-iotests/114
+++ b/qemu/tests/qemu-iotests/114
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/114.out b/qemu/tests/qemu-iotests/114.out
index 6c6b21085..b6d10e480 100644
--- a/qemu/tests/qemu-iotests/114.out
+++ b/qemu/tests/qemu-iotests/114.out
@@ -1,13 +1,13 @@
QA output created by 114
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 64M (67108864 bytes)
cluster_size: 65536
backing file: TEST_DIR/t.IMGFMT.base
backing file format: foo
-qemu-io: can't open device TEST_DIR/t.qcow2: Could not open backing file: Unknown driver 'foo'
+can't open device TEST_DIR/t.qcow2: Could not open backing file: Unknown driver 'foo'
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
*** done
diff --git a/qemu/tests/qemu-iotests/115 b/qemu/tests/qemu-iotests/115
index a6be1876a..665c2ead4 100755
--- a/qemu/tests/qemu-iotests/115
+++ b/qemu/tests/qemu-iotests/115
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/115.out b/qemu/tests/qemu-iotests/115.out
index 7b2c5e02f..dbdad17b2 100644
--- a/qemu/tests/qemu-iotests/115.out
+++ b/qemu/tests/qemu-iotests/115.out
@@ -2,7 +2,7 @@ QA output created by 115
=== Testing large refcount and L1 table ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=268435456 preallocation='metadata'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=268435456 preallocation=metadata
No errors were found on the image.
100.00% allocated clusters
*** done
diff --git a/qemu/tests/qemu-iotests/116 b/qemu/tests/qemu-iotests/116
index 713ed484b..df0172fed 100755
--- a/qemu/tests/qemu-iotests/116
+++ b/qemu/tests/qemu-iotests/116
@@ -28,7 +28,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/116.out b/qemu/tests/qemu-iotests/116.out
index b679ceea6..1f11d4446 100644
--- a/qemu/tests/qemu-iotests/116.out
+++ b/qemu/tests/qemu-iotests/116.out
@@ -2,36 +2,36 @@ QA output created by 116
== truncated header cluster ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
+can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
no file open, try 'help open'
== invalid header magic ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-qemu-io: can't open device TEST_DIR/t.qed: Image not in QED format
+can't open device TEST_DIR/t.qed: Image not in QED format
no file open, try 'help open'
== invalid cluster size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
+can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
no file open, try 'help open'
== invalid table size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
+can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
no file open, try 'help open'
== invalid header size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
+can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
no file open, try 'help open'
== invalid L1 table offset ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
+can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
no file open, try 'help open'
== invalid image size ==
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
-qemu-io: can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
+can't open device TEST_DIR/t.qed: Could not open 'TEST_DIR/t.qed': Invalid argument
no file open, try 'help open'
*** done
diff --git a/qemu/tests/qemu-iotests/117 b/qemu/tests/qemu-iotests/117
new file mode 100755
index 000000000..9385b3f8d
--- /dev/null
+++ b/qemu/tests/qemu-iotests/117
@@ -0,0 +1,85 @@
+#!/bin/bash
+#
+# Test case for shared BDS between backend trees
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+_make_test_img 64k
+
+_launch_qemu
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'blockdev-add',
+ 'arguments': { 'options': { 'id': 'protocol',
+ 'driver': 'file',
+ 'filename': '$TEST_IMG' } } }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'blockdev-add',
+ 'arguments': { 'options': { 'id': 'format',
+ 'driver': '$IMGFMT',
+ 'file': 'protocol' } } }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'human-monitor-command',
+ 'arguments': { 'command-line': 'qemu-io format \"write -P 42 0 64k\"' } }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'quit' }" \
+ 'return'
+
+wait=1 _cleanup_qemu
+
+_check_test_img
+
+$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/117.out b/qemu/tests/qemu-iotests/117.out
new file mode 100644
index 000000000..f52dc1a35
--- /dev/null
+++ b/qemu/tests/qemu-iotests/117.out
@@ -0,0 +1,14 @@
+QA output created by 117
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
+{"return": {}}
+{"return": {}}
+{"return": {}}
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": ""}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+No errors were found on the image.
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/qemu/tests/qemu-iotests/118 b/qemu/tests/qemu-iotests/118
new file mode 100755
index 000000000..9e5951f64
--- /dev/null
+++ b/qemu/tests/qemu-iotests/118
@@ -0,0 +1,677 @@
+#!/usr/bin/env python
+#
+# Test case for the QMP 'change' command and all other associated
+# commands
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import stat
+import time
+import iotests
+from iotests import qemu_img
+
+old_img = os.path.join(iotests.test_dir, 'test0.img')
+new_img = os.path.join(iotests.test_dir, 'test1.img')
+
+class ChangeBaseClass(iotests.QMPTestCase):
+ has_opened = False
+ has_closed = False
+
+ def process_events(self):
+ for event in self.vm.get_qmp_events(wait=False):
+ if (event['event'] == 'DEVICE_TRAY_MOVED' and
+ event['data']['device'] == 'drive0'):
+ if event['data']['tray-open'] == False:
+ self.has_closed = True
+ else:
+ self.has_opened = True
+
+ def wait_for_open(self):
+ if not self.has_real_tray:
+ return
+
+ timeout = time.clock() + 3
+ while not self.has_opened and time.clock() < timeout:
+ self.process_events()
+ if not self.has_opened:
+ self.fail('Timeout while waiting for the tray to open')
+
+ def wait_for_close(self):
+ if not self.has_real_tray:
+ return
+
+ timeout = time.clock() + 3
+ while not self.has_closed and time.clock() < timeout:
+ self.process_events()
+ if not self.has_opened:
+ self.fail('Timeout while waiting for the tray to close')
+
+class GeneralChangeTestsBaseClass(ChangeBaseClass):
+ def test_change(self):
+ result = self.vm.qmp('change', device='drive0', target=new_img,
+ arg=iotests.imgfmt)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+ self.wait_for_close()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_blockdev_change_medium(self):
+ result = self.vm.qmp('blockdev-change-medium', device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+ self.wait_for_close()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_eject(self):
+ result = self.vm.qmp('eject', device='drive0', force=True)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+
+ def test_tray_eject_change(self):
+ result = self.vm.qmp('eject', device='drive0', force=True)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+
+ result = self.vm.qmp('blockdev-change-medium', device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_close()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_tray_open_close(self):
+ result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.was_empty == True:
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+ else:
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-close-tray', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ if self.has_real_tray or not self.was_empty:
+ self.wait_for_close()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
+ if self.was_empty == True:
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+ else:
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ def test_tray_eject_close(self):
+ result = self.vm.qmp('eject', device='drive0', force=True)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+
+ result = self.vm.qmp('blockdev-close-tray', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_close()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+
+ def test_tray_open_change(self):
+ result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.was_empty == True:
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+ else:
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium', device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_close()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_cycle(self):
+ result = self.vm.qmp('blockdev-add',
+ options={'node-name': 'new',
+ 'driver': iotests.imgfmt,
+ 'file': {'filename': new_img,
+ 'driver': 'file'}})
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('blockdev-open-tray', device='drive0', force=True)
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
+ if self.was_empty == True:
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+ else:
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+
+ result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
+ node_name='new')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ result = self.vm.qmp('blockdev-close-tray', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_close()
+
+ result = self.vm.qmp('query-block')
+ if self.has_real_tray:
+ self.assert_qmp(result, 'return[0]/tray_open', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_close_on_closed(self):
+ result = self.vm.qmp('blockdev-close-tray', device='drive0')
+ # Should be a no-op
+ self.assert_qmp(result, 'return', {})
+ self.assertEquals(self.vm.get_qmp_events(wait=False), [])
+
+ def test_remove_on_closed(self):
+ if not self.has_real_tray:
+ return
+
+ result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ def test_insert_on_closed(self):
+ if not self.has_real_tray:
+ return
+
+ result = self.vm.qmp('blockdev-add',
+ options={'node-name': 'new',
+ 'driver': iotests.imgfmt,
+ 'file': {'filename': new_img,
+ 'driver': 'file'}})
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
+ node_name='new')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+class TestInitiallyFilled(GeneralChangeTestsBaseClass):
+ was_empty = False
+
+ def setUp(self, media, interface):
+ qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
+ qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
+ self.vm = iotests.VM().add_drive(old_img, 'media=%s' % media, interface)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(old_img)
+ os.remove(new_img)
+
+ def test_insert_on_filled(self):
+ result = self.vm.qmp('blockdev-add',
+ options={'node-name': 'new',
+ 'driver': iotests.imgfmt,
+ 'file': {'filename': new_img,
+ 'driver': 'file'}})
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('blockdev-open-tray', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+
+ result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
+ node_name='new')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+class TestInitiallyEmpty(GeneralChangeTestsBaseClass):
+ was_empty = True
+
+ def setUp(self, media, interface):
+ qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
+ self.vm = iotests.VM().add_drive(None, 'media=%s' % media, interface)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(new_img)
+
+ def test_remove_on_empty(self):
+ result = self.vm.qmp('blockdev-open-tray', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.wait_for_open()
+
+ result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
+ # Should be a no-op
+ self.assert_qmp(result, 'return', {})
+
+class TestCDInitiallyFilled(TestInitiallyFilled):
+ TestInitiallyFilled = TestInitiallyFilled
+ has_real_tray = True
+
+ def setUp(self):
+ self.TestInitiallyFilled.setUp(self, 'cdrom', 'ide')
+
+class TestCDInitiallyEmpty(TestInitiallyEmpty):
+ TestInitiallyEmpty = TestInitiallyEmpty
+ has_real_tray = True
+
+ def setUp(self):
+ self.TestInitiallyEmpty.setUp(self, 'cdrom', 'ide')
+
+class TestFloppyInitiallyFilled(TestInitiallyFilled):
+ TestInitiallyFilled = TestInitiallyFilled
+ has_real_tray = False
+
+ def setUp(self):
+ self.TestInitiallyFilled.setUp(self, 'disk', 'floppy')
+
+class TestFloppyInitiallyEmpty(TestInitiallyEmpty):
+ TestInitiallyEmpty = TestInitiallyEmpty
+ has_real_tray = False
+
+ def setUp(self):
+ self.TestInitiallyEmpty.setUp(self, 'disk', 'floppy')
+ # FDDs not having a real tray and there not being a medium inside the
+ # tray at startup means the tray will be considered open
+ self.has_opened = True
+
+class TestChangeReadOnly(ChangeBaseClass):
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, old_img, '1440k')
+ qemu_img('create', '-f', iotests.imgfmt, new_img, '1440k')
+ self.vm = iotests.VM()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.chmod(old_img, 0666)
+ os.chmod(new_img, 0666)
+ os.remove(old_img)
+ os.remove(new_img)
+
+ def test_ro_ro_retain(self):
+ os.chmod(old_img, 0444)
+ os.chmod(new_img, 0444)
+ self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium', device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt,
+ read_only_mode='retain')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_ro_rw_retain(self):
+ os.chmod(old_img, 0444)
+ self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium', device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt,
+ read_only_mode='retain')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_rw_ro_retain(self):
+ os.chmod(new_img, 0444)
+ self.vm.add_drive(old_img, 'media=disk', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium', device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt,
+ read_only_mode='retain')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ self.assertEquals(self.vm.get_qmp_events(wait=False), [])
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ def test_ro_rw(self):
+ os.chmod(old_img, 0444)
+ self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium',
+ device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt,
+ read_only_mode='read-write')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_rw_ro(self):
+ os.chmod(new_img, 0444)
+ self.vm.add_drive(old_img, 'media=disk', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium',
+ device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt,
+ read_only_mode='read-only')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_make_rw_ro(self):
+ self.vm.add_drive(old_img, 'media=disk', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium',
+ device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt,
+ read_only_mode='read-only')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_make_ro_rw(self):
+ os.chmod(new_img, 0444)
+ self.vm.add_drive(old_img, 'media=disk', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium',
+ device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt,
+ read_only_mode='read-write')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ def test_make_rw_ro_by_retain(self):
+ os.chmod(old_img, 0444)
+ self.vm.add_drive(old_img, 'media=disk,read-only=on', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium', device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt,
+ read_only_mode='retain')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ def test_make_ro_rw_by_retain(self):
+ os.chmod(new_img, 0444)
+ self.vm.add_drive(old_img, 'media=disk', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-change-medium', device='drive0',
+ filename=new_img,
+ format=iotests.imgfmt,
+ read_only_mode='retain')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ def test_rw_ro_cycle(self):
+ os.chmod(new_img, 0444)
+ self.vm.add_drive(old_img, 'media=disk', 'floppy')
+ self.vm.launch()
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('blockdev-add',
+ options={'node-name': 'new',
+ 'driver': iotests.imgfmt,
+ 'read-only': True,
+ 'file': {'filename': new_img,
+ 'driver': 'file'}})
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', False)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+
+ result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
+ node_name='new')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/ro', True)
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+
+GeneralChangeTestsBaseClass = None
+TestInitiallyFilled = None
+TestInitiallyEmpty = None
+
+
+class TestBlockJobsAfterCycle(ChangeBaseClass):
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, old_img, '1M')
+
+ self.vm = iotests.VM()
+ self.vm.launch()
+
+ result = self.vm.qmp('blockdev-add',
+ options={'id': 'drive0',
+ 'driver': 'null-co'})
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/image/format', 'null-co')
+
+ # For device-less BBs, calling blockdev-open-tray or blockdev-close-tray
+ # is not necessary
+ result = self.vm.qmp('x-blockdev-remove-medium', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp_absent(result, 'return[0]/inserted')
+
+ result = self.vm.qmp('blockdev-add',
+ options={'node-name': 'node0',
+ 'driver': iotests.imgfmt,
+ 'file': {'filename': old_img,
+ 'driver': 'file'}})
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('x-blockdev-insert-medium', device='drive0',
+ node_name='node0')
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', old_img)
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(old_img)
+ try:
+ os.remove(new_img)
+ except OSError:
+ pass
+
+ def test_snapshot_and_commit(self):
+ # We need backing file support
+ if iotests.imgfmt != 'qcow2' and iotests.imgfmt != 'qed':
+ return
+
+ result = self.vm.qmp('blockdev-snapshot-sync', device='drive0',
+ snapshot_file=new_img,
+ format=iotests.imgfmt)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('query-block')
+ self.assert_qmp(result, 'return[0]/inserted/image/filename', new_img)
+ self.assert_qmp(result,
+ 'return[0]/inserted/image/backing-image/filename',
+ old_img)
+
+ result = self.vm.qmp('block-commit', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.event_wait(name='BLOCK_JOB_READY')
+
+ result = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(result, 'return[0]/device', 'drive0')
+
+ result = self.vm.qmp('block-job-complete', device='drive0')
+ self.assert_qmp(result, 'return', {})
+
+ self.vm.event_wait(name='BLOCK_JOB_COMPLETED')
+
+
+if __name__ == '__main__':
+ if iotests.qemu_default_machine != 'pc':
+ # We need floppy and IDE CD-ROM
+ iotests.notrun('not suitable for this machine type: %s' %
+ iotests.qemu_default_machine)
+ # Need to support image creation
+ iotests.main(supported_fmts=['vpc', 'parallels', 'qcow', 'vdi', 'qcow2',
+ 'vmdk', 'raw', 'vhdx', 'qed'])
diff --git a/qemu/tests/qemu-iotests/118.out b/qemu/tests/qemu-iotests/118.out
new file mode 100644
index 000000000..6a917130b
--- /dev/null
+++ b/qemu/tests/qemu-iotests/118.out
@@ -0,0 +1,5 @@
+...........................................................
+----------------------------------------------------------------------
+Ran 59 tests
+
+OK
diff --git a/qemu/tests/qemu-iotests/119 b/qemu/tests/qemu-iotests/119
index 9a11f1b92..4f34fb434 100755
--- a/qemu/tests/qemu-iotests/119
+++ b/qemu/tests/qemu-iotests/119
@@ -26,7 +26,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -49,7 +48,7 @@ echo "{'execute': 'qmp_capabilities'}
{'execute': 'human-monitor-command',
'arguments': {'command-line': 'qemu-io drv \"read -P 0 0 64k\"'}}
{'execute': 'quit'}" \
- | $QEMU -drive id=drv,if=none,file="$TEST_IMG",driver=nbd \
+ | $QEMU -nographic -drive id=drv,if=none,file="$TEST_IMG",driver=nbd \
-qmp stdio -nodefaults \
| _filter_qmp | _filter_qemu_io
diff --git a/qemu/tests/qemu-iotests/120 b/qemu/tests/qemu-iotests/120
index 9f1307876..4f88a67fe 100755
--- a/qemu/tests/qemu-iotests/120
+++ b/qemu/tests/qemu-iotests/120
@@ -26,7 +26,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -49,7 +48,7 @@ echo "{'execute': 'qmp_capabilities'}
{'execute': 'human-monitor-command',
'arguments': {'command-line': 'qemu-io drv \"write -P 42 0 64k\"'}}
{'execute': 'quit'}" \
- | $QEMU -qmp stdio -nodefaults \
+ | $QEMU -qmp stdio -nographic -nodefaults \
-drive id=drv,if=none,file="$TEST_IMG",driver=raw,file.driver=$IMGFMT \
| _filter_qmp | _filter_qemu_io
$QEMU_IO -c 'read -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
diff --git a/qemu/tests/qemu-iotests/121 b/qemu/tests/qemu-iotests/121
index 0912c3f0c..1307b4e32 100755
--- a/qemu/tests/qemu-iotests/121
+++ b/qemu/tests/qemu-iotests/121
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/121.out b/qemu/tests/qemu-iotests/121.out
index ff18e2c61..5961a44cd 100644
--- a/qemu/tests/qemu-iotests/121.out
+++ b/qemu/tests/qemu-iotests/121.out
@@ -4,7 +4,7 @@ QA output created by 121
--- Test 1 ---
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66060288 preallocation='metadata'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66060288 preallocation=metadata
Image resized.
wrote 1049600/1049600 bytes at offset 65011712
1.001 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
@@ -14,7 +14,7 @@ No errors were found on the image.
--- Test 2 ---
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66061312 preallocation='metadata'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=66061312 preallocation=metadata
Image resized.
wrote 133120/133120 bytes at offset 66060288
130 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/qemu/tests/qemu-iotests/122 b/qemu/tests/qemu-iotests/122
index 350ca9c46..45b359c2b 100755
--- a/qemu/tests/qemu-iotests/122
+++ b/qemu/tests/qemu-iotests/122
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/122.out b/qemu/tests/qemu-iotests/122.out
index 1f853b9e9..98814de5d 100644
--- a/qemu/tests/qemu-iotests/122.out
+++ b/qemu/tests/qemu-iotests/122.out
@@ -5,7 +5,7 @@ wrote 67108864/67108864 bytes at offset 0
=== Check allocation status regression with -B ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 3145728/3145728 bytes at offset 0
3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Offset Length File
@@ -14,7 +14,7 @@ Offset Length File
=== Check that zero clusters are kept in overlay ===
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 3145728/3145728 bytes at offset 0
3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 3145728/3145728 bytes at offset 0
@@ -112,20 +112,18 @@ read 3145728/3145728 bytes at offset 0
3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 63963136/63963136 bytes at offset 3145728
61 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-[{ "start": 0, "length": 6291456, "depth": 0, "zero": false, "data": true, "offset": 327680},
-{ "start": 6291456, "length": 60817408, "depth": 0, "zero": true, "data": false}]
+[{ "start": 0, "length": 67108864, "depth": 0, "zero": false, "data": true, "offset": 327680}]
convert -c -S 0:
read 3145728/3145728 bytes at offset 0
3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
read 63963136/63963136 bytes at offset 3145728
61 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-[{ "start": 0, "length": 6291456, "depth": 0, "zero": false, "data": true},
-{ "start": 6291456, "length": 60817408, "depth": 0, "zero": true, "data": false}]
+[{ "start": 0, "length": 67108864, "depth": 0, "zero": false, "data": true}]
Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
wrote 33554432/33554432 bytes at offset 0
32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.base'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
wrote 3145728/3145728 bytes at offset 0
3 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/qemu/tests/qemu-iotests/123 b/qemu/tests/qemu-iotests/123
index ad608035d..b18e3fca9 100755
--- a/qemu/tests/qemu-iotests/123
+++ b/qemu/tests/qemu-iotests/123
@@ -25,7 +25,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/124 b/qemu/tests/qemu-iotests/124
index 9ccd11809..de7cdbe00 100644
--- a/qemu/tests/qemu-iotests/124
+++ b/qemu/tests/qemu-iotests/124
@@ -36,6 +36,23 @@ def try_remove(img):
pass
+def transaction_action(action, **kwargs):
+ return {
+ 'type': action,
+ 'data': dict((k.replace('_', '-'), v) for k, v in kwargs.iteritems())
+ }
+
+
+def transaction_bitmap_clear(node, name, **kwargs):
+ return transaction_action('block-dirty-bitmap-clear',
+ node=node, name=name, **kwargs)
+
+
+def transaction_drive_backup(device, target, **kwargs):
+ return transaction_action('drive-backup', device=device, target=target,
+ **kwargs)
+
+
class Bitmap:
def __init__(self, name, drive):
self.name = name
@@ -74,24 +91,31 @@ class Bitmap:
try_remove(image)
-class TestIncrementalBackup(iotests.QMPTestCase):
- def setUp(self):
+class TestIncrementalBackupBase(iotests.QMPTestCase):
+ def __init__(self, *args):
+ super(TestIncrementalBackupBase, self).__init__(*args)
self.bitmaps = list()
self.files = list()
self.drives = list()
self.vm = iotests.VM()
self.err_img = os.path.join(iotests.test_dir, 'err.%s' % iotests.imgfmt)
+
+ def setUp(self):
# Create a base image with a distinctive patterning
drive0 = self.add_node('drive0')
self.img_create(drive0['file'], drive0['fmt'])
self.vm.add_drive(drive0['file'])
- io_write_patterns(drive0['file'], (('0x41', 0, 512),
- ('0xd5', '1M', '32k'),
- ('0xdc', '32M', '124k')))
+ self.write_default_pattern(drive0['file'])
self.vm.launch()
+ def write_default_pattern(self, target):
+ io_write_patterns(target, (('0x41', 0, 512),
+ ('0xd5', '1M', '32k'),
+ ('0xdc', '32M', '124k')))
+
+
def add_node(self, node_id, fmt=iotests.imgfmt, path=None, backup=None):
if path is None:
path = os.path.join(iotests.test_dir, '%s.%s' % (node_id, fmt))
@@ -108,23 +132,28 @@ class TestIncrementalBackup(iotests.QMPTestCase):
def img_create(self, img, fmt=iotests.imgfmt, size='64M',
- parent=None, parentFormat=None):
+ parent=None, parentFormat=None, **kwargs):
+ optargs = []
+ for k,v in kwargs.iteritems():
+ optargs = optargs + ['-o', '%s=%s' % (k,v)]
+ args = ['create', '-f', fmt] + optargs + [img, size]
if parent:
if parentFormat is None:
parentFormat = fmt
- iotests.qemu_img('create', '-f', fmt, img, size,
- '-b', parent, '-F', parentFormat)
- else:
- iotests.qemu_img('create', '-f', fmt, img, size)
+ args = args + ['-b', parent, '-F', parentFormat]
+ iotests.qemu_img(*args)
self.files.append(img)
def do_qmp_backup(self, error='Input/output error', **kwargs):
res = self.vm.qmp('drive-backup', **kwargs)
self.assert_qmp(res, 'return', {})
+ return self.wait_qmp_backup(kwargs['device'], error)
+
+ def wait_qmp_backup(self, device, error='Input/output error'):
event = self.vm.event_wait(name="BLOCK_JOB_COMPLETED",
- match={'data': {'device': kwargs['device']}})
+ match={'data': {'device': device}})
self.assertNotEqual(event, None)
try:
@@ -139,6 +168,12 @@ class TestIncrementalBackup(iotests.QMPTestCase):
return False
+ def wait_qmp_backup_cancelled(self, device):
+ event = self.vm.event_wait(name='BLOCK_JOB_CANCELLED',
+ match={'data': {'device': device}})
+ self.assertNotEqual(event, None)
+
+
def create_anchor_backup(self, drive=None):
if drive is None:
drive = self.drives[-1]
@@ -233,6 +268,16 @@ class TestIncrementalBackup(iotests.QMPTestCase):
self.check_backups()
+ def tearDown(self):
+ self.vm.shutdown()
+ for bitmap in self.bitmaps:
+ bitmap.cleanup()
+ for filename in self.files:
+ try_remove(filename)
+
+
+
+class TestIncrementalBackup(TestIncrementalBackupBase):
def test_incremental_simple(self):
'''
Test: Create and verify three incremental backups.
@@ -264,19 +309,110 @@ class TestIncrementalBackup(iotests.QMPTestCase):
return self.do_incremental_simple(granularity=131072)
- def test_incremental_failure(self):
- '''Test: Verify backups made after a failure are correct.
+ def test_larger_cluster_target(self):
+ '''
+ Test: Create and verify backups made to a larger cluster size target.
- Simulate a failure during an incremental backup block job,
- emulate additional writes, then create another incremental backup
- afterwards and verify that the backup created is correct.
+ With a default granularity of 64KiB, verify that backups made to a
+ larger cluster size target of 128KiB without a backing file works.
'''
+ drive0 = self.drives[0]
+
+ # Create a cluster_size=128k full backup / "anchor" backup
+ self.img_create(drive0['backup'], cluster_size='128k')
+ self.assertTrue(self.do_qmp_backup(device=drive0['id'], sync='full',
+ format=drive0['fmt'],
+ target=drive0['backup'],
+ mode='existing'))
+
+ # Create bitmap and dirty it with some new writes.
+ # overwrite [32736, 32799] which will dirty bitmap clusters at
+ # 32M-64K and 32M. 32M+64K will be left undirtied.
+ bitmap0 = self.add_bitmap('bitmap0', drive0)
+ self.hmp_io_writes(drive0['id'],
+ (('0xab', 0, 512),
+ ('0xfe', '16M', '256k'),
+ ('0x64', '32736k', '64k')))
+
+
+ # Prepare a cluster_size=128k backup target without a backing file.
+ (target, _) = bitmap0.new_target()
+ self.img_create(target, bitmap0.drive['fmt'], cluster_size='128k')
+
+ # Perform Incremental Backup
+ self.assertTrue(self.do_qmp_backup(device=bitmap0.drive['id'],
+ sync='incremental',
+ bitmap=bitmap0.name,
+ format=bitmap0.drive['fmt'],
+ target=target,
+ mode='existing'))
+ self.make_reference_backup(bitmap0)
+
+ # Add the backing file, then compare and exit.
+ iotests.qemu_img('rebase', '-f', drive0['fmt'], '-u', '-b',
+ drive0['backup'], '-F', drive0['fmt'], target)
+ self.vm.shutdown()
+ self.check_backups()
+
+
+ def test_incremental_transaction(self):
+ '''Test: Verify backups made from transactionally created bitmaps.
+
+ Create a bitmap "before" VM execution begins, then create a second
+ bitmap AFTER writes have already occurred. Use transactions to create
+ a full backup and synchronize both bitmaps to this backup.
+ Create an incremental backup through both bitmaps and verify that
+ both backups match the current drive0 image.
+ '''
+
+ drive0 = self.drives[0]
+ bitmap0 = self.add_bitmap('bitmap0', drive0)
+ self.hmp_io_writes(drive0['id'], (('0xab', 0, 512),
+ ('0xfe', '16M', '256k'),
+ ('0x64', '32736k', '64k')))
+ bitmap1 = self.add_bitmap('bitmap1', drive0)
+
+ result = self.vm.qmp('transaction', actions=[
+ transaction_bitmap_clear(bitmap0.drive['id'], bitmap0.name),
+ transaction_bitmap_clear(bitmap1.drive['id'], bitmap1.name),
+ transaction_drive_backup(drive0['id'], drive0['backup'],
+ sync='full', format=drive0['fmt'])
+ ])
+ self.assert_qmp(result, 'return', {})
+ self.wait_until_completed(drive0['id'])
+ self.files.append(drive0['backup'])
+
+ self.hmp_io_writes(drive0['id'], (('0x9a', 0, 512),
+ ('0x55', '8M', '352k'),
+ ('0x78', '15872k', '1M')))
+ # Both bitmaps should be correctly in sync.
+ self.create_incremental(bitmap0)
+ self.create_incremental(bitmap1)
+ self.vm.shutdown()
+ self.check_backups()
- # Create a blkdebug interface to this img as 'drive1',
- # but don't actually create a new image.
- drive1 = self.add_node('drive1', self.drives[0]['fmt'],
- path=self.drives[0]['file'],
- backup=self.drives[0]['backup'])
+
+ def test_transaction_failure(self):
+ '''Test: Verify backups made from a transaction that partially fails.
+
+ Add a second drive with its own unique pattern, and add a bitmap to each
+ drive. Use blkdebug to interfere with the backup on just one drive and
+ attempt to create a coherent incremental backup across both drives.
+
+ verify a failure in one but not both, then delete the failed stubs and
+ re-run the same transaction.
+
+ verify that both incrementals are created successfully.
+ '''
+
+ # Create a second drive, with pattern:
+ drive1 = self.add_node('drive1')
+ self.img_create(drive1['file'], drive1['fmt'])
+ io_write_patterns(drive1['file'], (('0x14', 0, 512),
+ ('0x5d', '1M', '32k'),
+ ('0xcd', '32M', '124k')))
+
+ # Create a blkdebug interface to this img as 'drive1'
result = self.vm.qmp('blockdev-add', options={
'id': drive1['id'],
'driver': drive1['fmt'],
@@ -302,21 +438,73 @@ class TestIncrementalBackup(iotests.QMPTestCase):
})
self.assert_qmp(result, 'return', {})
- self.create_anchor_backup(self.drives[0])
- self.add_bitmap('bitmap0', drive1)
- # Note: at this point, during a normal execution,
- # Assume that the VM resumes and begins issuing IO requests here.
+ # Create bitmaps and full backups for both drives
+ drive0 = self.drives[0]
+ dr0bm0 = self.add_bitmap('bitmap0', drive0)
+ dr1bm0 = self.add_bitmap('bitmap0', drive1)
+ self.create_anchor_backup(drive0)
+ self.create_anchor_backup(drive1)
+ self.assert_no_active_block_jobs()
+ self.assertFalse(self.vm.get_qmp_events(wait=False))
- self.hmp_io_writes(drive1['id'], (('0xab', 0, 512),
+ # Emulate some writes
+ self.hmp_io_writes(drive0['id'], (('0xab', 0, 512),
('0xfe', '16M', '256k'),
('0x64', '32736k', '64k')))
+ self.hmp_io_writes(drive1['id'], (('0xba', 0, 512),
+ ('0xef', '16M', '256k'),
+ ('0x46', '32736k', '64k')))
+
+ # Create incremental backup targets
+ target0 = self.prepare_backup(dr0bm0)
+ target1 = self.prepare_backup(dr1bm0)
+
+ # Ask for a new incremental backup per-each drive,
+ # expecting drive1's backup to fail:
+ transaction = [
+ transaction_drive_backup(drive0['id'], target0, sync='incremental',
+ format=drive0['fmt'], mode='existing',
+ bitmap=dr0bm0.name),
+ transaction_drive_backup(drive1['id'], target1, sync='incremental',
+ format=drive1['fmt'], mode='existing',
+ bitmap=dr1bm0.name)
+ ]
+ result = self.vm.qmp('transaction', actions=transaction,
+ properties={'completion-mode': 'grouped'} )
+ self.assert_qmp(result, 'return', {})
- result = self.create_incremental(validate=False)
- self.assertFalse(result)
- self.hmp_io_writes(drive1['id'], (('0x9a', 0, 512),
- ('0x55', '8M', '352k'),
- ('0x78', '15872k', '1M')))
- self.create_incremental()
+ # Observe that drive0's backup is cancelled and drive1 completes with
+ # an error.
+ self.wait_qmp_backup_cancelled(drive0['id'])
+ self.assertFalse(self.wait_qmp_backup(drive1['id']))
+ error = self.vm.event_wait('BLOCK_JOB_ERROR')
+ self.assert_qmp(error, 'data', {'device': drive1['id'],
+ 'action': 'report',
+ 'operation': 'read'})
+ self.assertFalse(self.vm.get_qmp_events(wait=False))
+ self.assert_no_active_block_jobs()
+
+ # Delete drive0's successful target and eliminate our record of the
+ # unsuccessful drive1 target. Then re-run the same transaction.
+ dr0bm0.del_target()
+ dr1bm0.del_target()
+ target0 = self.prepare_backup(dr0bm0)
+ target1 = self.prepare_backup(dr1bm0)
+
+ # Re-run the exact same transaction.
+ result = self.vm.qmp('transaction', actions=transaction,
+ properties={'completion-mode':'grouped'})
+ self.assert_qmp(result, 'return', {})
+
+ # Both should complete successfully this time.
+ self.assertTrue(self.wait_qmp_backup(drive0['id']))
+ self.assertTrue(self.wait_qmp_backup(drive1['id']))
+ self.make_reference_backup(dr0bm0)
+ self.make_reference_backup(dr1bm0)
+ self.assertFalse(self.vm.get_qmp_events(wait=False))
+ self.assert_no_active_block_jobs()
+
+ # And the images should of course validate.
self.vm.shutdown()
self.check_backups()
@@ -351,12 +539,66 @@ class TestIncrementalBackup(iotests.QMPTestCase):
granularity=64000)
- def tearDown(self):
+class TestIncrementalBackupBlkdebug(TestIncrementalBackupBase):
+ '''Incremental backup tests that utilize a BlkDebug filter on drive0.'''
+
+ def setUp(self):
+ drive0 = self.add_node('drive0')
+ self.img_create(drive0['file'], drive0['fmt'])
+ self.write_default_pattern(drive0['file'])
+ self.vm.launch()
+
+ def test_incremental_failure(self):
+ '''Test: Verify backups made after a failure are correct.
+
+ Simulate a failure during an incremental backup block job,
+ emulate additional writes, then create another incremental backup
+ afterwards and verify that the backup created is correct.
+ '''
+
+ drive0 = self.drives[0]
+ result = self.vm.qmp('blockdev-add', options={
+ 'id': drive0['id'],
+ 'driver': drive0['fmt'],
+ 'file': {
+ 'driver': 'blkdebug',
+ 'image': {
+ 'driver': 'file',
+ 'filename': drive0['file']
+ },
+ 'set-state': [{
+ 'event': 'flush_to_disk',
+ 'state': 1,
+ 'new_state': 2
+ }],
+ 'inject-error': [{
+ 'event': 'read_aio',
+ 'errno': 5,
+ 'state': 2,
+ 'immediately': False,
+ 'once': True
+ }],
+ }
+ })
+ self.assert_qmp(result, 'return', {})
+
+ self.create_anchor_backup(drive0)
+ self.add_bitmap('bitmap0', drive0)
+ # Note: at this point, during a normal execution,
+ # Assume that the VM resumes and begins issuing IO requests here.
+
+ self.hmp_io_writes(drive0['id'], (('0xab', 0, 512),
+ ('0xfe', '16M', '256k'),
+ ('0x64', '32736k', '64k')))
+
+ result = self.create_incremental(validate=False)
+ self.assertFalse(result)
+ self.hmp_io_writes(drive0['id'], (('0x9a', 0, 512),
+ ('0x55', '8M', '352k'),
+ ('0x78', '15872k', '1M')))
+ self.create_incremental()
self.vm.shutdown()
- for bitmap in self.bitmaps:
- bitmap.cleanup()
- for filename in self.files:
- try_remove(filename)
+ self.check_backups()
if __name__ == '__main__':
diff --git a/qemu/tests/qemu-iotests/124.out b/qemu/tests/qemu-iotests/124.out
index 2f7d3902f..36376bed8 100644
--- a/qemu/tests/qemu-iotests/124.out
+++ b/qemu/tests/qemu-iotests/124.out
@@ -1,5 +1,5 @@
-.......
+..........
----------------------------------------------------------------------
-Ran 7 tests
+Ran 10 tests
OK
diff --git a/qemu/tests/qemu-iotests/128 b/qemu/tests/qemu-iotests/128
index e2a0f2f89..0976a1813 100755
--- a/qemu/tests/qemu-iotests/128
+++ b/qemu/tests/qemu-iotests/128
@@ -25,12 +25,16 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
devname="eiodev$$"
sudo=""
+_sudo_qemu_io_wrapper()
+{
+ (exec $sudo "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@")
+}
+
_setup_eiodev()
{
# This test should either be run as root or with passwordless sudo
@@ -76,7 +80,9 @@ TEST_IMG="/dev/mapper/$devname"
echo
echo "== reading from error device =="
# Opening image should succeed but the read operation should fail
-$sudo $QEMU_IO --format "$IMGFMT" --nocache -c "read 0 65536" "$TEST_IMG" | _filter_qemu_io
+_sudo_qemu_io_wrapper --format "$IMGFMT" --nocache \
+ -c "read 0 65536" "$TEST_IMG" \
+ | _filter_qemu_io
# success, all done
echo "*** done"
diff --git a/qemu/tests/qemu-iotests/130 b/qemu/tests/qemu-iotests/130
index bc26247e3..ecc8a5ba1 100755
--- a/qemu/tests/qemu-iotests/130
+++ b/qemu/tests/qemu-iotests/130
@@ -27,7 +27,6 @@ seq="$(basename $0)"
echo "QA output created by $seq"
here="$PWD"
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
@@ -59,8 +58,8 @@ echo
# bdrv_make_empty() involves a header update for qcow2
# Test that a backing file isn't written
-_launch_qemu -drive file="$TEST_IMG",backing.file.filename="$TEST_IMG.base"
-_send_qemu_cmd $QEMU_HANDLE "commit ide0-hd0" "(qemu)"
+_launch_qemu -drive id=testdisk,file="$TEST_IMG",backing.file.filename="$TEST_IMG.base"
+_send_qemu_cmd $QEMU_HANDLE "commit testdisk" "(qemu)"
_send_qemu_cmd $QEMU_HANDLE '' '(qemu)'
_cleanup_qemu
_img_info | _filter_img_info
@@ -68,8 +67,8 @@ _img_info | _filter_img_info
# Make sure that if there was a backing file that was just overridden on the
# command line, that backing file is retained, with the right format
_make_test_img -F raw -b "$TEST_IMG.orig" 64M
-_launch_qemu -drive file="$TEST_IMG",backing.file.filename="$TEST_IMG.base",backing.driver=$IMGFMT
-_send_qemu_cmd $QEMU_HANDLE "commit ide0-hd0" "(qemu)"
+_launch_qemu -drive id=testdisk,file="$TEST_IMG",backing.file.filename="$TEST_IMG.base",backing.driver=$IMGFMT
+_send_qemu_cmd $QEMU_HANDLE "commit testdisk" "(qemu)"
_send_qemu_cmd $QEMU_HANDLE '' '(qemu)'
_cleanup_qemu
_img_info | _filter_img_info
diff --git a/qemu/tests/qemu-iotests/130.out b/qemu/tests/qemu-iotests/130.out
index ea68b5d28..ae95b5027 100644
--- a/qemu/tests/qemu-iotests/130.out
+++ b/qemu/tests/qemu-iotests/130.out
@@ -9,14 +9,14 @@ virtual size: 64M (67108864 bytes)
=== HMP commit ===
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) ccocomcommcommicommitcommit commit icommit idcommit idecommit ide0commit ide0-commit ide0-hcommit ide0-hdcommit ide0-hd0
+(qemu) ccocomcommcommicommitcommit commit tcommit tecommit tescommit testcommit testdcommit testdicommit testdiscommit testdisk
(qemu)
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 64M (67108864 bytes)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.orig' backing_fmt='raw'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.orig backing_fmt=raw
QEMU X.Y.Z monitor - type 'help' for more information
-(qemu) ccocomcommcommicommitcommit commit icommit idcommit idecommit ide0commit ide0-commit ide0-hcommit ide0-hdcommit ide0-hd0
+(qemu) ccocomcommcommicommitcommit commit tcommit tecommit tescommit testcommit testdcommit testdicommit testdiscommit testdisk
(qemu)
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
@@ -32,7 +32,7 @@ wrote 4096/4096 bytes at offset 0
image: TEST_DIR/t.IMGFMT
file format: IMGFMT
virtual size: 64M (67108864 bytes)
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file='TEST_DIR/t.IMGFMT.orig' backing_fmt='raw'
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.orig backing_fmt=raw
wrote 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
image: TEST_DIR/t.IMGFMT
diff --git a/qemu/tests/qemu-iotests/131 b/qemu/tests/qemu-iotests/131
index 4873f40e9..94a9ae76a 100755
--- a/qemu/tests/qemu-iotests/131
+++ b/qemu/tests/qemu-iotests/131
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/131.out b/qemu/tests/qemu-iotests/131.out
index 021a04c81..ae2412ebf 100644
--- a/qemu/tests/qemu-iotests/131.out
+++ b/qemu/tests/qemu-iotests/131.out
@@ -22,7 +22,7 @@ read 32768/32768 bytes at offset 163840
read 32768/32768 bytes at offset 0
32 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== Corrupt image ==
-qemu-io: can't open device TEST_DIR/t.parallels: parallels: Image was not closed correctly; cannot be opened read/write
+can't open device TEST_DIR/t.parallels: parallels: Image was not closed correctly; cannot be opened read/write
no file open, try 'help open'
ERROR image was not closed correctly
diff --git a/qemu/tests/qemu-iotests/133 b/qemu/tests/qemu-iotests/133
new file mode 100755
index 000000000..9d35a6a1c
--- /dev/null
+++ b/qemu/tests/qemu-iotests/133
@@ -0,0 +1,89 @@
+#!/bin/bash
+#
+# Test for reopen
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+TEST_IMG="$TEST_IMG.base" _make_test_img 64M
+_make_test_img -b "$TEST_IMG.base"
+
+echo
+echo "=== Check that node-name can't be changed ==="
+echo
+
+$QEMU_IO -c 'reopen -o node-name=foo' $TEST_IMG
+$QEMU_IO -c 'reopen -o file.node-name=foo' $TEST_IMG
+$QEMU_IO -c 'reopen -o backing.node-name=foo' $TEST_IMG
+
+echo
+echo "=== Check that unchanged node-name is okay ==="
+echo
+
+# Explicitly repeated
+$QEMU_IO -c "open -o node-name=foo $TEST_IMG" -c 'reopen -o node-name=foo'
+$QEMU_IO -c "open -o file.node-name=foo $TEST_IMG" -c 'reopen -o file.node-name=foo'
+$QEMU_IO -c "open -o backing.node-name=foo $TEST_IMG" -c 'reopen -o backing.node-name=foo'
+
+# Implicitly retained
+$QEMU_IO -c "open -o node-name=foo $TEST_IMG" -c 'reopen'
+$QEMU_IO -c "open -o file.node-name=foo $TEST_IMG" -c 'reopen'
+$QEMU_IO -c "open -o backing.node-name=foo $TEST_IMG" -c 'reopen'
+
+echo
+echo "=== Check that driver can't be changed ==="
+echo
+
+$QEMU_IO -c 'reopen -o driver=raw' $TEST_IMG
+$QEMU_IO -c 'reopen -o file.driver=qcow2' $TEST_IMG
+$QEMU_IO -c 'reopen -o backing.driver=file' $TEST_IMG
+
+echo
+echo "=== Check that unchanged driver is okay ==="
+echo
+
+# Explicitly repeated (implicit case is covered in node-name test)
+$QEMU_IO -c 'reopen -o driver=qcow2' $TEST_IMG
+$QEMU_IO -c 'reopen -o file.driver=file' $TEST_IMG
+$QEMU_IO -c 'reopen -o backing.driver=qcow2' $TEST_IMG
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/133.out b/qemu/tests/qemu-iotests/133.out
new file mode 100644
index 000000000..cc86b9488
--- /dev/null
+++ b/qemu/tests/qemu-iotests/133.out
@@ -0,0 +1,22 @@
+QA output created by 133
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=TEST_DIR/t.IMGFMT.base
+
+=== Check that node-name can't be changed ===
+
+Cannot change the option 'node-name'
+Cannot change the option 'node-name'
+Cannot change the option 'node-name'
+
+=== Check that unchanged node-name is okay ===
+
+
+=== Check that driver can't be changed ===
+
+Cannot change the option 'driver'
+Cannot change the option 'driver'
+Cannot change the option 'driver'
+
+=== Check that unchanged driver is okay ===
+
+*** done
diff --git a/qemu/tests/qemu-iotests/134 b/qemu/tests/qemu-iotests/134
index 1c3820b17..af618b881 100755
--- a/qemu/tests/qemu-iotests/134
+++ b/qemu/tests/qemu-iotests/134
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/134.out b/qemu/tests/qemu-iotests/134.out
index a16acb81c..6493704ec 100644
--- a/qemu/tests/qemu-iotests/134.out
+++ b/qemu/tests/qemu-iotests/134.out
@@ -1,43 +1,25 @@
QA output created by 134
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
== reading whole image ==
-Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
Disk image 'TEST_DIR/t.qcow2' is encrypted.
password:
read 134217728/134217728 bytes at offset 0
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== rewriting whole image ==
-Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
Disk image 'TEST_DIR/t.qcow2' is encrypted.
password:
wrote 134217728/134217728 bytes at offset 0
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== verify pattern ==
-Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
Disk image 'TEST_DIR/t.qcow2' is encrypted.
password:
read 134217728/134217728 bytes at offset 0
128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== verify pattern failure with wrong password ==
-Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
Disk image 'TEST_DIR/t.qcow2' is encrypted.
password:
Pattern verification failed at offset 0, 134217728 bytes
diff --git a/qemu/tests/qemu-iotests/135 b/qemu/tests/qemu-iotests/135
index 16bf73656..ce608312f 100755
--- a/qemu/tests/qemu-iotests/135
+++ b/qemu/tests/qemu-iotests/135
@@ -25,7 +25,6 @@ seq=`basename $0`
echo "QA output created by $seq"
here=`pwd`
-tmp=/tmp/$$
status=1 # failure is the default!
_cleanup()
diff --git a/qemu/tests/qemu-iotests/136 b/qemu/tests/qemu-iotests/136
new file mode 100644
index 000000000..e8c6937fc
--- /dev/null
+++ b/qemu/tests/qemu-iotests/136
@@ -0,0 +1,349 @@
+#!/usr/bin/env python
+#
+# Tests for block device statistics
+#
+# Copyright (C) 2015 Igalia, S.L.
+# Author: Alberto Garcia <berto@igalia.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import iotests
+import os
+
+interval_length = 10
+nsec_per_sec = 1000000000
+op_latency = nsec_per_sec / 1000 # See qtest_latency_ns in accounting.c
+bad_sector = 8192
+bad_offset = bad_sector * 512
+blkdebug_file = os.path.join(iotests.test_dir, 'blkdebug.conf')
+
+class BlockDeviceStatsTestCase(iotests.QMPTestCase):
+ test_img = "null-aio://"
+ total_rd_bytes = 0
+ total_rd_ops = 0
+ total_wr_bytes = 0
+ total_wr_ops = 0
+ total_wr_merged = 0
+ total_flush_ops = 0
+ failed_rd_ops = 0
+ failed_wr_ops = 0
+ invalid_rd_ops = 0
+ invalid_wr_ops = 0
+ wr_highest_offset = 0
+ account_invalid = False
+ account_failed = False
+
+ def blockstats(self, device):
+ result = self.vm.qmp("query-blockstats")
+ for r in result['return']:
+ if r['device'] == device:
+ return r['stats']
+ raise Exception("Device not found for blockstats: %s" % device)
+
+ def create_blkdebug_file(self):
+ file = open(blkdebug_file, 'w')
+ file.write('''
+[inject-error]
+event = "read_aio"
+errno = "5"
+sector = "%d"
+
+[inject-error]
+event = "write_aio"
+errno = "5"
+sector = "%d"
+''' % (bad_sector, bad_sector))
+ file.close()
+
+ def setUp(self):
+ drive_args = []
+ drive_args.append("stats-intervals.0=%d" % interval_length)
+ drive_args.append("stats-account-invalid=%s" %
+ (self.account_invalid and "on" or "off"))
+ drive_args.append("stats-account-failed=%s" %
+ (self.account_failed and "on" or "off"))
+ self.create_blkdebug_file()
+ self.vm = iotests.VM().add_drive('blkdebug:%s:%s ' %
+ (blkdebug_file, self.test_img),
+ ','.join(drive_args))
+ self.vm.launch()
+ # Set an initial value for the clock
+ self.vm.qtest("clock_step %d" % nsec_per_sec)
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(blkdebug_file)
+
+ def accounted_ops(self, read = False, write = False, flush = False):
+ ops = 0
+ if write:
+ ops += self.total_wr_ops
+ if self.account_failed:
+ ops += self.failed_wr_ops
+ if self.account_invalid:
+ ops += self.invalid_wr_ops
+ if read:
+ ops += self.total_rd_ops
+ if self.account_failed:
+ ops += self.failed_rd_ops
+ if self.account_invalid:
+ ops += self.invalid_rd_ops
+ if flush:
+ ops += self.total_flush_ops
+ return ops
+
+ def accounted_latency(self, read = False, write = False, flush = False):
+ latency = 0
+ if write:
+ latency += self.total_wr_ops * op_latency
+ if self.account_failed:
+ latency += self.failed_wr_ops * op_latency
+ if read:
+ latency += self.total_rd_ops * op_latency
+ if self.account_failed:
+ latency += self.failed_rd_ops * op_latency
+ if flush:
+ latency += self.total_flush_ops * op_latency
+ return latency
+
+ def check_values(self):
+ stats = self.blockstats('drive0')
+
+ # Check that the totals match with what we have calculated
+ self.assertEqual(self.total_rd_bytes, stats['rd_bytes'])
+ self.assertEqual(self.total_wr_bytes, stats['wr_bytes'])
+ self.assertEqual(self.total_rd_ops, stats['rd_operations'])
+ self.assertEqual(self.total_wr_ops, stats['wr_operations'])
+ self.assertEqual(self.total_flush_ops, stats['flush_operations'])
+ self.assertEqual(self.wr_highest_offset, stats['wr_highest_offset'])
+ self.assertEqual(self.failed_rd_ops, stats['failed_rd_operations'])
+ self.assertEqual(self.failed_wr_ops, stats['failed_wr_operations'])
+ self.assertEqual(self.invalid_rd_ops, stats['invalid_rd_operations'])
+ self.assertEqual(self.invalid_wr_ops, stats['invalid_wr_operations'])
+ self.assertEqual(self.account_invalid, stats['account_invalid'])
+ self.assertEqual(self.account_failed, stats['account_failed'])
+ self.assertEqual(self.total_wr_merged, stats['wr_merged'])
+
+ # Check that there's exactly one interval with the length we defined
+ self.assertEqual(1, len(stats['timed_stats']))
+ timed_stats = stats['timed_stats'][0]
+ self.assertEqual(interval_length, timed_stats['interval_length'])
+
+ total_rd_latency = self.accounted_latency(read = True)
+ if (total_rd_latency != 0):
+ self.assertEqual(total_rd_latency, stats['rd_total_time_ns'])
+ self.assertEqual(op_latency, timed_stats['min_rd_latency_ns'])
+ self.assertEqual(op_latency, timed_stats['max_rd_latency_ns'])
+ self.assertEqual(op_latency, timed_stats['avg_rd_latency_ns'])
+ self.assertLess(0, timed_stats['avg_rd_queue_depth'])
+ else:
+ self.assertEqual(0, stats['rd_total_time_ns'])
+ self.assertEqual(0, timed_stats['min_rd_latency_ns'])
+ self.assertEqual(0, timed_stats['max_rd_latency_ns'])
+ self.assertEqual(0, timed_stats['avg_rd_latency_ns'])
+ self.assertEqual(0, timed_stats['avg_rd_queue_depth'])
+
+ # min read latency <= avg read latency <= max read latency
+ self.assertLessEqual(timed_stats['min_rd_latency_ns'],
+ timed_stats['avg_rd_latency_ns'])
+ self.assertLessEqual(timed_stats['avg_rd_latency_ns'],
+ timed_stats['max_rd_latency_ns'])
+
+ total_wr_latency = self.accounted_latency(write = True)
+ if (total_wr_latency != 0):
+ self.assertEqual(total_wr_latency, stats['wr_total_time_ns'])
+ self.assertEqual(op_latency, timed_stats['min_wr_latency_ns'])
+ self.assertEqual(op_latency, timed_stats['max_wr_latency_ns'])
+ self.assertEqual(op_latency, timed_stats['avg_wr_latency_ns'])
+ self.assertLess(0, timed_stats['avg_wr_queue_depth'])
+ else:
+ self.assertEqual(0, stats['wr_total_time_ns'])
+ self.assertEqual(0, timed_stats['min_wr_latency_ns'])
+ self.assertEqual(0, timed_stats['max_wr_latency_ns'])
+ self.assertEqual(0, timed_stats['avg_wr_latency_ns'])
+ self.assertEqual(0, timed_stats['avg_wr_queue_depth'])
+
+ # min write latency <= avg write latency <= max write latency
+ self.assertLessEqual(timed_stats['min_wr_latency_ns'],
+ timed_stats['avg_wr_latency_ns'])
+ self.assertLessEqual(timed_stats['avg_wr_latency_ns'],
+ timed_stats['max_wr_latency_ns'])
+
+ total_flush_latency = self.accounted_latency(flush = True)
+ if (total_flush_latency != 0):
+ self.assertEqual(total_flush_latency, stats['flush_total_time_ns'])
+ self.assertEqual(op_latency, timed_stats['min_flush_latency_ns'])
+ self.assertEqual(op_latency, timed_stats['max_flush_latency_ns'])
+ self.assertEqual(op_latency, timed_stats['avg_flush_latency_ns'])
+ else:
+ self.assertEqual(0, stats['flush_total_time_ns'])
+ self.assertEqual(0, timed_stats['min_flush_latency_ns'])
+ self.assertEqual(0, timed_stats['max_flush_latency_ns'])
+ self.assertEqual(0, timed_stats['avg_flush_latency_ns'])
+
+ # min flush latency <= avg flush latency <= max flush latency
+ self.assertLessEqual(timed_stats['min_flush_latency_ns'],
+ timed_stats['avg_flush_latency_ns'])
+ self.assertLessEqual(timed_stats['avg_flush_latency_ns'],
+ timed_stats['max_flush_latency_ns'])
+
+ # idle_time_ns must be > 0 if we have performed any operation
+ if (self.accounted_ops(read = True, write = True, flush = True) != 0):
+ self.assertLess(0, stats['idle_time_ns'])
+ else:
+ self.assertFalse(stats.has_key('idle_time_ns'))
+
+ # This test does not alter these, so they must be all 0
+ self.assertEqual(0, stats['rd_merged'])
+ self.assertEqual(0, stats['failed_flush_operations'])
+ self.assertEqual(0, stats['invalid_flush_operations'])
+
+ def do_test_stats(self, rd_size = 0, rd_ops = 0, wr_size = 0, wr_ops = 0,
+ flush_ops = 0, invalid_rd_ops = 0, invalid_wr_ops = 0,
+ failed_rd_ops = 0, failed_wr_ops = 0, wr_merged = 0):
+ # The 'ops' list will contain all the requested I/O operations
+ ops = []
+ for i in range(rd_ops):
+ ops.append("aio_read %d %d" % (i * rd_size, rd_size))
+
+ for i in range(wr_ops):
+ ops.append("aio_write %d %d" % (i * wr_size, wr_size))
+
+ for i in range(flush_ops):
+ ops.append("aio_flush")
+
+ highest_offset = wr_ops * wr_size
+
+ # Two types of invalid operations: unaligned length and unaligned offset
+ for i in range(invalid_rd_ops / 2):
+ ops.append("aio_read 0 511")
+
+ for i in range(invalid_rd_ops / 2, invalid_rd_ops):
+ ops.append("aio_read 13 512")
+
+ for i in range(invalid_wr_ops / 2):
+ ops.append("aio_write 0 511")
+
+ for i in range(invalid_wr_ops / 2, invalid_wr_ops):
+ ops.append("aio_write 13 512")
+
+ for i in range(failed_rd_ops):
+ ops.append("aio_read %d 512" % bad_offset)
+
+ for i in range(failed_wr_ops):
+ ops.append("aio_write %d 512" % bad_offset)
+
+ if failed_wr_ops > 0:
+ highest_offset = max(highest_offset, bad_offset + 512)
+
+ for i in range(wr_merged):
+ first = i * wr_size * 2
+ second = first + wr_size
+ ops.append("multiwrite %d %d ; %d %d" %
+ (first, wr_size, second, wr_size))
+
+ highest_offset = max(highest_offset, wr_merged * wr_size * 2)
+
+ # Now perform all operations
+ for op in ops:
+ self.vm.hmp_qemu_io("drive0", op)
+
+ # Update the expected totals
+ self.total_rd_bytes += rd_ops * rd_size
+ self.total_rd_ops += rd_ops
+ self.total_wr_bytes += wr_ops * wr_size
+ self.total_wr_ops += wr_ops
+ self.total_wr_merged += wr_merged
+ self.total_flush_ops += flush_ops
+ self.invalid_rd_ops += invalid_rd_ops
+ self.invalid_wr_ops += invalid_wr_ops
+ self.failed_rd_ops += failed_rd_ops
+ self.failed_wr_ops += failed_wr_ops
+
+ self.wr_highest_offset = max(self.wr_highest_offset, highest_offset)
+
+ # Advance the clock so idle_time_ns has a meaningful value
+ self.vm.qtest("clock_step %d" % nsec_per_sec)
+
+ # And check that the actual statistics match the expected ones
+ self.check_values()
+
+ def test_read_only(self):
+ test_values = [[512, 1],
+ [65536, 1],
+ [512, 12],
+ [65536, 12]]
+ for i in test_values:
+ self.do_test_stats(rd_size = i[0], rd_ops = i[1])
+
+ def test_write_only(self):
+ test_values = [[512, 1],
+ [65536, 1],
+ [512, 12],
+ [65536, 12]]
+ for i in test_values:
+ self.do_test_stats(wr_size = i[0], wr_ops = i[1])
+
+ def test_invalid(self):
+ self.do_test_stats(invalid_rd_ops = 7)
+ self.do_test_stats(invalid_wr_ops = 3)
+ self.do_test_stats(invalid_rd_ops = 4, invalid_wr_ops = 5)
+
+ def test_failed(self):
+ self.do_test_stats(failed_rd_ops = 8)
+ self.do_test_stats(failed_wr_ops = 6)
+ self.do_test_stats(failed_rd_ops = 5, failed_wr_ops = 12)
+
+ def test_flush(self):
+ self.do_test_stats(flush_ops = 8)
+
+ def test_merged(self):
+ for i in range(5):
+ self.do_test_stats(wr_merged = i * 3)
+
+ def test_all(self):
+ # rd_size, rd_ops, wr_size, wr_ops, flush_ops
+ # invalid_rd_ops, invalid_wr_ops,
+ # failed_rd_ops, failed_wr_ops
+ # wr_merged
+ test_values = [[512, 1, 512, 1, 1, 4, 7, 5, 2, 1],
+ [65536, 1, 2048, 12, 7, 7, 5, 2, 5, 5],
+ [32768, 9, 8192, 1, 4, 3, 2, 4, 6, 4],
+ [16384, 11, 3584, 16, 9, 8, 6, 7, 3, 4]]
+ for i in test_values:
+ self.do_test_stats(*i)
+
+ def test_no_op(self):
+ # All values must be sane before doing any I/O
+ self.check_values()
+
+
+class BlockDeviceStatsTestAccountInvalid(BlockDeviceStatsTestCase):
+ account_invalid = True
+ account_failed = False
+
+class BlockDeviceStatsTestAccountFailed(BlockDeviceStatsTestCase):
+ account_invalid = False
+ account_failed = True
+
+class BlockDeviceStatsTestAccountBoth(BlockDeviceStatsTestCase):
+ account_invalid = True
+ account_failed = True
+
+class BlockDeviceStatsTestCoroutine(BlockDeviceStatsTestCase):
+ test_img = "null-co://"
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=["raw"])
diff --git a/qemu/tests/qemu-iotests/136.out b/qemu/tests/qemu-iotests/136.out
new file mode 100644
index 000000000..0a5e9583a
--- /dev/null
+++ b/qemu/tests/qemu-iotests/136.out
@@ -0,0 +1,5 @@
+........................................
+----------------------------------------------------------------------
+Ran 40 tests
+
+OK
diff --git a/qemu/tests/qemu-iotests/137 b/qemu/tests/qemu-iotests/137
new file mode 100755
index 000000000..e5e30de2f
--- /dev/null
+++ b/qemu/tests/qemu-iotests/137
@@ -0,0 +1,144 @@
+#!/bin/bash
+#
+# Test qcow2 reopen
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+
+_make_test_img 64M
+
+echo === Try setting valid values for all options ===
+echo
+
+# Try all options and then check that all of the basic I/O operations still
+# work on this image.
+$QEMU_IO \
+ -c "reopen -o lazy-refcounts=on,pass-discard-request=on" \
+ -c "reopen -o lazy-refcounts=off,pass-discard-request=off" \
+ -c "reopen -o pass-discard-snapshot=on,pass-discard-other=on" \
+ -c "reopen -o pass-discard-snapshot=off,pass-discard-other=off" \
+ -c "reopen -o overlap-check=all" \
+ -c "reopen -o overlap-check=none" \
+ -c "reopen -o overlap-check=cached" \
+ -c "reopen -o overlap-check=constant" \
+ -c "reopen -o overlap-check.template=all" \
+ -c "reopen -o overlap-check.template=none" \
+ -c "reopen -o overlap-check.template=cached" \
+ -c "reopen -o overlap-check.template=constant" \
+ -c "reopen -o overlap-check.main-header=on" \
+ -c "reopen -o overlap-check.main-header=off" \
+ -c "reopen -o overlap-check.active-l1=on" \
+ -c "reopen -o overlap-check.active-l1=off" \
+ -c "reopen -o overlap-check.active-l2=on" \
+ -c "reopen -o overlap-check.active-l2=off" \
+ -c "reopen -o overlap-check.refcount-table=on" \
+ -c "reopen -o overlap-check.refcount-table=off" \
+ -c "reopen -o overlap-check.refcount-block=on" \
+ -c "reopen -o overlap-check.refcount-block=off" \
+ -c "reopen -o overlap-check.snapshot-table=on" \
+ -c "reopen -o overlap-check.snapshot-table=off" \
+ -c "reopen -o overlap-check.inactive-l1=on" \
+ -c "reopen -o overlap-check.inactive-l1=off" \
+ -c "reopen -o overlap-check.inactive-l2=on" \
+ -c "reopen -o overlap-check.inactive-l2=off" \
+ -c "reopen -o cache-size=1M" \
+ -c "reopen -o l2-cache-size=512k" \
+ -c "reopen -o refcount-cache-size=128k" \
+ -c "reopen -o cache-clean-interval=5" \
+ -c "reopen -o cache-clean-interval=0" \
+ -c "reopen -o cache-clean-interval=10" \
+ \
+ -c "write -P 55 0 32M" \
+ -c "read -P 55 0 32M" \
+ -c "discard 0 32M" \
+ -c "write -z 0 32M" \
+ -c "read -P 0 0 32M" \
+ \
+ "$TEST_IMG" | _filter_qemu_io
+
+
+echo
+echo === Try setting some invalid values ===
+echo
+
+$QEMU_IO \
+ -c "reopen -o lazy-refcounts=42" \
+ -c "reopen -o cache-size=1M,l2-cache-size=64k,refcount-cache-size=64k" \
+ -c "reopen -o cache-size=1M,l2-cache-size=2M" \
+ -c "reopen -o cache-size=1M,refcount-cache-size=2M" \
+ -c "reopen -o l2-cache-size=256T" \
+ -c "reopen -o refcount-cache-size=256T" \
+ -c "reopen -o overlap-check=constant,overlap-check.template=all" \
+ -c "reopen -o overlap-check=blubb" \
+ -c "reopen -o overlap-check.template=blubb" \
+ -c "reopen -o cache-clean-interval=-1" \
+ "$TEST_IMG" | _filter_qemu_io
+
+echo
+echo === Test transaction semantics ===
+echo
+
+# Whether lazy-refcounts was actually enabled can easily be tested: Check if
+# the dirty bit is set after a crash
+$QEMU_IO \
+ -c "reopen -o lazy-refcounts=on,overlap-check=blubb" \
+ -c "write -P 0x5a 0 512" \
+ -c "sigraise $(kill -l KILL)" \
+ "$TEST_IMG" 2>&1 | _filter_qemu_io
+
+# The dirty bit must not be set
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+
+# Similarly we can test whether corruption detection has been enabled:
+# Create L1/L2, overwrite first entry in refcount block, allocate something.
+# Disabling the checks should fail, so the corruption must be detected.
+_make_test_img 64M
+$QEMU_IO -c "write 0 64k" "$TEST_IMG" | _filter_qemu_io
+poke_file "$TEST_IMG" "$((0x20000))" "\x00\x00"
+$QEMU_IO \
+ -c "reopen -o overlap-check=none,lazy-refcounts=42" \
+ -c "write 64k 64k" \
+ "$TEST_IMG" 2>&1 | _filter_qemu_io
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/137.out b/qemu/tests/qemu-iotests/137.out
new file mode 100644
index 000000000..88c702cf7
--- /dev/null
+++ b/qemu/tests/qemu-iotests/137.out
@@ -0,0 +1,46 @@
+QA output created by 137
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+=== Try setting valid values for all options ===
+
+wrote 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+discard 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 33554432/33554432 bytes at offset 0
+32 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Try setting some invalid values ===
+
+Parameter 'lazy-refcounts' expects 'on' or 'off'
+cache-size, l2-cache-size and refcount-cache-size may not be set the same time
+l2-cache-size may not exceed cache-size
+refcount-cache-size may not exceed cache-size
+L2 cache size too big
+L2 cache size too big
+Conflicting values for qcow2 options 'overlap-check' ('constant') and 'overlap-check.template' ('all')
+Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
+Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
+Cache clean interval too big
+
+=== Test transaction semantics ===
+
+Unsupported value 'blubb' for qcow2 option 'overlap-check'. Allowed are any of the following: none, constant, cached, all
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+./common.config: Killed ( if [ "${VALGRIND_QEMU}" == "y" ]; then
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+else
+ exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@";
+fi )
+incompatible_features 0x0
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Parameter 'lazy-refcounts' expects 'on' or 'off'
+qcow2: Marking image as corrupt: Preventing invalid write on metadata (overlaps with qcow2_header); further corruption events will be suppressed
+write failed: Input/output error
+*** done
diff --git a/qemu/tests/qemu-iotests/138 b/qemu/tests/qemu-iotests/138
new file mode 100755
index 000000000..21650d819
--- /dev/null
+++ b/qemu/tests/qemu-iotests/138
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# General test case for qcow2's image check
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+# This tests qocw2-specific low-level functionality
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+echo
+echo '=== Check on an image with a multiple of 2^32 clusters ==='
+echo
+
+IMGOPTS=$(_optstr_add "$IMGOPTS" "cluster_size=512") \
+ _make_test_img 512
+
+# Allocate L2 table
+$QEMU_IO -c 'write 0 512' "$TEST_IMG" | _filter_qemu_io
+
+# Put the data cluster at a multiple of 2 TB, resulting in the image apparently
+# having a multiple of 2^32 clusters
+# (To be more specific: It is at 32 PB)
+poke_file "$TEST_IMG" 2048 "\x80\x80\x00\x00\x00\x00\x00\x00"
+
+# An offset of 32 PB results in qemu-img check having to allocate an in-memory
+# refcount table of 128 TB (16 bit refcounts, 512 byte clusters).
+# This should be generally too much for any system and thus fail.
+# What this test is checking is that the qcow2 driver actually tries to allocate
+# such a large amount of memory (and is consequently aborting) instead of having
+# truncated the cluster count somewhere (which would result in much less memory
+# being allocated and then a segfault occurring).
+_check_test_img
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/138.out b/qemu/tests/qemu-iotests/138.out
new file mode 100644
index 000000000..3fe911f85
--- /dev/null
+++ b/qemu/tests/qemu-iotests/138.out
@@ -0,0 +1,9 @@
+QA output created by 138
+
+=== Check on an image with a multiple of 2^32 clusters ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=512
+wrote 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+qemu-img: Check failed: Cannot allocate memory
+*** done
diff --git a/qemu/tests/qemu-iotests/139 b/qemu/tests/qemu-iotests/139
new file mode 100644
index 000000000..a4b969499
--- /dev/null
+++ b/qemu/tests/qemu-iotests/139
@@ -0,0 +1,416 @@
+#!/usr/bin/env python
+#
+# Test cases for the QMP 'x-blockdev-del' command
+#
+# Copyright (C) 2015 Igalia, S.L.
+# Author: Alberto Garcia <berto@igalia.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import iotests
+import time
+
+base_img = os.path.join(iotests.test_dir, 'base.img')
+new_img = os.path.join(iotests.test_dir, 'new.img')
+
+class TestBlockdevDel(iotests.QMPTestCase):
+
+ def setUp(self):
+ iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M')
+ self.vm = iotests.VM()
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(base_img)
+ if os.path.isfile(new_img):
+ os.remove(new_img)
+
+ # Check whether a BlockBackend exists
+ def checkBlockBackend(self, backend, node, must_exist = True):
+ result = self.vm.qmp('query-block')
+ backends = filter(lambda x: x['device'] == backend, result['return'])
+ self.assertLessEqual(len(backends), 1)
+ self.assertEqual(must_exist, len(backends) == 1)
+ if must_exist:
+ if node:
+ self.assertEqual(backends[0]['inserted']['node-name'], node)
+ else:
+ self.assertFalse(backends[0].has_key('inserted'))
+
+ # Check whether a BlockDriverState exists
+ def checkBlockDriverState(self, node, must_exist = True):
+ result = self.vm.qmp('query-named-block-nodes')
+ nodes = filter(lambda x: x['node-name'] == node, result['return'])
+ self.assertLessEqual(len(nodes), 1)
+ self.assertEqual(must_exist, len(nodes) == 1)
+
+ # Add a new BlockBackend (with its attached BlockDriverState)
+ def addBlockBackend(self, backend, node):
+ file_node = '%s_file' % node
+ self.checkBlockBackend(backend, node, False)
+ self.checkBlockDriverState(node, False)
+ self.checkBlockDriverState(file_node, False)
+ opts = {'driver': iotests.imgfmt,
+ 'id': backend,
+ 'node-name': node,
+ 'file': {'driver': 'file',
+ 'node-name': file_node,
+ 'filename': base_img}}
+ result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockBackend(backend, node)
+ self.checkBlockDriverState(node)
+ self.checkBlockDriverState(file_node)
+
+ # Add a BlockDriverState without a BlockBackend
+ def addBlockDriverState(self, node):
+ file_node = '%s_file' % node
+ self.checkBlockDriverState(node, False)
+ self.checkBlockDriverState(file_node, False)
+ opts = {'driver': iotests.imgfmt,
+ 'node-name': node,
+ 'file': {'driver': 'file',
+ 'node-name': file_node,
+ 'filename': base_img}}
+ result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockDriverState(node)
+ self.checkBlockDriverState(file_node)
+
+ # Add a BlockDriverState that will be used as overlay for the base_img BDS
+ def addBlockDriverStateOverlay(self, node):
+ self.checkBlockDriverState(node, False)
+ iotests.qemu_img('create', '-f', iotests.imgfmt,
+ '-b', base_img, new_img, '1M')
+ opts = {'driver': iotests.imgfmt,
+ 'node-name': node,
+ 'backing': '',
+ 'file': {'driver': 'file',
+ 'filename': new_img}}
+ result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockDriverState(node)
+
+ # Delete a BlockBackend
+ def delBlockBackend(self, backend, node, expect_error = False,
+ destroys_media = True):
+ self.checkBlockBackend(backend, node)
+ if node:
+ self.checkBlockDriverState(node)
+ result = self.vm.qmp('x-blockdev-del', id = backend)
+ if expect_error:
+ self.assert_qmp(result, 'error/class', 'GenericError')
+ if node:
+ self.checkBlockDriverState(node)
+ else:
+ self.assert_qmp(result, 'return', {})
+ if node:
+ self.checkBlockDriverState(node, not destroys_media)
+ self.checkBlockBackend(backend, node, must_exist = expect_error)
+
+ # Delete a BlockDriverState
+ def delBlockDriverState(self, node, expect_error = False):
+ self.checkBlockDriverState(node)
+ result = self.vm.qmp('x-blockdev-del', node_name = node)
+ if expect_error:
+ self.assert_qmp(result, 'error/class', 'GenericError')
+ else:
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockDriverState(node, expect_error)
+
+ # Add a device model
+ def addDeviceModel(self, device, backend):
+ result = self.vm.qmp('device_add', id = device,
+ driver = 'virtio-blk-pci', drive = backend)
+ self.assert_qmp(result, 'return', {})
+
+ # Delete a device model
+ def delDeviceModel(self, device):
+ result = self.vm.qmp('device_del', id = device)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('system_reset')
+ self.assert_qmp(result, 'return', {})
+
+ device_path = '/machine/peripheral/%s/virtio-backend' % device
+ event = self.vm.event_wait(name="DEVICE_DELETED",
+ match={'data': {'path': device_path}})
+ self.assertNotEqual(event, None)
+
+ event = self.vm.event_wait(name="DEVICE_DELETED",
+ match={'data': {'device': device}})
+ self.assertNotEqual(event, None)
+
+ # Remove a BlockDriverState
+ def ejectDrive(self, backend, node, expect_error = False,
+ destroys_media = True):
+ self.checkBlockBackend(backend, node)
+ self.checkBlockDriverState(node)
+ result = self.vm.qmp('eject', device = backend)
+ if expect_error:
+ self.assert_qmp(result, 'error/class', 'GenericError')
+ self.checkBlockDriverState(node)
+ self.checkBlockBackend(backend, node)
+ else:
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockDriverState(node, not destroys_media)
+ self.checkBlockBackend(backend, None)
+
+ # Insert a BlockDriverState
+ def insertDrive(self, backend, node):
+ self.checkBlockBackend(backend, None)
+ self.checkBlockDriverState(node)
+ result = self.vm.qmp('x-blockdev-insert-medium',
+ device = backend, node_name = node)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockBackend(backend, node)
+ self.checkBlockDriverState(node)
+
+ # Create a snapshot using 'blockdev-snapshot-sync'
+ def createSnapshotSync(self, node, overlay):
+ self.checkBlockDriverState(node)
+ self.checkBlockDriverState(overlay, False)
+ opts = {'node-name': node,
+ 'snapshot-file': new_img,
+ 'snapshot-node-name': overlay,
+ 'format': iotests.imgfmt}
+ result = self.vm.qmp('blockdev-snapshot-sync', conv_keys=False, **opts)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockDriverState(node)
+ self.checkBlockDriverState(overlay)
+
+ # Create a snapshot using 'blockdev-snapshot'
+ def createSnapshot(self, node, overlay):
+ self.checkBlockDriverState(node)
+ self.checkBlockDriverState(overlay)
+ result = self.vm.qmp('blockdev-snapshot',
+ node = node, overlay = overlay)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockDriverState(node)
+ self.checkBlockDriverState(overlay)
+
+ # Create a mirror
+ def createMirror(self, backend, node, new_node):
+ self.checkBlockBackend(backend, node)
+ self.checkBlockDriverState(new_node, False)
+ opts = {'device': backend,
+ 'target': new_img,
+ 'node-name': new_node,
+ 'sync': 'top',
+ 'format': iotests.imgfmt}
+ result = self.vm.qmp('drive-mirror', conv_keys=False, **opts)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockBackend(backend, node)
+ self.checkBlockDriverState(new_node)
+
+ # Complete an existing block job
+ def completeBlockJob(self, backend, node_before, node_after):
+ self.checkBlockBackend(backend, node_before)
+ result = self.vm.qmp('block-job-complete', device=backend)
+ self.assert_qmp(result, 'return', {})
+ self.wait_until_completed(backend)
+ self.checkBlockBackend(backend, node_after)
+
+ # Add a BlkDebug node
+ # Note that the purpose of this is to test the x-blockdev-del
+ # sanity checks, not to create a usable blkdebug drive
+ def addBlkDebug(self, debug, node):
+ self.checkBlockDriverState(node, False)
+ self.checkBlockDriverState(debug, False)
+ image = {'driver': iotests.imgfmt,
+ 'node-name': node,
+ 'file': {'driver': 'file',
+ 'filename': base_img}}
+ opts = {'driver': 'blkdebug',
+ 'node-name': debug,
+ 'image': image}
+ result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockDriverState(node)
+ self.checkBlockDriverState(debug)
+
+ # Add a BlkVerify node
+ # Note that the purpose of this is to test the x-blockdev-del
+ # sanity checks, not to create a usable blkverify drive
+ def addBlkVerify(self, blkverify, test, raw):
+ self.checkBlockDriverState(test, False)
+ self.checkBlockDriverState(raw, False)
+ self.checkBlockDriverState(blkverify, False)
+ iotests.qemu_img('create', '-f', iotests.imgfmt, new_img, '1M')
+ node_0 = {'driver': iotests.imgfmt,
+ 'node-name': test,
+ 'file': {'driver': 'file',
+ 'filename': base_img}}
+ node_1 = {'driver': iotests.imgfmt,
+ 'node-name': raw,
+ 'file': {'driver': 'file',
+ 'filename': new_img}}
+ opts = {'driver': 'blkverify',
+ 'node-name': blkverify,
+ 'test': node_0,
+ 'raw': node_1}
+ result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockDriverState(test)
+ self.checkBlockDriverState(raw)
+ self.checkBlockDriverState(blkverify)
+
+ # Add a Quorum node
+ def addQuorum(self, quorum, child0, child1):
+ self.checkBlockDriverState(child0, False)
+ self.checkBlockDriverState(child1, False)
+ self.checkBlockDriverState(quorum, False)
+ iotests.qemu_img('create', '-f', iotests.imgfmt, new_img, '1M')
+ child_0 = {'driver': iotests.imgfmt,
+ 'node-name': child0,
+ 'file': {'driver': 'file',
+ 'filename': base_img}}
+ child_1 = {'driver': iotests.imgfmt,
+ 'node-name': child1,
+ 'file': {'driver': 'file',
+ 'filename': new_img}}
+ opts = {'driver': 'quorum',
+ 'node-name': quorum,
+ 'vote-threshold': 1,
+ 'children': [ child_0, child_1 ]}
+ result = self.vm.qmp('blockdev-add', conv_keys = False, options = opts)
+ self.assert_qmp(result, 'return', {})
+ self.checkBlockDriverState(child0)
+ self.checkBlockDriverState(child1)
+ self.checkBlockDriverState(quorum)
+
+ ########################
+ # The tests start here #
+ ########################
+
+ def testWrongParameters(self):
+ self.addBlockBackend('drive0', 'node0')
+ result = self.vm.qmp('x-blockdev-del')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+ result = self.vm.qmp('x-blockdev-del', id='drive0', node_name='node0')
+ self.assert_qmp(result, 'error/class', 'GenericError')
+ self.delBlockBackend('drive0', 'node0')
+
+ def testBlockBackend(self):
+ self.addBlockBackend('drive0', 'node0')
+ # You cannot delete a BDS that is attached to a backend
+ self.delBlockDriverState('node0', expect_error = True)
+ self.delBlockBackend('drive0', 'node0')
+
+ def testBlockDriverState(self):
+ self.addBlockDriverState('node0')
+ # You cannot delete a file BDS directly
+ self.delBlockDriverState('node0_file', expect_error = True)
+ self.delBlockDriverState('node0')
+
+ def testEject(self):
+ self.addBlockBackend('drive0', 'node0')
+ self.ejectDrive('drive0', 'node0')
+ self.delBlockBackend('drive0', None)
+
+ def testDeviceModel(self):
+ self.addBlockBackend('drive0', 'node0')
+ self.addDeviceModel('device0', 'drive0')
+ self.ejectDrive('drive0', 'node0', expect_error = True)
+ self.delBlockBackend('drive0', 'node0', expect_error = True)
+ self.delDeviceModel('device0')
+ self.delBlockBackend('drive0', 'node0')
+
+ def testAttachMedia(self):
+ # This creates a BlockBackend and removes its media
+ self.addBlockBackend('drive0', 'node0')
+ self.ejectDrive('drive0', 'node0')
+ # This creates a new BlockDriverState and inserts it into the backend
+ self.addBlockDriverState('node1')
+ self.insertDrive('drive0', 'node1')
+ # The backend can't be removed: the new BDS has an extra reference
+ self.delBlockBackend('drive0', 'node1', expect_error = True)
+ self.delBlockDriverState('node1', expect_error = True)
+ # The BDS still exists after being ejected, but now it can be removed
+ self.ejectDrive('drive0', 'node1', destroys_media = False)
+ self.delBlockDriverState('node1')
+ self.delBlockBackend('drive0', None)
+
+ def testSnapshotSync(self):
+ self.addBlockBackend('drive0', 'node0')
+ self.createSnapshotSync('node0', 'overlay0')
+ # This fails because node0 is now being used as a backing image
+ self.delBlockDriverState('node0', expect_error = True)
+ # This succeeds because overlay0 only has the backend reference
+ self.delBlockBackend('drive0', 'overlay0')
+ self.checkBlockDriverState('node0', False)
+
+ def testSnapshot(self):
+ self.addBlockBackend('drive0', 'node0')
+ self.addBlockDriverStateOverlay('overlay0')
+ self.createSnapshot('node0', 'overlay0')
+ self.delBlockBackend('drive0', 'overlay0', expect_error = True)
+ self.delBlockDriverState('node0', expect_error = True)
+ self.delBlockDriverState('overlay0', expect_error = True)
+ self.ejectDrive('drive0', 'overlay0', destroys_media = False)
+ self.delBlockBackend('drive0', None)
+ self.delBlockDriverState('node0', expect_error = True)
+ self.delBlockDriverState('overlay0')
+ self.checkBlockDriverState('node0', False)
+
+ def testMirror(self):
+ self.addBlockBackend('drive0', 'node0')
+ self.createMirror('drive0', 'node0', 'mirror0')
+ # The block job prevents removing the device
+ self.delBlockBackend('drive0', 'node0', expect_error = True)
+ self.delBlockDriverState('node0', expect_error = True)
+ self.delBlockDriverState('mirror0', expect_error = True)
+ self.wait_ready('drive0')
+ self.completeBlockJob('drive0', 'node0', 'mirror0')
+ self.assert_no_active_block_jobs()
+ self.checkBlockDriverState('node0', False)
+ # This succeeds because the backend now points to mirror0
+ self.delBlockBackend('drive0', 'mirror0')
+
+ def testBlkDebug(self):
+ self.addBlkDebug('debug0', 'node0')
+ # 'node0' is used by the blkdebug node
+ self.delBlockDriverState('node0', expect_error = True)
+ # But we can remove the blkdebug node directly
+ self.delBlockDriverState('debug0')
+ self.checkBlockDriverState('node0', False)
+
+ def testBlkVerify(self):
+ self.addBlkVerify('verify0', 'node0', 'node1')
+ # We cannot remove the children of a blkverify device
+ self.delBlockDriverState('node0', expect_error = True)
+ self.delBlockDriverState('node1', expect_error = True)
+ # But we can remove the blkverify node directly
+ self.delBlockDriverState('verify0')
+ self.checkBlockDriverState('node0', False)
+ self.checkBlockDriverState('node1', False)
+
+ def testQuorum(self):
+ if not 'quorum' in iotests.qemu_img_pipe('--help'):
+ return
+ self.addQuorum('quorum0', 'node0', 'node1')
+ # We cannot remove the children of a Quorum device
+ self.delBlockDriverState('node0', expect_error = True)
+ self.delBlockDriverState('node1', expect_error = True)
+ # But we can remove the Quorum node directly
+ self.delBlockDriverState('quorum0')
+ self.checkBlockDriverState('node0', False)
+ self.checkBlockDriverState('node1', False)
+
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=["qcow2"])
diff --git a/qemu/tests/qemu-iotests/139.out b/qemu/tests/qemu-iotests/139.out
new file mode 100644
index 000000000..281b69efe
--- /dev/null
+++ b/qemu/tests/qemu-iotests/139.out
@@ -0,0 +1,5 @@
+............
+----------------------------------------------------------------------
+Ran 12 tests
+
+OK
diff --git a/qemu/tests/qemu-iotests/140 b/qemu/tests/qemu-iotests/140
new file mode 100755
index 000000000..49f9df4eb
--- /dev/null
+++ b/qemu/tests/qemu-iotests/140
@@ -0,0 +1,95 @@
+#!/bin/bash
+#
+# Test case for ejecting a BlockBackend with an NBD server attached to it
+#
+# Verify that the NBD server stops offering the drive when ejecting a
+# BlockDriverState tree from a BlockBackend (that is, a medium from a
+# drive) exposed via an NBD server.
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+ rm -f "$TEST_DIR/nbd"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt generic
+_supported_proto file
+_supported_os Linux
+
+_make_test_img 64k
+
+$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG" | _filter_qemu_io
+
+keep_stderr=y \
+_launch_qemu -drive if=none,media=cdrom,id=drv,file="$TEST_IMG",format=$IMGFMT \
+ 2> >(_filter_nbd)
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'nbd-server-start',
+ 'arguments': { 'addr': { 'type': 'unix',
+ 'data': { 'path': '$TEST_DIR/nbd' }}}}" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'nbd-server-add',
+ 'arguments': { 'device': 'drv' }}" \
+ 'return'
+
+$QEMU_IO_PROG -f raw -c 'read -P 42 0 64k' \
+ "nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
+ | _filter_qemu_io | _filter_nbd
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'eject',
+ 'arguments': { 'device': 'drv' }}" \
+ 'return'
+
+$QEMU_IO_PROG -f raw -c close \
+ "nbd+unix:///drv?socket=$TEST_DIR/nbd" 2>&1 \
+ | _filter_qemu_io | _filter_nbd
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'quit' }" \
+ 'return'
+
+wait=1 _cleanup_qemu
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/140.out b/qemu/tests/qemu-iotests/140.out
new file mode 100644
index 000000000..0409cd017
--- /dev/null
+++ b/qemu/tests/qemu-iotests/140.out
@@ -0,0 +1,15 @@
+QA output created by 140
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65536
+wrote 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
+{"return": {}}
+{"return": {}}
+read 65536/65536 bytes at offset 0
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
+can't open device nbd+unix:///drv?socket=TEST_DIR/nbd: No export with name 'drv' available
+no file open, try 'help open'
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+*** done
diff --git a/qemu/tests/qemu-iotests/141 b/qemu/tests/qemu-iotests/141
new file mode 100755
index 000000000..b2617e5e2
--- /dev/null
+++ b/qemu/tests/qemu-iotests/141
@@ -0,0 +1,185 @@
+#!/bin/bash
+#
+# Test case for ejecting BDSs with block jobs still running on them
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+ rm -f "$TEST_DIR/{b,m,o}.$IMGFMT"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+# Needs backing file and backing format support
+_supported_fmt qcow2 qed
+_supported_proto file
+_supported_os Linux
+
+
+test_blockjob()
+{
+ _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'blockdev-add',
+ 'arguments': {
+ 'options': {
+ 'id': 'drv0',
+ 'driver': '$IMGFMT',
+ 'file': {
+ 'driver': 'file',
+ 'filename': '$TEST_IMG'
+ }}}}" \
+ 'return'
+
+ _send_qemu_cmd $QEMU_HANDLE \
+ "$1" \
+ "$2" \
+ | _filter_img_create
+
+ # We want this to return an error because the block job is still running
+ _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'x-blockdev-remove-medium',
+ 'arguments': {'device': 'drv0'}}" \
+ 'error'
+
+ _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'block-job-cancel',
+ 'arguments': {'device': 'drv0'}}" \
+ "$3"
+
+ _send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'x-blockdev-del',
+ 'arguments': {'id': 'drv0'}}" \
+ 'return'
+}
+
+
+TEST_IMG="$TEST_DIR/b.$IMGFMT" _make_test_img 1M
+TEST_IMG="$TEST_DIR/m.$IMGFMT" _make_test_img -b "$TEST_DIR/b.$IMGFMT" 1M
+_make_test_img -b "$TEST_DIR/m.$IMGFMT" 1M
+
+_launch_qemu -nodefaults
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{'execute': 'qmp_capabilities'}" \
+ 'return'
+
+echo
+echo '=== Testing drive-backup ==='
+echo
+
+# drive-backup will not send BLOCK_JOB_READY by itself, and cancelling the job
+# will consequently result in BLOCK_JOB_CANCELLED being emitted.
+
+test_blockjob \
+ "{'execute': 'drive-backup',
+ 'arguments': {'device': 'drv0',
+ 'target': '$TEST_DIR/o.$IMGFMT',
+ 'format': '$IMGFMT',
+ 'sync': 'none'}}" \
+ 'return' \
+ 'BLOCK_JOB_CANCELLED'
+
+echo
+echo '=== Testing drive-mirror ==='
+echo
+
+# drive-mirror will send BLOCK_JOB_READY basically immediately, and cancelling
+# the job will consequently result in BLOCK_JOB_COMPLETED being emitted.
+
+test_blockjob \
+ "{'execute': 'drive-mirror',
+ 'arguments': {'device': 'drv0',
+ 'target': '$TEST_DIR/o.$IMGFMT',
+ 'format': '$IMGFMT',
+ 'sync': 'none'}}" \
+ 'BLOCK_JOB_READY' \
+ 'BLOCK_JOB_COMPLETED'
+
+echo
+echo '=== Testing active block-commit ==='
+echo
+
+# An active block-commit will send BLOCK_JOB_READY basically immediately, and
+# cancelling the job will consequently result in BLOCK_JOB_COMPLETED being
+# emitted.
+
+test_blockjob \
+ "{'execute': 'block-commit',
+ 'arguments': {'device': 'drv0'}}" \
+ 'BLOCK_JOB_READY' \
+ 'BLOCK_JOB_COMPLETED'
+
+echo
+echo '=== Testing non-active block-commit ==='
+echo
+
+# Give block-commit something to work on, otherwise it would be done
+# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
+# fine without the block job still running.
+
+$QEMU_IO -c 'write 0 1M' "$TEST_DIR/m.$IMGFMT" | _filter_qemu_io
+
+test_blockjob \
+ "{'execute': 'block-commit',
+ 'arguments': {'device': 'drv0',
+ 'top': '$TEST_DIR/m.$IMGFMT',
+ 'speed': 1}}" \
+ 'return' \
+ 'BLOCK_JOB_CANCELLED'
+
+echo
+echo '=== Testing block-stream ==='
+echo
+
+# Give block-stream something to work on, otherwise it would be done
+# immediately, send a BLOCK_JOB_COMPLETED and ejecting the BDS would work just
+# fine without the block job still running.
+
+$QEMU_IO -c 'write 0 1M' "$TEST_DIR/b.$IMGFMT" | _filter_qemu_io
+
+# With some data to stream (and @speed set to 1), block-stream will not complete
+# until we send the block-job-cancel command. Therefore, no event other than
+# BLOCK_JOB_CANCELLED will be emitted.
+
+test_blockjob \
+ "{'execute': 'block-stream',
+ 'arguments': {'device': 'drv0',
+ 'speed': 1}}" \
+ 'return' \
+ 'BLOCK_JOB_CANCELLED'
+
+_cleanup_qemu
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/141.out b/qemu/tests/qemu-iotests/141.out
new file mode 100644
index 000000000..adceac181
--- /dev/null
+++ b/qemu/tests/qemu-iotests/141.out
@@ -0,0 +1,59 @@
+QA output created by 141
+Formatting 'TEST_DIR/b.IMGFMT', fmt=IMGFMT size=1048576
+Formatting 'TEST_DIR/m.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/b.IMGFMT
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/m.IMGFMT
+{"return": {}}
+
+=== Testing drive-backup ===
+
+{"return": {}}
+Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: backup"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "drv0", "len": 1048576, "offset": 0, "speed": 0, "type": "backup"}}
+{"return": {}}
+
+=== Testing drive-mirror ===
+
+{"return": {}}
+Formatting 'TEST_DIR/o.IMGFMT', fmt=IMGFMT size=1048576 backing_file=TEST_DIR/t.IMGFMT backing_fmt=IMGFMT
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: mirror"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "mirror"}}
+{"return": {}}
+
+=== Testing active block-commit ===
+
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "drv0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"return": {}}
+
+=== Testing non-active block-commit ===
+
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: commit"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "drv0", "len": 1048576, "offset": 524288, "speed": 1, "type": "commit"}}
+{"return": {}}
+
+=== Testing block-stream ===
+
+wrote 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+{"return": {}}
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "Node 'drv0' is busy: block device is in use by block job: stream"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_CANCELLED", "data": {"device": "drv0", "len": 1048576, "offset": 524288, "speed": 1, "type": "stream"}}
+{"return": {}}
+*** done
diff --git a/qemu/tests/qemu-iotests/142 b/qemu/tests/qemu-iotests/142
new file mode 100755
index 000000000..29c0606bd
--- /dev/null
+++ b/qemu/tests/qemu-iotests/142
@@ -0,0 +1,358 @@
+#!/bin/bash
+#
+# Test for configuring cache modes of arbitrary nodes (requires O_DIRECT)
+#
+# Copyright (C) 2015 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+ rm -f $TEST_IMG.snap
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+# We test all cache modes anyway, but O_DIRECT needs to be supported
+_default_cache_mode none
+_supported_cache_modes none directsync
+
+function do_run_qemu()
+{
+ echo Testing: "$@"
+ (
+ if ! test -t 0; then
+ while read cmd; do
+ echo $cmd
+ done
+ fi
+ echo quit
+ ) | $QEMU -nographic -monitor stdio -nodefaults "$@"
+ echo
+}
+
+function run_qemu()
+{
+ do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qemu
+}
+
+size=128M
+
+TEST_IMG="$TEST_IMG.base" _make_test_img $size
+TEST_IMG="$TEST_IMG.snap" _make_test_img $size
+_make_test_img -b "$TEST_IMG.base" $size
+
+echo
+echo === Simple test for all cache modes ===
+echo
+
+run_qemu -drive file="$TEST_IMG",cache=none
+run_qemu -drive file="$TEST_IMG",cache=directsync
+run_qemu -drive file="$TEST_IMG",cache=writeback
+run_qemu -drive file="$TEST_IMG",cache=writethrough
+run_qemu -drive file="$TEST_IMG",cache=unsafe
+run_qemu -drive file="$TEST_IMG",cache=invalid_value
+
+echo
+echo === Check inheritance of cache modes ===
+echo
+
+files="if=none,file=$TEST_IMG,backing.file.filename=$TEST_IMG.base"
+ids="node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file"
+
+function check_cache_all()
+{
+ # cache.direct is supposed to be inherited by both bs->file and
+ # bs->backing
+
+ echo -e "cache.direct=on on none0"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't"
+ echo -e "\ncache.direct=on on file"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't"
+ echo -e "\ncache.direct=on on backing"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't"
+ echo -e "\ncache.direct=on on backing-file"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.direct=on | grep -e "Cache" -e "[Cc]annot|[Cc]ould not|[Cc]an't"
+
+ # cache.writeback is supposed to be inherited by bs->backing; bs->file
+ # always gets cache.writeback=on
+
+ echo -e "\n\ncache.writeback=off on none0"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.writeback=off | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.writeback=off on file"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.writeback=off | grep -e "doesn't" -e "does not"
+ echo -e "\ncache.writeback=off on backing"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.writeback=off | grep -e "doesn't" -e "does not"
+ echo -e "\ncache.writeback=off on backing-file"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.writeback=off | grep -e "doesn't" -e "does not"
+
+ # cache.no-flush is supposed to be inherited by both bs->file and bs->backing
+
+ echo -e "\n\ncache.no-flush=on on none0"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.no-flush=on on file"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",file.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.no-flush=on on backing"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.no-flush=on on backing-file"
+ echo "$hmp_cmds" | run_qemu -drive "$files","$ids",backing.file.cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+}
+
+echo
+echo "--- Configure cache modes on the command line ---"
+echo
+
+# First check the inherited cache mode after opening the image.
+
+hmp_cmds="info block none0
+info block image
+info block file
+info block backing
+info block backing-file"
+
+check_cache_all
+
+echo
+echo "--- Cache modes after reopen (live snapshot) ---"
+echo
+
+# Then trigger a reopen and check that the cache modes are still the same.
+
+hmp_cmds="snapshot_blkdev -n none0 $TEST_IMG.snap $IMGFMT
+info block
+info block image
+info block file
+info block backing
+info block backing-file"
+
+check_cache_all
+
+echo
+echo "--- Change cache modes with reopen (qemu-io command, flags) ---"
+echo
+
+# This one actually changes the cache mode with the reopen. For this test, the
+# new cache mode is specified in the flags, not as an option.
+
+hmp_cmds='qemu-io none0 "reopen -c none"
+info block none0
+info block image
+info block file
+info block backing
+info block backing-file'
+
+check_cache_all
+
+echo
+echo "--- Change cache modes with reopen (qemu-io command, options) ---"
+echo
+
+# This one actually changes the cache mode with the reopen. For this test, the
+# new cache mode is specified as an option, not in the flags.
+
+hmp_cmds='qemu-io none0 "reopen -o cache.direct=on"
+info block none0
+info block image
+info block file
+info block backing
+info block backing-file'
+
+check_cache_all
+
+echo
+echo "--- Change cache modes after snapshot ---"
+echo
+
+# This checks that the original image doesn't inherit from the snapshot
+
+hmp_cmds="snapshot_blkdev -n none0 $TEST_IMG.snap $IMGFMT
+qemu-io none0 \"reopen -c none\"
+info block none0
+info block image
+info block file
+info block backing
+info block backing-file"
+
+check_cache_all
+
+echo
+echo "--- Change cache mode in parent, child has explicit option in JSON ---"
+echo
+
+# This checks that children with options explicitly set by the json:
+# pseudo-protocol don't inherit these options from their parents.
+#
+# Yes, blkdebug::json:... is criminal, but I can't see another way to have a
+# BDS initialised with the json: pseudo-protocol, but still have it inherit
+# options from its parent node.
+
+hmp_cmds="qemu-io none0 \"reopen -o cache.direct=on,cache.no-flush=on\"
+info block none0
+info block image
+info block blkdebug
+info block file"
+
+echo "$hmp_cmds" | run_qemu -drive if=none,file="blkdebug::json:{\"filename\":\"$TEST_IMG\",,\"cache\":{\"direct\":false}}",node-name=image,file.node-name=blkdebug,file.image.node-name=file | grep "Cache"
+
+echo
+echo "=== Check that referenced BDSes don't inherit ==="
+echo
+
+drv_bkfile="if=none,driver=file,filename=$TEST_IMG.base,node-name=backing-file"
+drv_bk="if=none,file=json:{'driver':'$IMGFMT',,'file':'backing-file',,'node-name':'backing'}"
+drv_file="if=none,driver=file,filename=$TEST_IMG,node-name=file"
+drv_img="if=none,id=blk,file=json:{'driver':'$IMGFMT',,'file':'file',,'backing':'backing',,'node-name':'image'}"
+
+function check_cache_all_separate()
+{
+ # Check cache.direct
+
+ echo -e "cache.direct=on on blk"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.direct=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.direct=on on file"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.direct=on -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.direct=on on backing"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.direct=on -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.direct=on on backing-file"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.direct=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+
+ # Check cache.writeback
+
+ echo -e "\n\ncache.writeback=off on blk"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.writeback=off | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.writeback=off on file"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.writeback=off -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.writeback=off on backing"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.writeback=off -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.writeback=off on backing-file"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.writeback=off -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+
+ # Check cache.no-flush
+
+ echo -e "\n\ncache.no-flush=on on blk"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img",cache.no-flush=on | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.no-flush=on on file"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk" -drive "$drv_file",cache.no-flush=on -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.no-flush=on on backing"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile" -drive "$drv_bk",cache.no-flush=on -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+ echo -e "\ncache.no-flush=on on backing-file"
+ echo "$hmp_cmds" | run_qemu -drive "$drv_bkfile",cache.no-flush=on -drive "$drv_bk" -drive "$drv_file" -drive "$drv_img" | grep -e "Cache" -e "[Cc]annot\|[Cc]ould not\|[Cc]an't"
+}
+
+echo
+echo "--- Configure cache modes on the command line ---"
+echo
+
+# First check the inherited cache mode after opening the image.
+
+hmp_cmds="info block image
+info block file
+info block backing
+info block backing-file"
+
+check_cache_all_separate
+
+echo
+echo "--- Cache modes after reopen (live snapshot) ---"
+echo
+
+# Then trigger a reopen and check that the cache modes are still the same.
+
+hmp_cmds="snapshot_blkdev -n blk $TEST_IMG.snap $IMGFMT
+info block blk
+info block image
+info block file
+info block backing
+info block backing-file"
+
+check_cache_all_separate
+
+echo
+echo "--- Change cache modes with reopen (qemu-io command, flags) ---"
+echo
+
+# This one actually changes the cache mode with the reopen. For this test, the
+# new cache mode is specified as flags, not as option.
+
+hmp_cmds='qemu-io blk "reopen -c none"
+info block image
+info block file
+info block backing
+info block backing-file'
+
+check_cache_all_separate
+
+
+echo
+echo "=== Reopening children instead of the root ==="
+echo
+
+files="if=none,file=$TEST_IMG,backing.file.filename=$TEST_IMG.base"
+ids="node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file"
+
+echo
+echo "--- Basic reopen ---"
+echo
+
+hmp_cmds='qemu-io none0 "reopen -o backing.cache.direct=on"
+info block none0
+info block image
+info block file
+info block backing
+info block backing-file'
+
+check_cache_all
+
+echo
+echo "--- Change cache mode after reopening child ---"
+echo
+
+# This checks that children with options explicitly set with reopen don't
+# inherit these options from their parents any more
+
+# TODO Implement node-name support for 'qemu-io' HMP command for -c
+# Can use only -o to access child node options for now
+
+hmp_cmds="qemu-io none0 \"reopen -o file.cache.direct=off,file.cache.no-flush=off\"
+qemu-io none0 \"reopen -o backing.file.cache.direct=off,backing.file.cache.no-flush=on\"
+qemu-io none0 \"reopen -c none\"
+info block image
+info block file
+info block backing
+info block backing-file"
+
+echo "$hmp_cmds" | run_qemu -drive "$files","$ids" | grep "Cache"
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/142.out b/qemu/tests/qemu-iotests/142.out
new file mode 100644
index 000000000..600beca8f
--- /dev/null
+++ b/qemu/tests/qemu-iotests/142.out
@@ -0,0 +1,750 @@
+QA output created by 142
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728
+Formatting 'TEST_DIR/t.IMGFMT.snap', fmt=IMGFMT size=134217728
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 backing_file=TEST_DIR/t.IMGFMT.base
+
+=== Simple test for all cache modes ===
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=none
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=directsync
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=writeback
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=writethrough
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=unsafe
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+
+Testing: -drive file=TEST_DIR/t.qcow2,cache=invalid_value
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,cache=invalid_value: invalid cache option
+
+
+=== Check inheritance of cache modes ===
+
+
+--- Configure cache modes on the command line ---
+
+cache.direct=on on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.direct=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+
+
+cache.writeback=off on none0
+ Cache mode: writethrough
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,file.cache.writeback=off: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+cache.writeback=off on backing
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.cache.writeback=off: Could not open backing file: Block format 'qcow2' does not support the option 'cache.writeback'
+
+cache.writeback=off on backing-file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.file.cache.writeback=off: Could not open backing file: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+
+cache.no-flush=on on none0
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+
+cache.no-flush=on on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.no-flush=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+
+cache.no-flush=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+
+--- Cache modes after reopen (live snapshot) ---
+
+cache.direct=on on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.direct=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+
+
+cache.writeback=off on none0
+ Cache mode: writethrough
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,file.cache.writeback=off: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+cache.writeback=off on backing
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.cache.writeback=off: Could not open backing file: Block format 'qcow2' does not support the option 'cache.writeback'
+
+cache.writeback=off on backing-file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.file.cache.writeback=off: Could not open backing file: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+
+cache.no-flush=on on none0
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+
+cache.no-flush=on on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.no-flush=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+
+cache.no-flush=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+
+--- Change cache modes with reopen (qemu-io command, flags) ---
+
+cache.direct=on on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on file
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on backing
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on backing-file
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+
+cache.writeback=off on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.writeback=off on file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,file.cache.writeback=off: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+cache.writeback=off on backing
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.cache.writeback=off: Could not open backing file: Block format 'qcow2' does not support the option 'cache.writeback'
+
+cache.writeback=off on backing-file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.file.cache.writeback=off: Could not open backing file: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+
+cache.no-flush=on on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.no-flush=on on file
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.no-flush=on on backing
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+
+cache.no-flush=on on backing-file
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct, ignore flushes
+
+--- Change cache modes with reopen (qemu-io command, options) ---
+
+cache.direct=on on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on file
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on backing
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on backing-file
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+
+cache.writeback=off on none0
+ Cache mode: writethrough, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.writeback=off on file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,file.cache.writeback=off: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+cache.writeback=off on backing
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.cache.writeback=off: Could not open backing file: Block format 'qcow2' does not support the option 'cache.writeback'
+
+cache.writeback=off on backing-file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.file.cache.writeback=off: Could not open backing file: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+
+cache.no-flush=on on none0
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+
+cache.no-flush=on on file
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.no-flush=on on backing
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+
+cache.no-flush=on on backing-file
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct, ignore flushes
+
+--- Change cache modes after snapshot ---
+
+cache.direct=on on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on file
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.direct=on on backing
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on backing-file
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+
+
+cache.writeback=off on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,file.cache.writeback=off: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+cache.writeback=off on backing
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.cache.writeback=off: Could not open backing file: Block format 'qcow2' does not support the option 'cache.writeback'
+
+cache.writeback=off on backing-file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.file.cache.writeback=off: Could not open backing file: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+
+cache.no-flush=on on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+
+cache.no-flush=on on file
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.no-flush=on on backing
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+
+cache.no-flush=on on backing-file
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+
+--- Change cache mode in parent, child has explicit option in JSON ---
+
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, ignore flushes
+
+=== Check that referenced BDSes don't inherit ===
+
+
+--- Configure cache modes on the command line ---
+
+cache.direct=on on blk
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.direct=on on file
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.direct=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback
+
+cache.direct=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+
+
+cache.writeback=off on blk
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+
+cache.no-flush=on on blk
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.no-flush=on on file
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.no-flush=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+
+cache.no-flush=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+
+--- Cache modes after reopen (live snapshot) ---
+
+cache.direct=on on blk
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.direct=on on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.direct=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback
+
+cache.direct=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+
+
+cache.writeback=off on blk
+ Cache mode: writethrough
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+
+cache.no-flush=on on blk
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.no-flush=on on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.no-flush=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+
+cache.no-flush=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+
+--- Change cache modes with reopen (qemu-io command, flags) ---
+
+cache.direct=on on blk
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.direct=on on file
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.direct=on on backing
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback
+
+cache.direct=on on backing-file
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+
+
+cache.writeback=off on blk
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on file
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on backing
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.writeback=off on backing-file
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+
+cache.no-flush=on on blk
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.no-flush=on on file
+ Cache mode: writeback, direct
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+ Cache mode: writeback
+
+cache.no-flush=on on backing
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback
+
+cache.no-flush=on on backing-file
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+
+=== Reopening children instead of the root ===
+
+
+--- Basic reopen ---
+
+cache.direct=on on none0
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.direct=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+
+cache.writeback=off on none0
+ Cache mode: writethrough
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.writeback=off on file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,file.cache.writeback=off: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+cache.writeback=off on backing
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.cache.writeback=off: Could not open backing file: Block format 'qcow2' does not support the option 'cache.writeback'
+
+cache.writeback=off on backing-file
+QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,backing.file.filename=TEST_DIR/t.qcow2.base,node-name=image,backing.node-name=backing,backing.file.node-name=backing-file,file.node-name=file,backing.file.cache.writeback=off: Could not open backing file: Block protocol 'file' doesn't support the option 'cache.writeback'
+
+
+cache.no-flush=on on none0
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+
+cache.no-flush=on on file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, ignore flushes
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct
+
+cache.no-flush=on on backing
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct, ignore flushes
+ Cache mode: writeback, direct, ignore flushes
+
+cache.no-flush=on on backing-file
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback, direct, ignore flushes
+
+--- Change cache mode after reopening child ---
+
+ Cache mode: writeback, direct
+ Cache mode: writeback
+ Cache mode: writeback, direct
+ Cache mode: writeback, ignore flushes
+*** done
diff --git a/qemu/tests/qemu-iotests/143 b/qemu/tests/qemu-iotests/143
new file mode 100755
index 000000000..ec4ef2221
--- /dev/null
+++ b/qemu/tests/qemu-iotests/143
@@ -0,0 +1,72 @@
+#!/bin/bash
+#
+# Test case for connecting to a non-existing NBD export name
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ rm -f "$TEST_DIR/nbd"
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt generic
+_supported_proto generic
+_supported_os Linux
+
+keep_stderr=y \
+_launch_qemu 2> >(_filter_nbd)
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'qmp_capabilities' }" \
+ 'return'
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'nbd-server-start',
+ 'arguments': { 'addr': { 'type': 'unix',
+ 'data': { 'path': '$TEST_DIR/nbd' }}}}" \
+ 'return'
+
+# This should just result in a client error, not in the server crashing
+$QEMU_IO_PROG -f raw -c quit \
+ "nbd+unix:///no_such_export?socket=$TEST_DIR/nbd" 2>&1 \
+ | _filter_qemu_io | _filter_nbd
+
+_send_qemu_cmd $QEMU_HANDLE \
+ "{ 'execute': 'quit' }" \
+ 'return'
+
+wait=1 _cleanup_qemu
+
+# success, all done
+echo '*** done'
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/143.out b/qemu/tests/qemu-iotests/143.out
new file mode 100644
index 000000000..d24ad20db
--- /dev/null
+++ b/qemu/tests/qemu-iotests/143.out
@@ -0,0 +1,7 @@
+QA output created by 143
+{"return": {}}
+{"return": {}}
+can't open device nbd+unix:///no_such_export?socket=TEST_DIR/nbd: No export with name 'no_such_export' available
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "SHUTDOWN"}
+*** done
diff --git a/qemu/tests/qemu-iotests/144 b/qemu/tests/qemu-iotests/144
new file mode 100755
index 000000000..00de3c33c
--- /dev/null
+++ b/qemu/tests/qemu-iotests/144
@@ -0,0 +1,114 @@
+#!/bin/bash
+# Check live snapshot, followed by active commit, and another snapshot.
+#
+# This test is to catch the error case of BZ #1300209:
+# https://bugzilla.redhat.com/show_bug.cgi?id=1300209
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=jcody@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1 # failure is the default!
+
+TMP_SNAP1=${TEST_DIR}/tmp.qcow2
+TMP_SNAP2=${TEST_DIR}/tmp2.qcow2
+
+_cleanup()
+{
+ _cleanup_qemu
+ rm -f "${TEST_IMG}" "${TMP_SNAP1}" "${TMP_SNAP2}"
+}
+
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt qcow2
+_supported_proto file
+_supported_os Linux
+
+size=512M
+
+_make_test_img $size
+
+echo
+echo === Launching QEMU ===
+echo
+
+qemu_comm_method="qmp"
+_launch_qemu -drive file="${TEST_IMG}",if=virtio
+h=$QEMU_HANDLE
+
+
+echo
+echo === Performing Live Snapshot 1 ===
+echo
+
+_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return"
+
+
+# First live snapshot, new overlay as active layer
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': {
+ 'device': 'virtio0',
+ 'snapshot-file':'${TMP_SNAP1}',
+ 'format': 'qcow2'
+ }
+ }" "return"
+
+echo
+echo === Performing block-commit on active layer ===
+echo
+
+# Block commit on active layer, push the new overlay into base
+_send_qemu_cmd $h "{ 'execute': 'block-commit',
+ 'arguments': {
+ 'device': 'virtio0'
+ }
+ }" "READY"
+
+_send_qemu_cmd $h "{ 'execute': 'block-job-complete',
+ 'arguments': {
+ 'device': 'virtio0'
+ }
+ }" "COMPLETED"
+
+echo
+echo === Performing Live Snapshot 2 ===
+echo
+
+# New live snapshot, new overlays as active layer
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': {
+ 'device': 'virtio0',
+ 'snapshot-file':'${TMP_SNAP2}',
+ 'format': 'qcow2'
+ }
+ }" "return"
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/144.out b/qemu/tests/qemu-iotests/144.out
new file mode 100644
index 000000000..410d74180
--- /dev/null
+++ b/qemu/tests/qemu-iotests/144.out
@@ -0,0 +1,24 @@
+QA output created by 144
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=536870912
+
+=== Launching QEMU ===
+
+
+=== Performing Live Snapshot 1 ===
+
+{"return": {}}
+Formatting 'TEST_DIR/tmp.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+{"return": {}}
+
+=== Performing block-commit on active layer ===
+
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_READY", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "virtio0", "len": 0, "offset": 0, "speed": 0, "type": "commit"}}
+
+=== Performing Live Snapshot 2 ===
+
+Formatting 'TEST_DIR/tmp2.qcow2', fmt=qcow2 size=536870912 backing_file=TEST_DIR/t.qcow2 backing_fmt=qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
+{"return": {}}
+*** done
diff --git a/qemu/tests/qemu-iotests/145 b/qemu/tests/qemu-iotests/145
new file mode 100755
index 000000000..1eca0e899
--- /dev/null
+++ b/qemu/tests/qemu-iotests/145
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# Test the combination of -incoming and snapshot=on
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=kwolf@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+ true
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt generic
+_supported_proto generic
+_supported_os Linux
+
+_make_test_img 1M
+echo quit | $QEMU -nographic -hda "$TEST_IMG" -incoming 'exec:true' -snapshot -serial none -monitor stdio | _filter_qemu
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/145.out b/qemu/tests/qemu-iotests/145.out
new file mode 100644
index 000000000..75b5c8ac3
--- /dev/null
+++ b/qemu/tests/qemu-iotests/145.out
@@ -0,0 +1,5 @@
+QA output created by 145
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
+QEMU X.Y.Z monitor - type 'help' for more information
+(qemu) qququiquit
+*** done
diff --git a/qemu/tests/qemu-iotests/146 b/qemu/tests/qemu-iotests/146
new file mode 100755
index 000000000..043711be6
--- /dev/null
+++ b/qemu/tests/qemu-iotests/146
@@ -0,0 +1,165 @@
+#!/bin/bash
+#
+# Test VHD image format creator detection and override
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=jcody@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+here=`pwd`
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_qemu
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+. ./common.qemu
+
+_supported_fmt vpc
+_supported_proto file
+_supported_os Linux
+
+
+qemu_comm_method="monitor"
+silent=
+
+echo
+echo === Testing VPC Autodetect ===
+echo
+_use_sample_img virtualpc-dynamic.vhd.bz2
+
+${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
+
+echo
+echo === Testing VPC with current_size force ===
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
+
+echo
+echo === Testing VPC with chs force ===
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
+
+_cleanup_test_img
+
+echo
+echo === Testing Hyper-V Autodetect ===
+echo
+_use_sample_img hyperv2012r2-dynamic.vhd.bz2
+
+${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
+
+echo
+echo === Testing Hyper-V with current_size force ===
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
+
+echo
+echo === Testing Hyper-V with chs force ===
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
+
+_cleanup_test_img
+
+echo
+echo === Testing d2v Autodetect ===
+echo
+_use_sample_img d2v-zerofilled.vhd.bz2
+
+${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
+
+echo
+echo === Testing d2v with current_size force ===
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
+
+echo
+echo === Testing d2v with chs force ===
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
+
+_cleanup_test_img
+
+echo
+echo === Testing Image create, default ===
+echo
+
+TEST_IMG="${TEST_DIR}/vpc-create-test.vpc"
+
+_make_test_img 4G
+
+echo
+echo === Read created image, default opts ====
+echo
+
+${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
+
+echo
+echo === Read created image, force_size_calc=chs ====
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
+
+echo
+echo === Read created image, force_size_calc=current_size ====
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
+
+echo
+echo === Testing Image create, force_size ===
+echo
+
+_make_test_img -o force_size 4G
+
+echo
+echo === Read created image, default opts ====
+echo
+
+${QEMU_IO} -c "open -o driver=vpc ${TEST_IMG}" -c 'map'
+
+echo
+echo === Read created image, force_size_calc=chs ====
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=chs ${TEST_IMG}" -c 'map'
+
+echo
+echo === Read created image, force_size_calc=current_size ====
+echo
+
+${QEMU_IO} -c "open -o driver=vpc,force_size_calc=current_size ${TEST_IMG}" -c 'map'
+
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/146.out b/qemu/tests/qemu-iotests/146.out
new file mode 100644
index 000000000..4f334d86b
--- /dev/null
+++ b/qemu/tests/qemu-iotests/146.out
@@ -0,0 +1,70 @@
+QA output created by 146
+
+=== Testing VPC Autodetect ===
+
+[ 0] 266334240/ 266334240 sectors not allocated at offset 0 bytes (0)
+
+=== Testing VPC with current_size force ===
+
+[ 0] 266338304/ 266338304 sectors not allocated at offset 0 bytes (0)
+
+=== Testing VPC with chs force ===
+
+[ 0] 266334240/ 266334240 sectors not allocated at offset 0 bytes (0)
+
+=== Testing Hyper-V Autodetect ===
+
+[ 0] 266338304/ 266338304 sectors not allocated at offset 0 bytes (0)
+
+=== Testing Hyper-V with current_size force ===
+
+[ 0] 266338304/ 266338304 sectors not allocated at offset 0 bytes (0)
+
+=== Testing Hyper-V with chs force ===
+
+[ 0] 266334240/ 266334240 sectors not allocated at offset 0 bytes (0)
+
+=== Testing d2v Autodetect ===
+
+[ 0] 514560/ 514560 sectors allocated at offset 0 bytes (1)
+
+=== Testing d2v with current_size force ===
+
+[ 0] 514560/ 514560 sectors allocated at offset 0 bytes (1)
+
+=== Testing d2v with chs force ===
+
+[ 0] 514560/ 514560 sectors allocated at offset 0 bytes (1)
+
+=== Testing Image create, default ===
+
+Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296
+
+=== Read created image, default opts ====
+
+[ 0] 8389584/ 8389584 sectors not allocated at offset 0 bytes (0)
+
+=== Read created image, force_size_calc=chs ====
+
+[ 0] 8389584/ 8389584 sectors not allocated at offset 0 bytes (0)
+
+=== Read created image, force_size_calc=current_size ====
+
+[ 0] 8389584/ 8389584 sectors not allocated at offset 0 bytes (0)
+
+=== Testing Image create, force_size ===
+
+Formatting 'TEST_DIR/IMGFMT-create-test.IMGFMT', fmt=IMGFMT size=4294967296 force_size=on
+
+=== Read created image, default opts ====
+
+[ 0] 8388608/ 8388608 sectors not allocated at offset 0 bytes (0)
+
+=== Read created image, force_size_calc=chs ====
+
+[ 0] 8388608/ 8388608 sectors not allocated at offset 0 bytes (0)
+
+=== Read created image, force_size_calc=current_size ====
+
+[ 0] 8388608/ 8388608 sectors not allocated at offset 0 bytes (0)
+*** done
diff --git a/qemu/tests/qemu-iotests/148 b/qemu/tests/qemu-iotests/148
new file mode 100644
index 000000000..e01b061fe
--- /dev/null
+++ b/qemu/tests/qemu-iotests/148
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+#
+# Test the rate limit of QMP events
+#
+# Copyright (C) 2016 Igalia, S.L.
+# Author: Alberto Garcia <berto@igalia.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import iotests
+
+imgs = (os.path.join(iotests.test_dir, 'quorum0.img'),
+ os.path.join(iotests.test_dir, 'quorum1.img'),
+ os.path.join(iotests.test_dir, 'quorum2.img'))
+
+img_conf = (os.path.join(iotests.test_dir, 'quorum0.conf'),
+ os.path.join(iotests.test_dir, 'quorum1.conf'),
+ os.path.join(iotests.test_dir, 'quorum2.conf'))
+
+event_rate = 1000000000
+sector_size = 512
+offset = 10
+
+class TestQuorumEvents(iotests.QMPTestCase):
+ read_pattern = 'quorum'
+
+ def create_blkdebug_file(self, blkdebug_file, bad_sector):
+ file = open(blkdebug_file, 'w')
+ file.write('''
+[inject-error]
+event = "read_aio"
+errno = "5"
+sector = "%d"
+''' % bad_sector)
+ file.close()
+
+ def setUp(self):
+ driveopts = ['driver=quorum', 'vote-threshold=2']
+ driveopts.append('read-pattern=%s' % self.read_pattern)
+ for i in range(len(imgs)):
+ iotests.qemu_img('create', '-f', iotests.imgfmt, imgs[i], '1M')
+ self.create_blkdebug_file(img_conf[i], i + offset)
+ driveopts.append('children.%d.driver=%s' % (i, iotests.imgfmt))
+ driveopts.append('children.%d.file.driver=blkdebug' % i)
+ driveopts.append('children.%d.file.config=%s' % (i, img_conf[i]))
+ driveopts.append('children.%d.file.image.filename=%s' % (i, imgs[i]))
+ driveopts.append('children.%d.node-name=img%d' % (i, i))
+ self.vm = iotests.VM()
+ self.vm.add_drive(None, opts = ','.join(driveopts))
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ for i in range(len(imgs)):
+ os.remove(imgs[i])
+ os.remove(img_conf[i])
+
+ def do_check_event(self, node, sector = 0):
+ if node == None:
+ self.assertEqual(self.vm.get_qmp_event(), None)
+ return
+
+ for event in self.vm.get_qmp_events(wait=True):
+ if event['event'] == 'QUORUM_REPORT_BAD':
+ self.assert_qmp(event, 'data/node-name', node)
+ self.assert_qmp(event, 'data/sector-num', sector)
+
+ def testQuorum(self):
+ # Generate an error and get an event
+ self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
+ (offset * sector_size, sector_size))
+ self.vm.qtest("clock_step 10")
+ self.do_check_event('img0', offset)
+
+ # I/O errors in the same child: only one event is emitted
+ delay = 10
+ for i in range(3):
+ self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
+ (offset * sector_size, sector_size))
+ self.vm.qtest("clock_step %d" % delay)
+ self.do_check_event(None)
+
+ # Wait enough so the event is finally emitted
+ self.vm.qtest("clock_step %d" % (2 * event_rate))
+ self.do_check_event('img0', offset)
+
+ # I/O errors in the same child: all events are emitted
+ delay = 2 * event_rate
+ for i in range(3):
+ self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
+ (offset * sector_size, sector_size))
+ self.vm.qtest("clock_step %d" % delay)
+ self.do_check_event('img0', offset)
+
+ # I/O errors in different children: all events are emitted
+ delay = 10
+ for i in range(len(imgs)):
+ self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
+ ((offset + i) * sector_size, sector_size))
+ self.vm.qtest("clock_step %d" % delay)
+ # In fifo mode only errors in the first child are detected
+ if i > 0 and self.read_pattern == 'fifo':
+ self.do_check_event(None)
+ else:
+ self.do_check_event('img%d' % i, offset + i)
+
+ # I/O errors in different children: all events are emitted
+ delay = 2 * event_rate
+ for i in range(len(imgs)):
+ self.vm.hmp_qemu_io("drive0", "aio_read %d %d" %
+ ((offset + i) * sector_size, sector_size))
+ self.vm.qtest("clock_step %d" % delay)
+ # In fifo mode only errors in the first child are detected
+ if i > 0 and self.read_pattern == 'fifo':
+ self.do_check_event(None)
+ else:
+ self.do_check_event('img%d' % i, offset + i)
+
+ # No more pending events
+ self.do_check_event(None)
+
+class TestFifoQuorumEvents(TestQuorumEvents):
+ read_pattern = 'fifo'
+
+if __name__ == '__main__':
+ iotests.verify_quorum()
+ iotests.main(supported_fmts=["raw"])
diff --git a/qemu/tests/qemu-iotests/148.out b/qemu/tests/qemu-iotests/148.out
new file mode 100644
index 000000000..fbc63e62f
--- /dev/null
+++ b/qemu/tests/qemu-iotests/148.out
@@ -0,0 +1,5 @@
+..
+----------------------------------------------------------------------
+Ran 2 tests
+
+OK
diff --git a/qemu/tests/qemu-iotests/149 b/qemu/tests/qemu-iotests/149
new file mode 100755
index 000000000..52e23d294
--- /dev/null
+++ b/qemu/tests/qemu-iotests/149
@@ -0,0 +1,519 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Creator/Owner: Daniel P. Berrange <berrange@redhat.com>
+#
+# Exercise the QEMU 'luks' block driver to validate interoperability
+# with the Linux dm-crypt + cryptsetup implementation
+
+import subprocess
+import os
+import os.path
+
+import base64
+
+import iotests
+
+
+class LUKSConfig(object):
+ """Represent configuration parameters for a single LUKS
+ setup to be tested"""
+
+ def __init__(self, name, cipher, keylen, mode, ivgen,
+ ivgen_hash, hash, password=None, passwords=None):
+
+ self.name = name
+ self.cipher = cipher
+ self.keylen = keylen
+ self.mode = mode
+ self.ivgen = ivgen
+ self.ivgen_hash = ivgen_hash
+ self.hash = hash
+
+ if passwords is not None:
+ self.passwords = passwords
+ else:
+ self.passwords = {}
+
+ if password is None:
+ self.passwords["0"] = "123456"
+ else:
+ self.passwords["0"] = password
+
+ def __repr__(self):
+ return self.name
+
+ def image_name(self):
+ return "luks-%s.img" % self.name
+
+ def image_path(self):
+ return os.path.join(iotests.test_dir, self.image_name())
+
+ def device_name(self):
+ return "qiotest-145-%s" % self.name
+
+ def device_path(self):
+ return "/dev/mapper/" + self.device_name()
+
+ def first_password(self):
+ for i in range(8):
+ slot = str(i)
+ if slot in self.passwords:
+ return (self.passwords[slot], slot)
+ raise Exception("No password found")
+
+ def first_password_base64(self):
+ (pw, slot) = self.first_password()
+ return base64.b64encode(pw)
+
+ def active_slots(self):
+ slots = []
+ for i in range(8):
+ slot = str(i)
+ if slot in self.passwords:
+ slots.append(slot)
+ return slots
+
+def verify_passwordless_sudo():
+ """Check whether sudo is configured to allow
+ password-less access to commands"""
+
+ args = ["sudo", "-n", "/bin/true"]
+
+ proc = subprocess.Popen(args,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+ msg = proc.communicate()[0]
+
+ if proc.returncode != 0:
+ iotests.notrun('requires password-less sudo access: %s' % msg)
+
+
+def cryptsetup(args, password=None):
+ """Run the cryptsetup command in batch mode"""
+
+ fullargs = ["sudo", "cryptsetup", "-q", "-v"]
+ fullargs.extend(args)
+
+ iotests.log(" ".join(fullargs), filters=[iotests.filter_test_dir])
+ proc = subprocess.Popen(fullargs,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+ msg = proc.communicate(password)[0]
+
+ if proc.returncode != 0:
+ raise Exception(msg)
+
+
+def cryptsetup_add_password(config, slot):
+ """Add another password to a LUKS key slot"""
+
+ (password, mainslot) = config.first_password()
+
+ pwfile = os.path.join(iotests.test_dir, "passwd.txt")
+ with open(pwfile, "w") as fh:
+ fh.write(config.passwords[slot])
+
+ try:
+ args = ["luksAddKey", config.image_path(),
+ "--key-slot", slot,
+ "--key-file", "-",
+ pwfile]
+
+ cryptsetup(args, password)
+ finally:
+ os.unlink(pwfile)
+
+
+def cryptsetup_format(config):
+ """Format a new LUKS volume with cryptsetup, adding the
+ first key slot only"""
+
+ (password, slot) = config.first_password()
+
+ args = ["luksFormat"]
+ cipher = config.cipher + "-" + config.mode + "-" + config.ivgen
+ if config.ivgen_hash is not None:
+ cipher = cipher + ":" + config.ivgen_hash
+ args.extend(["--cipher", cipher])
+ if config.mode == "xts":
+ args.extend(["--key-size", str(config.keylen * 2)])
+ else:
+ args.extend(["--key-size", str(config.keylen)])
+ if config.hash is not None:
+ args.extend(["--hash", config.hash])
+ args.extend(["--key-slot", slot])
+ args.extend(["--key-file", "-"])
+ args.append(config.image_path())
+
+ cryptsetup(args, password)
+
+
+def chown(config):
+ """Set the ownership of a open LUKS device to this user"""
+
+ path = config.device_path()
+
+ args = ["sudo", "chown", "%d:%d" % (os.getuid(), os.getgid()), path]
+ iotests.log(" ".join(args), filters=[iotests.filter_chown])
+ proc = subprocess.Popen(args,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+ msg = proc.communicate()[0]
+
+ if proc.returncode != 0:
+ raise Exception("Cannot change owner on %s" % path)
+
+
+def cryptsetup_open(config):
+ """Open an image as a LUKS device"""
+
+ (password, slot) = config.first_password()
+
+ args = ["luksOpen", config.image_path(), config.device_name()]
+
+ cryptsetup(args, password)
+
+
+def cryptsetup_close(config):
+ """Close an active LUKS device """
+
+ args = ["luksClose", config.device_name()]
+ cryptsetup(args)
+
+
+def delete_image(config):
+ """Delete a disk image"""
+
+ try:
+ os.unlink(config.image_path())
+ iotests.log("unlink %s" % config.image_path(),
+ filters=[iotests.filter_test_dir])
+ except Exception as e:
+ pass
+
+
+def create_image(config, size_mb):
+ """Create a bare disk image with requested size"""
+
+ delete_image(config)
+ iotests.log("truncate %s --size %dMB" % (config.image_path(), size_mb),
+ filters=[iotests.filter_test_dir])
+ with open(config.image_path(), "w") as fn:
+ fn.truncate(size_mb * 1024 * 1024)
+
+
+def qemu_img_create(config, size_mb):
+ """Create and format a disk image with LUKS using qemu-img"""
+
+ opts = [
+ "key-secret=sec0",
+ "cipher-alg=%s-%d" % (config.cipher, config.keylen),
+ "cipher-mode=%s" % config.mode,
+ "ivgen-alg=%s" % config.ivgen,
+ "hash-alg=%s" % config.hash,
+ ]
+ if config.ivgen_hash is not None:
+ opts.append("ivgen-hash-alg=%s" % config.ivgen_hash)
+
+ args = ["create", "-f", "luks",
+ "--object",
+ ("secret,id=sec0,data=%s,format=base64" %
+ config.first_password_base64()),
+ "-o", ",".join(opts),
+ config.image_path(),
+ "%dM" % size_mb]
+
+ iotests.log("qemu-img " + " ".join(args), filters=[iotests.filter_test_dir])
+ iotests.log(iotests.qemu_img_pipe(*args), filters=[iotests.filter_test_dir])
+
+def qemu_io_image_args(config, dev=False):
+ """Get the args for access an image or device with qemu-io"""
+
+ if dev:
+ return [
+ "--image-opts",
+ "driver=file,filename=%s" % config.device_path()]
+ else:
+ return [
+ "--object",
+ ("secret,id=sec0,data=%s,format=base64" %
+ config.first_password_base64()),
+ "--image-opts",
+ ("driver=luks,key-secret=sec0,file.filename=%s" %
+ config.image_path())]
+
+def qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False):
+ """Write a pattern of data to a LUKS image or device"""
+
+ args = ["-c", "write -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
+ args.extend(qemu_io_image_args(config, dev))
+ iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
+ iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir,
+ iotests.filter_qemu_io])
+
+
+def qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False):
+ """Read a pattern of data to a LUKS image or device"""
+
+ args = ["-c", "read -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
+ args.extend(qemu_io_image_args(config, dev))
+ iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
+ iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir,
+ iotests.filter_qemu_io])
+
+
+def test_once(config, qemu_img=False):
+ """Run the test with a desired LUKS configuration. Can either
+ use qemu-img for creating the initial volume, or cryptsetup,
+ in order to test interoperability in both directions"""
+
+ iotests.log("# ================= %s %s =================" % (
+ "qemu-img" if qemu_img else "dm-crypt", config))
+
+ oneKB = 1024
+ oneMB = oneKB * 1024
+ oneGB = oneMB * 1024
+ oneTB = oneGB * 1024
+
+ # 4 TB, so that we pass the 32-bit sector number boundary.
+ # Important for testing correctness of some IV generators
+ # The files are sparse, so not actually using this much space
+ image_size = 4 * oneTB
+ if qemu_img:
+ iotests.log("# Create image")
+ qemu_img_create(config, image_size / oneMB)
+ else:
+ iotests.log("# Create image")
+ create_image(config, image_size / oneMB)
+
+ lowOffsetMB = 100
+ highOffsetMB = 3 * oneTB / oneMB
+
+ try:
+ if not qemu_img:
+ iotests.log("# Format image")
+ cryptsetup_format(config)
+
+ for slot in config.active_slots()[1:]:
+ iotests.log("# Add password slot %s" % slot)
+ cryptsetup_add_password(config, slot)
+
+ # First we'll open the image using cryptsetup and write a
+ # known pattern of data that we'll then verify with QEMU
+
+ iotests.log("# Open dev")
+ cryptsetup_open(config)
+
+ try:
+ iotests.log("# Set dev owner")
+ chown(config)
+
+ iotests.log("# Write test pattern 0xa7")
+ qemu_io_write_pattern(config, 0xa7, lowOffsetMB, 10, dev=True)
+ iotests.log("# Write test pattern 0x13")
+ qemu_io_write_pattern(config, 0x13, highOffsetMB, 10, dev=True)
+ finally:
+ iotests.log("# Close dev")
+ cryptsetup_close(config)
+
+ # Ok, now we're using QEMU to verify the pattern just
+ # written via dm-crypt
+
+ iotests.log("# Read test pattern 0xa7")
+ qemu_io_read_pattern(config, 0xa7, lowOffsetMB, 10, dev=False)
+ iotests.log("# Read test pattern 0x13")
+ qemu_io_read_pattern(config, 0x13, highOffsetMB, 10, dev=False)
+
+
+ # Write a new pattern to the image, which we'll later
+ # verify with dm-crypt
+ iotests.log("# Write test pattern 0x91")
+ qemu_io_write_pattern(config, 0x91, lowOffsetMB, 10, dev=False)
+ iotests.log("# Write test pattern 0x5e")
+ qemu_io_write_pattern(config, 0x5e, highOffsetMB, 10, dev=False)
+
+
+ # Now we're opening the image with dm-crypt once more
+ # and verifying what QEMU wrote, completing the circle
+ iotests.log("# Open dev")
+ cryptsetup_open(config)
+
+ try:
+ iotests.log("# Set dev owner")
+ chown(config)
+
+ iotests.log("# Read test pattern 0x91")
+ qemu_io_read_pattern(config, 0x91, lowOffsetMB, 10, dev=True)
+ iotests.log("# Read test pattern 0x5e")
+ qemu_io_read_pattern(config, 0x5e, highOffsetMB, 10, dev=True)
+ finally:
+ iotests.log("# Close dev")
+ cryptsetup_close(config)
+ finally:
+ iotests.log("# Delete image")
+ delete_image(config)
+ print
+
+
+# Obviously we only work with the luks image format
+iotests.verify_image_format(supported_fmts=['luks'])
+iotests.verify_platform()
+
+# We need sudo in order to run cryptsetup to create
+# dm-crypt devices. This is safe to use on any
+# machine, since all dm-crypt devices are backed
+# by newly created plain files, and have a dm-crypt
+# name prefix of 'qiotest' to avoid clashing with
+# user LUKS volumes
+verify_passwordless_sudo()
+
+
+# If we look at all permutations of cipher, key size,
+# mode, ivgen, hash, there are ~1000 possible configs.
+#
+# We certainly don't want/need to test every permutation
+# to get good validation of interoperability between QEMU
+# and dm-crypt/cryptsetup.
+#
+# The configs below are a representative set that aim to
+# exercise each axis of configurability.
+#
+configs = [
+ # A common LUKS default
+ LUKSConfig("aes-256-xts-plain64-sha1",
+ "aes", 256, "xts", "plain64", None, "sha1"),
+
+
+ # LUKS default but diff ciphers
+ LUKSConfig("twofish-256-xts-plain64-sha1",
+ "twofish", 256, "xts", "plain64", None, "sha1"),
+ LUKSConfig("serpent-256-xts-plain64-sha1",
+ "serpent", 256, "xts", "plain64", None, "sha1"),
+ # Should really be xts, but kernel doesn't support xts+cast5
+ # nor does it do essiv+cast5
+ LUKSConfig("cast5-128-cbc-plain64-sha1",
+ "cast5", 128, "cbc", "plain64", None, "sha1"),
+ LUKSConfig("cast6-256-xts-plain64-sha1",
+ "cast6", 256, "xts", "plain64", None, "sha1"),
+
+
+ # LUKS default but diff modes / ivgens
+ LUKSConfig("aes-256-cbc-plain-sha1",
+ "aes", 256, "cbc", "plain", None, "sha1"),
+ LUKSConfig("aes-256-cbc-plain64-sha1",
+ "aes", 256, "cbc", "plain64", None, "sha1"),
+ LUKSConfig("aes-256-cbc-essiv-sha256-sha1",
+ "aes", 256, "cbc", "essiv", "sha256", "sha1"),
+ LUKSConfig("aes-256-xts-essiv-sha256-sha1",
+ "aes", 256, "xts", "essiv", "sha256", "sha1"),
+
+
+ # LUKS default but smaller key sizes
+ LUKSConfig("aes-128-xts-plain64-sha256-sha1",
+ "aes", 128, "xts", "plain64", None, "sha1"),
+ LUKSConfig("aes-192-xts-plain64-sha256-sha1",
+ "aes", 192, "xts", "plain64", None, "sha1"),
+
+ LUKSConfig("twofish-128-xts-plain64-sha1",
+ "twofish", 128, "xts", "plain64", None, "sha1"),
+ LUKSConfig("twofish-192-xts-plain64-sha1",
+ "twofish", 192, "xts", "plain64", None, "sha1"),
+
+ LUKSConfig("serpent-128-xts-plain64-sha1",
+ "serpent", 128, "xts", "plain64", None, "sha1"),
+ LUKSConfig("serpent-192-xts-plain64-sha1",
+ "serpent", 192, "xts", "plain64", None, "sha1"),
+
+ LUKSConfig("cast6-128-xts-plain64-sha1",
+ "cast6", 128, "xts", "plain", None, "sha1"),
+ LUKSConfig("cast6-192-xts-plain64-sha1",
+ "cast6", 192, "xts", "plain64", None, "sha1"),
+
+
+ # LUKS default but diff hash
+ LUKSConfig("aes-256-xts-plain64-sha256",
+ "aes", 256, "xts", "plain64", None, "sha256"),
+ LUKSConfig("aes-256-xts-plain64-sha512",
+ "aes", 256, "xts", "plain64", None, "sha512"),
+ LUKSConfig("aes-256-xts-plain64-ripemd160",
+ "aes", 256, "xts", "plain64", None, "ripemd160"),
+
+ # Password in slot 3
+ LUKSConfig("aes-256-xts-plain-sha1-pwslot3",
+ "aes", 256, "xts", "plain", None, "sha1",
+ passwords={
+ "3": "slot3",
+ }),
+
+ # Passwords in every slot
+ LUKSConfig("aes-256-xts-plain-sha1-pwallslots",
+ "aes", 256, "xts", "plain", None, "sha1",
+ passwords={
+ "0": "slot1",
+ "1": "slot1",
+ "2": "slot2",
+ "3": "slot3",
+ "4": "slot4",
+ "5": "slot5",
+ "6": "slot6",
+ "7": "slot7",
+ }),
+]
+
+blacklist = [
+ # We don't have a cast-6 cipher impl for QEMU yet
+ "cast6-256-xts-plain64-sha1",
+ "cast6-128-xts-plain64-sha1",
+ "cast6-192-xts-plain64-sha1",
+
+ # GCrypt doesn't support Twofish with 192 bit key
+ "twofish-192-xts-plain64-sha1",
+
+ # We don't have sha512 hash wired up yet
+ "aes-256-xts-plain64-sha512",
+
+ # We don't have ripemd160 hash wired up yet
+ "aes-256-xts-plain64-ripemd160",
+]
+
+whitelist = []
+if "LUKS_CONFIG" in os.environ:
+ whitelist = os.environ["LUKS_CONFIG"].split(",")
+
+for config in configs:
+ if config.name in blacklist:
+ iotests.log("Skipping %s in blacklist" % config.name)
+ continue
+
+ if len(whitelist) > 0 and config.name not in whitelist:
+ iotests.log("Skipping %s not in whitelist" % config.name)
+ continue
+
+ test_once(config, qemu_img=False)
+
+ # XXX we should support setting passwords in a non-0
+ # key slot with 'qemu-img create' in future
+ (pw, slot) = config.first_password()
+ if slot == "0":
+ test_once(config, qemu_img=True)
diff --git a/qemu/tests/qemu-iotests/149.out b/qemu/tests/qemu-iotests/149.out
new file mode 100644
index 000000000..287f01301
--- /dev/null
+++ b/qemu/tests/qemu-iotests/149.out
@@ -0,0 +1,1880 @@
+# ================= dm-crypt aes-256-xts-plain64-sha1 =================
+# Create image
+truncate TEST_DIR/luks-aes-256-xts-plain64-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+
+# ================= qemu-img aes-256-xts-plain64-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain64-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha1.img qiotest-145-aes-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha1.img
+
+# ================= dm-crypt twofish-256-xts-plain64-sha1 =================
+# Create image
+truncate TEST_DIR/luks-twofish-256-xts-plain64-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-twofish-256-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-twofish-256-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+
+# ================= qemu-img twofish-256-xts-plain64-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=twofish-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-256-xts-plain64-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-twofish-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-twofish-256-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-256-xts-plain64-sha1.img qiotest-145-twofish-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-twofish-256-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-twofish-256-xts-plain64-sha1.img
+
+# ================= dm-crypt serpent-256-xts-plain64-sha1 =================
+# Create image
+truncate TEST_DIR/luks-serpent-256-xts-plain64-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-256-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-256-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+
+# ================= qemu-img serpent-256-xts-plain64-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=serpent-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-256-xts-plain64-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-serpent-256-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-256-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-256-xts-plain64-sha1.img qiotest-145-serpent-256-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-256-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-256-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-serpent-256-xts-plain64-sha1.img
+
+# ================= dm-crypt cast5-128-cbc-plain64-sha1 =================
+# Create image
+truncate TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher cast5-cbc-plain64 --key-size 128 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-cast5-128-cbc-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-cast5-128-cbc-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+
+# ================= qemu-img cast5-128-cbc-plain64-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=cast5-128,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=cast5-128 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-cast5-128-cbc-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img qiotest-145-cast5-128-cbc-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-cast5-128-cbc-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-cast5-128-cbc-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-cast5-128-cbc-plain64-sha1.img
+
+Skipping cast6-256-xts-plain64-sha1 in blacklist
+# ================= dm-crypt aes-256-cbc-plain-sha1 =================
+# Create image
+truncate TEST_DIR/luks-aes-256-cbc-plain-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+
+# ================= qemu-img aes-256-cbc-plain-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-aes-256-cbc-plain-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain-sha1.img qiotest-145-aes-256-cbc-plain-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-plain-sha1.img
+
+# ================= dm-crypt aes-256-cbc-plain64-sha1 =================
+# Create image
+truncate TEST_DIR/luks-aes-256-cbc-plain64-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-cbc-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+
+# ================= qemu-img aes-256-cbc-plain64-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-256-cbc-plain64-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-aes-256-cbc-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-plain64-sha1.img qiotest-145-aes-256-cbc-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-plain64-sha1.img
+
+# ================= dm-crypt aes-256-cbc-essiv-sha256-sha1 =================
+# Create image
+truncate TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+
+# ================= qemu-img aes-256-cbc-essiv-sha256-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=cbc,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=cbc ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-cbc-essiv-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-cbc-essiv-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-cbc-essiv-sha256-sha1.img
+
+# ================= dm-crypt aes-256-xts-essiv-sha256-sha1 =================
+# Create image
+truncate TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-xts-essiv:sha256 --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+
+# ================= qemu-img aes-256-xts-essiv-sha256-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=essiv,hash-alg=sha1,ivgen-hash-alg=sha256 TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=essiv ivgen-hash-alg=sha256 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-essiv-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-essiv-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-256-xts-essiv-sha256-sha1.img
+
+# ================= dm-crypt aes-128-xts-plain64-sha256-sha1 =================
+# Create image
+truncate TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+
+# ================= qemu-img aes-128-xts-plain64-sha256-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-128-xts-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-128-xts-plain64-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-128-xts-plain64-sha256-sha1.img
+
+# ================= dm-crypt aes-192-xts-plain64-sha256-sha1 =================
+# Create image
+truncate TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+
+# ================= qemu-img aes-192-xts-plain64-sha256-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-192-xts-plain64-sha256-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-192-xts-plain64-sha256-sha1
+# Delete image
+unlink TEST_DIR/luks-aes-192-xts-plain64-sha256-sha1.img
+
+# ================= dm-crypt twofish-128-xts-plain64-sha1 =================
+# Create image
+truncate TEST_DIR/luks-twofish-128-xts-plain64-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher twofish-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-twofish-128-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-twofish-128-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+
+# ================= qemu-img twofish-128-xts-plain64-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=twofish-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-twofish-128-xts-plain64-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-twofish-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=twofish-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-twofish-128-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-twofish-128-xts-plain64-sha1.img qiotest-145-twofish-128-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-twofish-128-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-twofish-128-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-twofish-128-xts-plain64-sha1.img
+
+Skipping twofish-192-xts-plain64-sha1 in blacklist
+# ================= dm-crypt serpent-128-xts-plain64-sha1 =================
+# Create image
+truncate TEST_DIR/luks-serpent-128-xts-plain64-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 256 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-128-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-128-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+
+# ================= qemu-img serpent-128-xts-plain64-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=serpent-128,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-128-xts-plain64-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-serpent-128-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-128 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-128-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-128-xts-plain64-sha1.img qiotest-145-serpent-128-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-128-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-128-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-serpent-128-xts-plain64-sha1.img
+
+# ================= dm-crypt serpent-192-xts-plain64-sha1 =================
+# Create image
+truncate TEST_DIR/luks-serpent-192-xts-plain64-sha1.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher serpent-xts-plain64 --key-size 384 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-192-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-192-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+
+# ================= qemu-img serpent-192-xts-plain64-sha1 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=serpent-192,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha1 TEST_DIR/luks-serpent-192-xts-plain64-sha1.img 4194304M
+Formatting 'TEST_DIR/luks-serpent-192-xts-plain64-sha1.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=serpent-192 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-192-xts-plain64-sha1
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-serpent-192-xts-plain64-sha1.img qiotest-145-serpent-192-xts-plain64-sha1
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-serpent-192-xts-plain64-sha1
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-serpent-192-xts-plain64-sha1
+# Delete image
+unlink TEST_DIR/luks-serpent-192-xts-plain64-sha1.img
+
+Skipping cast6-128-xts-plain64-sha1 in blacklist
+Skipping cast6-192-xts-plain64-sha1 in blacklist
+# ================= dm-crypt aes-256-xts-plain64-sha256 =================
+# Create image
+truncate TEST_DIR/luks-aes-256-xts-plain64-sha256.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain64 --key-size 512 --hash sha256 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha256
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha256
+# Delete image
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+
+# ================= qemu-img aes-256-xts-plain64-sha256 =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=MTIzNDU2,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain64,hash-alg=sha256 TEST_DIR/luks-aes-256-xts-plain64-sha256.img 4194304M
+Formatting 'TEST_DIR/luks-aes-256-xts-plain64-sha256.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain64 hash-alg=sha256
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha256
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=MTIzNDU2,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain64-sha256.img qiotest-145-aes-256-xts-plain64-sha256
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain64-sha256
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain64-sha256
+# Delete image
+unlink TEST_DIR/luks-aes-256-xts-plain64-sha256.img
+
+Skipping aes-256-xts-plain64-sha512 in blacklist
+Skipping aes-256-xts-plain64-ripemd160 in blacklist
+# ================= dm-crypt aes-256-xts-plain-sha1-pwslot3 =================
+# Create image
+truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 3 --key-file - TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img qiotest-145-aes-256-xts-plain-sha1-pwslot3
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain-sha1-pwslot3
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=c2xvdDM=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=c2xvdDM=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=c2xvdDM=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=c2xvdDM=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img qiotest-145-aes-256-xts-plain-sha1-pwslot3
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwslot3
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain-sha1-pwslot3
+# Delete image
+unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwslot3.img
+
+# ================= dm-crypt aes-256-xts-plain-sha1-pwallslots =================
+# Create image
+truncate TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --size 4194304MB
+# Format image
+sudo cryptsetup -q -v luksFormat --cipher aes-xts-plain --key-size 512 --hash sha1 --key-slot 0 --key-file - TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+# Add password slot 1
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 1 --key-file - TEST_DIR/passwd.txt
+# Add password slot 2
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 2 --key-file - TEST_DIR/passwd.txt
+# Add password slot 3
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 3 --key-file - TEST_DIR/passwd.txt
+# Add password slot 4
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 4 --key-file - TEST_DIR/passwd.txt
+# Add password slot 5
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 5 --key-file - TEST_DIR/passwd.txt
+# Add password slot 6
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 6 --key-file - TEST_DIR/passwd.txt
+# Add password slot 7
+sudo cryptsetup -q -v luksAddKey TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img --key-slot 7 --key-file - TEST_DIR/passwd.txt
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=c2xvdDE=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=c2xvdDE=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=c2xvdDE=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=c2xvdDE=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Delete image
+unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+
+# ================= qemu-img aes-256-xts-plain-sha1-pwallslots =================
+# Create image
+qemu-img create -f luks --object secret,id=sec0,data=c2xvdDE=,format=base64 -o key-secret=sec0,cipher-alg=aes-256,cipher-mode=xts,ivgen-alg=plain,hash-alg=sha1 TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img 4194304M
+Formatting 'TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img', fmt=luks size=4398046511104 key-secret=sec0 cipher-alg=aes-256 cipher-mode=xts ivgen-alg=plain hash-alg=sha1
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Write test pattern 0xa7
+qemu-io -c write -P 0xa7 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x13
+qemu-io -c write -P 0x13 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Read test pattern 0xa7
+qemu-io -c read -P 0xa7 100M 10M --object secret,id=sec0,data=c2xvdDE=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x13
+qemu-io -c read -P 0x13 3145728M 10M --object secret,id=sec0,data=c2xvdDE=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x91
+qemu-io -c write -P 0x91 100M 10M --object secret,id=sec0,data=c2xvdDE=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+wrote 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Write test pattern 0x5e
+qemu-io -c write -P 0x5e 3145728M 10M --object secret,id=sec0,data=c2xvdDE=,format=base64 --image-opts driver=luks,key-secret=sec0,file.filename=TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+wrote 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Open dev
+sudo cryptsetup -q -v luksOpen TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Set dev owner
+sudo chown UID:GID /dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Read test pattern 0x91
+qemu-io -c read -P 0x91 100M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+read 10485760/10485760 bytes at offset 104857600
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Read test pattern 0x5e
+qemu-io -c read -P 0x5e 3145728M 10M --image-opts driver=file,filename=/dev/mapper/qiotest-145-aes-256-xts-plain-sha1-pwallslots
+read 10485760/10485760 bytes at offset 3298534883328
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+# Close dev
+sudo cryptsetup -q -v luksClose qiotest-145-aes-256-xts-plain-sha1-pwallslots
+# Delete image
+unlink TEST_DIR/luks-aes-256-xts-plain-sha1-pwallslots.img
+
diff --git a/qemu/tests/qemu-iotests/150 b/qemu/tests/qemu-iotests/150
new file mode 100755
index 000000000..ee8f6375f
--- /dev/null
+++ b/qemu/tests/qemu-iotests/150
@@ -0,0 +1,73 @@
+#!/bin/bash
+#
+# Test that qemu-img convert -S 0 fully allocates the target image
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# creator
+owner=mreitz@redhat.com
+
+seq="$(basename $0)"
+echo "QA output created by $seq"
+
+here="$PWD"
+status=1 # failure is the default!
+
+_cleanup()
+{
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt raw qcow2
+_supported_proto file
+_supported_os Linux
+
+
+img_size=1048576
+
+
+echo
+echo '=== Mapping sparse conversion ==='
+echo
+
+$QEMU_IMG_PROG convert -O "$IMGFMT" -S 512 \
+ "json:{ 'driver': 'null-co', 'size': $img_size, 'read-zeroes': true }" \
+ "$TEST_IMG"
+
+$QEMU_IMG map "$TEST_IMG" | _filter_qemu_img_map
+
+
+echo
+echo '=== Mapping non-sparse conversion ==='
+echo
+
+$QEMU_IMG convert -O "$IMGFMT" -S 0 \
+ "json:{ 'driver': 'null-co', 'size': $img_size, 'read-zeroes': true }" \
+ "$TEST_IMG"
+
+$QEMU_IMG map "$TEST_IMG" | _filter_qemu_img_map
+
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/qemu/tests/qemu-iotests/150.out b/qemu/tests/qemu-iotests/150.out
new file mode 100644
index 000000000..2a54e8dcf
--- /dev/null
+++ b/qemu/tests/qemu-iotests/150.out
@@ -0,0 +1,11 @@
+QA output created by 150
+
+=== Mapping sparse conversion ===
+
+Offset Length File
+
+=== Mapping non-sparse conversion ===
+
+Offset Length File
+0 0x100000 TEST_DIR/t.IMGFMT
+*** done
diff --git a/qemu/tests/qemu-iotests/152 b/qemu/tests/qemu-iotests/152
new file mode 100644
index 000000000..fec546d03
--- /dev/null
+++ b/qemu/tests/qemu-iotests/152
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+#
+# Tests for drive-mirror with source size unaligned to granularity
+#
+# Copyright (C) 2016 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import iotests
+from iotests import qemu_img
+
+test_img = os.path.join(iotests.test_dir, 'test.img')
+target_img = os.path.join(iotests.test_dir, 'target.img')
+
+class TestUnaligned(iotests.QMPTestCase):
+ def setUp(self):
+ qemu_img('create', '-f', iotests.imgfmt, test_img, '512')
+ self.vm = iotests.VM().add_drive(test_img)
+ self.vm.launch()
+
+ def tearDown(self):
+ self.vm.shutdown()
+ os.remove(test_img)
+ try:
+ os.remove(target_img)
+ except OSError:
+ pass
+
+ def test_unaligned(self):
+ result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
+ granularity=65536, target=target_img)
+ self.complete_and_wait()
+ self.vm.shutdown()
+ self.assertEqual(iotests.image_size(test_img), iotests.image_size(target_img),
+ "Target size doesn't match source when granularity when unaligend")
+
+ def test_unaligned_with_update(self):
+ result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
+ granularity=65536, target=target_img)
+ self.wait_ready()
+ self.vm.hmp_qemu_io('drive0', 'write 0 512')
+ self.complete_and_wait(wait_ready=False)
+ self.vm.shutdown()
+ self.assertEqual(iotests.image_size(test_img), iotests.image_size(target_img),
+ "Target size doesn't match source when granularity when unaligend")
+
+
+if __name__ == '__main__':
+ iotests.main(supported_fmts=['raw', 'qcow2'])
diff --git a/qemu/tests/qemu-iotests/152.out b/qemu/tests/qemu-iotests/152.out
new file mode 100644
index 000000000..fbc63e62f
--- /dev/null
+++ b/qemu/tests/qemu-iotests/152.out
@@ -0,0 +1,5 @@
+..
+----------------------------------------------------------------------
+Ran 2 tests
+
+OK
diff --git a/qemu/tests/qemu-iotests/check b/qemu/tests/qemu-iotests/check
index 1fa63193b..4cba2151e 100755
--- a/qemu/tests/qemu-iotests/check
+++ b/qemu/tests/qemu-iotests/check
@@ -19,7 +19,6 @@
# Control script for QA
#
-tmp=/tmp/$$
status=0
needwrap=true
try=0
@@ -130,6 +129,8 @@ fi
# exit 1
#fi
+tmp="${TEST_DIR}"/$$
+
_wallclock()
{
date "+%H %M %S" | $AWK_PROG '{ print $1*3600 + $2*60 + $3 }'
@@ -146,8 +147,8 @@ _wrapup()
# for hangcheck ...
# remove files that were used by hangcheck
#
- [ -f /tmp/check.pid ] && rm -rf /tmp/check.pid
- [ -f /tmp/check.sts ] && rm -rf /tmp/check.sts
+ [ -f "${TEST_DIR}"/check.pid ] && rm -rf "${TEST_DIR}"/check.pid
+ [ -f "${TEST_DIR}"/check.sts ] && rm -rf "${TEST_DIR}"/check.sts
if $showme
then
@@ -197,8 +198,8 @@ END { if (NR > 0) {
needwrap=false
fi
- rm -f /tmp/*.out /tmp/*.err /tmp/*.time
- rm -f /tmp/check.pid /tmp/check.sts
+ rm -f "${TEST_DIR}"/*.out "${TEST_DIR}"/*.err "${TEST_DIR}"/*.time
+ rm -f "${TEST_DIR}"/check.pid "${TEST_DIR}"/check.sts
rm -f $tmp.*
}
@@ -208,16 +209,16 @@ trap "_wrapup; exit \$status" 0 1 2 3 15
# Save pid of check in a well known place, so that hangcheck can be sure it
# has the right pid (getting the pid from ps output is not reliable enough).
#
-rm -rf /tmp/check.pid
-echo $$ >/tmp/check.pid
+rm -rf "${TEST_DIR}"/check.pid
+echo $$ > "${TEST_DIR}"/check.pid
# for hangcheck ...
# Save the status of check in a well known place, so that hangcheck can be
# sure to know where check is up to (getting test number from ps output is
# not reliable enough since the trace stuff has been introduced).
#
-rm -rf /tmp/check.sts
-echo "preamble" >/tmp/check.sts
+rm -rf "${TEST_DIR}"/check.sts
+echo "preamble" > "${TEST_DIR}"/check.sts
# don't leave old full output behind on a clean run
rm -f check.full
@@ -231,10 +232,10 @@ FULL_HOST_DETAILS=`_full_platform_details`
#FULL_MOUNT_OPTIONS=`_scratch_mount_options`
cat <<EOF
-QEMU -- $QEMU
-QEMU_IMG -- $QEMU_IMG
-QEMU_IO -- $QEMU_IO
-QEMU_NBD -- $QEMU_NBD
+QEMU -- "$QEMU_PROG" $QEMU_OPTIONS
+QEMU_IMG -- "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS
+QEMU_IO -- "$QEMU_IO_PROG" $QEMU_IO_OPTIONS
+QEMU_NBD -- "$QEMU_NBD_PROG" $QEMU_NBD_OPTIONS
IMGFMT -- $FULL_IMGFMT_DETAILS
IMGPROTO -- $FULL_IMGPROTO_DETAILS
PLATFORM -- $FULL_HOST_DETAILS
@@ -285,7 +286,7 @@ do
rm -f core $seq.notrun
# for hangcheck ...
- echo "$seq" >/tmp/check.sts
+ echo "$seq" > "${TEST_DIR}"/check.sts
start=`_wallclock`
$timestamp && echo -n " ["`date "+%T"`"]"
@@ -330,6 +331,11 @@ do
fi
reference="$source_iotests/$seq.out"
+ reference_machine="$source_iotests/$seq.$QEMU_DEFAULT_MACHINE.out"
+ if [ -f "$reference_machine" ]; then
+ reference="$reference_machine"
+ fi
+
if [ "$CACHEMODE" = "none" ]; then
[ -f "$source_iotests/$seq.out.nocache" ] && reference="$source_iotests/$seq.out.nocache"
fi
diff --git a/qemu/tests/qemu-iotests/common b/qemu/tests/qemu-iotests/common
index 1030aaf25..49e193112 100644
--- a/qemu/tests/qemu-iotests/common
+++ b/qemu/tests/qemu-iotests/common
@@ -41,7 +41,6 @@ sortme=false
expunge=true
have_test_arg=false
randomize=false
-valgrind=false
cachemode=false
rm -f $tmp.list $tmp.tmp $tmp.sed
@@ -52,6 +51,8 @@ export IMGOPTS=""
export CACHEMODE="writeback"
export QEMU_IO_OPTIONS=""
export CACHEMODE_IS_DEFAULT=true
+export QEMU_OPTIONS="-nodefaults"
+export VALGRIND_QEMU=
for r
do
@@ -154,6 +155,7 @@ check options
-ssh test ssh
-nfs test nfs
-archipelago test archipelago
+ -luks test luks
-xdiff graphical mode diff
-nocache use O_DIRECT on backing file
-misalign misalign memory allocations
@@ -277,7 +279,7 @@ testlist options
;;
-valgrind)
- valgrind=true
+ VALGRIND_QEMU='y'
xpand=false
;;
@@ -435,8 +437,3 @@ fi
if [ "$IMGPROTO" = "nbd" ] ; then
[ "$QEMU_NBD" = "" ] && _fatal "qemu-nbd not found"
fi
-
-if $valgrind; then
- export REAL_QEMU_IO="$QEMU_IO_PROG"
- export QEMU_IO_PROG=valgrind_qemu_io
-fi
diff --git a/qemu/tests/qemu-iotests/common.config b/qemu/tests/qemu-iotests/common.config
index a1973ad9d..f824651ba 100644
--- a/qemu/tests/qemu-iotests/common.config
+++ b/qemu/tests/qemu-iotests/common.config
@@ -44,6 +44,8 @@ export HOST_OPTIONS=${HOST_OPTIONS:=local.config}
export CHECK_OPTIONS=${CHECK_OPTIONS:="-g auto"}
export PWD=`pwd`
+export _QEMU_HANDLE=0
+
# $1 = prog to look for, $2* = default pathnames if not found in $PATH
set_prog_path()
{
@@ -103,10 +105,63 @@ if [ -z "$QEMU_NBD_PROG" ]; then
export QEMU_NBD_PROG="`set_prog_path qemu-nbd`"
fi
-export QEMU=$QEMU_PROG
-export QEMU_IMG=$QEMU_IMG_PROG
-export QEMU_IO="$QEMU_IO_PROG $QEMU_IO_OPTIONS"
-export QEMU_NBD=$QEMU_NBD_PROG
+_qemu_wrapper()
+{
+ (
+ if [ -n "${QEMU_NEED_PID}" ]; then
+ echo $BASHPID > "${TEST_DIR}/qemu-${_QEMU_HANDLE}.pid"
+ fi
+ exec "$QEMU_PROG" $QEMU_OPTIONS "$@"
+ )
+}
+
+_qemu_img_wrapper()
+{
+ (exec "$QEMU_IMG_PROG" $QEMU_IMG_OPTIONS "$@")
+}
+
+_qemu_io_wrapper()
+{
+ local VALGRIND_LOGFILE="${TEST_DIR}"/$$.valgrind
+ local RETVAL
+ (
+ if [ "${VALGRIND_QEMU}" == "y" ]; then
+ exec valgrind --log-file="${VALGRIND_LOGFILE}" --error-exitcode=99 "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"
+ else
+ exec "$QEMU_IO_PROG" $QEMU_IO_OPTIONS "$@"
+ fi
+ )
+ RETVAL=$?
+ if [ "${VALGRIND_QEMU}" == "y" ]; then
+ if [ $RETVAL == 99 ]; then
+ cat "${VALGRIND_LOGFILE}"
+ fi
+ rm -f "${VALGRIND_LOGFILE}"
+ fi
+ (exit $RETVAL)
+}
+
+_qemu_nbd_wrapper()
+{
+ (
+ echo $BASHPID > "${TEST_DIR}/qemu-nbd.pid"
+ exec "$QEMU_NBD_PROG" $QEMU_NBD_OPTIONS "$@"
+ )
+}
+
+export QEMU=_qemu_wrapper
+export QEMU_IMG=_qemu_img_wrapper
+export QEMU_IO=_qemu_io_wrapper
+export QEMU_NBD=_qemu_nbd_wrapper
+
+default_machine=$($QEMU -machine help | sed -n '/(default)/ s/ .*//p')
+default_alias_machine=$($QEMU -machine help | \
+ sed -n "/(alias of $default_machine)/ { s/ .*//p; q; }")
+if [[ "$default_alias_machine" ]]; then
+ default_machine="$default_alias_machine"
+fi
+
+export QEMU_DEFAULT_MACHINE="$default_machine"
[ -f /etc/qemu-iotest.config ] && . /etc/qemu-iotest.config
diff --git a/qemu/tests/qemu-iotests/common.filter b/qemu/tests/qemu-iotests/common.filter
index 012a8122d..8a6e1b57c 100644
--- a/qemu/tests/qemu-iotests/common.filter
+++ b/qemu/tests/qemu-iotests/common.filter
@@ -19,107 +19,6 @@
# standard filters
#
-# Checks that given_value is in range of correct_value +/- tolerance.
-# Tolerance can be an absolute value or a percentage of the correct value
-# (see examples with tolerances below).
-# Outputs suitable message to stdout if it's not in range.
-#
-# A verbose option, -v, may be used as the LAST argument
-#
-# e.g.
-# foo: 0.0298 = 0.03 +/- 5%
-# _within_tolerance "foo" 0.0298 0.03 5%
-#
-# foo: 0.0298 = 0.03 +/- 0.01
-# _within_tolerance "foo" 0.0298 0.03 0.01
-#
-# foo: 0.0298 = 0.03 -0.01 +0.002
-# _within_tolerance "foo" 0.0298 0.03 0.01 0.002
-#
-# foo: verbose output of 0.0298 = 0.03 +/- 5%
-# _within_tolerance "foo" 0.0298 0.03 5% -v
-_within_tolerance()
-{
- _name=$1
- _given_val=$2
- _correct_val=$3
- _mintol=$4
- _maxtol=$_mintol
- _verbose=0
- _debug=false
-
- # maxtol arg is optional
- # verbose arg is optional
- if [ $# -ge 5 ]
- then
- if [ "$5" = "-v" ]
- then
- _verbose=1
- else
- _maxtol=$5
- fi
- fi
- if [ $# -ge 6 ]
- then
- [ "$6" = "-v" ] && _verbose=1
- fi
-
- # find min with or without %
- _mintolerance=`echo $_mintol | sed -e 's/%//'`
- if [ $_mintol = $_mintolerance ]
- then
- _min=`echo "scale=5; $_correct_val-$_mintolerance" | bc`
- else
- _min=`echo "scale=5; $_correct_val-$_mintolerance*0.01*$_correct_val" | bc`
- fi
-
- # find max with or without %
- _maxtolerance=`echo $_maxtol | sed -e 's/%//'`
- if [ $_maxtol = $_maxtolerance ]
- then
- _max=`echo "scale=5; $_correct_val+$_maxtolerance" | bc`
- else
- _max=`echo "scale=5; $_correct_val+$_maxtolerance*0.01*$_correct_val" | bc`
- fi
-
- $_debug && echo "min = $_min"
- $_debug && echo "max = $_max"
-
- cat <<EOF >$tmp.bc.1
-scale=5;
-if ($_min <= $_given_val) 1;
-if ($_min > $_given_val) 0;
-EOF
-
- cat <<EOF >$tmp.bc.2
-scale=5;
-if ($_given_val <= $_max) 1;
-if ($_given_val > $_max) 0;
-EOF
-
- _above_min=`bc <$tmp.bc.1`
- _below_max=`bc <$tmp.bc.2`
-
- rm -f $tmp.bc.[12]
-
- _in_range=`expr $_above_min \& $_below_max`
-
- # fix up min, max precision for output
- # can vary for 5.3, 6.2
- _min=`echo $_min | sed -e 's/0*$//'` # get rid of trailling zeroes
- _max=`echo $_max | sed -e 's/0*$//'` # get rid of trailling zeroes
-
- if [ $_in_range -eq 1 ]
- then
- [ $_verbose -eq 1 ] && echo $_name is in range
- return 0
- else
- [ $_verbose -eq 1 ] && echo $_name has value of $_given_val
- [ $_verbose -eq 1 ] && echo $_name is NOT in range $_min .. $_max
- return 1
- fi
-}
-
# ctime(3) dates
#
_filter_date()
@@ -128,6 +27,11 @@ _filter_date()
-e 's/[A-Z][a-z][a-z] [A-z][a-z][a-z] *[0-9][0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9] [0-9][0-9][0-9][0-9]$/DATE/'
}
+_filter_generated_node_ids()
+{
+ sed -re 's/\#block[0-9]{3,}/NODE_NAME/'
+}
+
# replace occurrences of the actual TEST_DIR value with TEST_DIR
_filter_testdir()
{
@@ -182,7 +86,7 @@ _filter_img_create()
-e "s# encryption=off##g" \
-e "s# cluster_size=[0-9]\\+##g" \
-e "s# table_size=[0-9]\\+##g" \
- -e "s# compat='[^']*'##g" \
+ -e "s# compat=[^ ]*##g" \
-e "s# compat6=\\(on\\|off\\)##g" \
-e "s# static=\\(on\\|off\\)##g" \
-e "s# zeroed_grain=\\(on\\|off\\)##g" \
@@ -225,5 +129,18 @@ _filter_qemu_img_map()
-e 's/Mapped to *//' | _filter_testdir | _filter_imgfmt
}
+_filter_nbd()
+{
+ # nbd.c error messages contain function names and line numbers that are
+ # prone to change. Message ordering depends on timing between send and
+ # receive callbacks sometimes, making them unreliable.
+ #
+ # Filter out the TCP port number since this changes between runs.
+ sed -e '/nbd\/.*\.c:/d' \
+ -e 's#nbd:\(//\)\?127\.0\.0\.1:[0-9]*#nbd:\1127.0.0.1:PORT#g' \
+ -e "s#?socket=$TEST_DIR#?socket=TEST_DIR#g" \
+ -e 's#\(exportname=foo\|PORT\): Failed to .*$#\1#'
+}
+
# make sure this script returns success
true
diff --git a/qemu/tests/qemu-iotests/common.qemu b/qemu/tests/qemu-iotests/common.qemu
index 4e1996c3e..2548a8700 100644
--- a/qemu/tests/qemu-iotests/common.qemu
+++ b/qemu/tests/qemu-iotests/common.qemu
@@ -30,8 +30,6 @@ QEMU_COMM_TIMEOUT=10
QEMU_FIFO_IN="${TEST_DIR}/qmp-in-$$"
QEMU_FIFO_OUT="${TEST_DIR}/qmp-out-$$"
-QEMU_PID=
-_QEMU_HANDLE=0
QEMU_HANDLE=0
# If bash version is >= 4.1, these will be overwritten and dynamic
@@ -131,6 +129,8 @@ function _send_qemu_cmd()
# $qemu_comm_method: set this variable to 'monitor' (case insensitive)
# to use the QEMU HMP monitor for communication.
# Otherwise, the default of QMP is used.
+# $keep_stderr: Set this variable to 'y' to keep QEMU's stderr output on stderr.
+# If this variable is empty, stderr will be redirected to stdout.
# Returns:
# $QEMU_HANDLE: set to a handle value to communicate with this QEMU instance.
#
@@ -153,11 +153,20 @@ function _launch_qemu()
mkfifo "${fifo_out}"
mkfifo "${fifo_in}"
- "${QEMU}" -nographic -serial none ${comm} -machine accel=qtest "${@}" \
+ if [ -z "$keep_stderr" ]; then
+ QEMU_NEED_PID='y'\
+ ${QEMU} -nographic -serial none ${comm} -machine accel=qtest "${@}" \
>"${fifo_out}" \
2>&1 \
<"${fifo_in}" &
- QEMU_PID[${_QEMU_HANDLE}]=$!
+ elif [ "$keep_stderr" = "y" ]; then
+ QEMU_NEED_PID='y'\
+ ${QEMU} -nographic -serial none ${comm} -machine accel=qtest "${@}" \
+ >"${fifo_out}" \
+ <"${fifo_in}" &
+ else
+ exit 1
+ fi
if [[ "${BASH_VERSINFO[0]}" -ge "5" ||
("${BASH_VERSINFO[0]}" -ge "4" && "${BASH_VERSINFO[1]}" -ge "1") ]]
@@ -196,10 +205,18 @@ function _cleanup_qemu()
# QEMU_PID[], QEMU_IN[], QEMU_OUT[] all use same indices
for i in "${!QEMU_OUT[@]}"
do
- if [ -z "${wait}" ]; then
- kill -KILL ${QEMU_PID[$i]} 2>/dev/null
+ local QEMU_PID
+ if [ -f "${TEST_DIR}/qemu-${i}.pid" ]; then
+ read QEMU_PID < "${TEST_DIR}/qemu-${i}.pid"
+ rm -f "${TEST_DIR}/qemu-${i}.pid"
+ if [ -z "${wait}" ] && [ -n "${QEMU_PID}" ]; then
+ kill -KILL ${QEMU_PID} 2>/dev/null
+ fi
+ if [ -n "${QEMU_PID}" ]; then
+ wait ${QEMU_PID} 2>/dev/null # silent kill
+ fi
fi
- wait ${QEMU_PID[$i]} 2>/dev/null # silent kill
+
if [ -n "${wait}" ]; then
cat <&${QEMU_OUT[$i]} | _filter_testdir | _filter_qemu \
| _filter_qemu_io | _filter_qmp
diff --git a/qemu/tests/qemu-iotests/common.rc b/qemu/tests/qemu-iotests/common.rc
index 22d351404..5249ec592 100644
--- a/qemu/tests/qemu-iotests/common.rc
+++ b/qemu/tests/qemu-iotests/common.rc
@@ -70,16 +70,6 @@ else
TEST_IMG=$IMGPROTO:$TEST_DIR/t.$IMGFMT
fi
-function valgrind_qemu_io()
-{
- valgrind --log-file=/tmp/$$.valgrind --error-exitcode=99 $REAL_QEMU_IO "$@"
- if [ $? != 0 ]; then
- cat /tmp/$$.valgrind
- fi
- rm -f /tmp/$$.valgrind
-}
-
-
_optstr_add()
{
if [ -n "$1" ]; then
@@ -154,7 +144,6 @@ _make_test_img()
# Start an NBD server on the image file, which is what we'll be talking to
if [ $IMGPROTO = "nbd" ]; then
eval "$QEMU_NBD -v -t -b 127.0.0.1 -p 10810 -f $IMGFMT $TEST_IMG_FILE &"
- QEMU_NBD_PID=$!
sleep 1 # FIXME: qemu-nbd needs to be listening before we continue
fi
}
@@ -175,8 +164,11 @@ _cleanup_test_img()
case "$IMGPROTO" in
nbd)
- if [ -n "$QEMU_NBD_PID" ]; then
- kill $QEMU_NBD_PID
+ if [ -f "${TEST_DIR}/qemu-nbd.pid" ]; then
+ local QEMU_NBD_PID
+ read QEMU_NBD_PID < "${TEST_DIR}/qemu-nbd.pid"
+ kill ${QEMU_NBD_PID}
+ rm -f "${TEST_DIR}/qemu-nbd.pid"
fi
rm -f "$TEST_IMG_FILE"
;;
@@ -295,52 +287,6 @@ _need_to_be_root()
fi
}
-
-# Do a command, log it to $seq.full, optionally test return status
-# and die if command fails. If called with one argument _do executes the
-# command, logs it, and returns its exit status. With two arguments _do
-# first prints the message passed in the first argument, and then "done"
-# or "fail" depending on the return status of the command passed in the
-# second argument. If the command fails and the variable _do_die_on_error
-# is set to "always" or the two argument form is used and _do_die_on_error
-# is set to "message_only" _do will print an error message to
-# $seq.out and exit.
-
-_do()
-{
- if [ $# -eq 1 ]; then
- _cmd=$1
- elif [ $# -eq 2 ]; then
- _note=$1
- _cmd=$2
- echo -n "$_note... "
- else
- echo "Usage: _do [note] cmd" 1>&2
- status=1; exit
- fi
-
- (eval "echo '---' \"$_cmd\"") >>"$OUTPUT_DIR/$seq.full"
- (eval "$_cmd") >$tmp._out 2>&1; ret=$?
- cat $tmp._out >>"$OUTPUT_DIR/$seq.full"
- if [ $# -eq 2 ]; then
- if [ $ret -eq 0 ]; then
- echo "done"
- else
- echo "fail"
- fi
- fi
- if [ $ret -ne 0 ] \
- && [ "$_do_die_on_error" = "always" \
- -o \( $# -eq 2 -a "$_do_die_on_error" = "message_only" \) ]
- then
- [ $# -ne 2 ] && echo
- eval "echo \"$_cmd\" failed \(returned $ret\): see $seq.full"
- status=1; exit
- fi
-
- return $ret
-}
-
# bail out, setting up .notrun file
#
_notrun()
@@ -439,7 +385,17 @@ _unsupported_imgopts()
#
_require_command()
{
- eval c=\$$1
+ if [ "$1" = "QEMU" ]; then
+ c=$QEMU_PROG
+ elif [ "$1" = "QEMU_IMG" ]; then
+ c=$QEMU_IMG_PROG
+ elif [ "$1" = "QEMU_IO" ]; then
+ c=$QEMU_IO_PROG
+ elif [ "$1" = "QEMU_NBD" ]; then
+ c=$QEMU_NBD_PROG
+ else
+ eval c=\$$1
+ fi
[ -x "$c" ] || _notrun "$1 utility required, skipped this test"
}
diff --git a/qemu/tests/qemu-iotests/group b/qemu/tests/qemu-iotests/group
index c430b6c23..822953b6f 100644
--- a/qemu/tests/qemu-iotests/group
+++ b/qemu/tests/qemu-iotests/group
@@ -102,6 +102,7 @@
093 auto
094 rw auto quick
095 rw auto quick
+096 rw auto quick
097 rw auto backing
098 rw auto backing quick
099 rw auto quick
@@ -121,6 +122,8 @@
114 rw auto quick
115 rw auto
116 rw auto quick
+117 rw auto
+118 rw auto
119 rw auto quick
120 rw auto quick
121 rw auto
@@ -132,5 +135,21 @@
130 rw auto quick
131 rw auto quick
132 rw auto quick
+133 auto quick
134 rw auto quick
135 rw auto
+136 rw auto
+137 rw auto
+138 rw auto quick
+139 rw auto quick
+140 rw auto quick
+141 rw auto quick
+142 auto
+143 auto quick
+144 rw auto quick
+145 auto quick
+146 auto quick
+148 rw auto quick
+149 rw auto sudo
+150 rw auto quick
+152 rw auto quick
diff --git a/qemu/tests/qemu-iotests/iotests.py b/qemu/tests/qemu-iotests/iotests.py
index 8615b1075..56f988ab3 100644
--- a/qemu/tests/qemu-iotests/iotests.py
+++ b/qemu/tests/qemu-iotests/iotests.py
@@ -16,6 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+import errno
import os
import re
import subprocess
@@ -27,41 +28,66 @@ sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'scripts', '
import qmp
import qtest
import struct
+import json
-__all__ = ['imgfmt', 'imgproto', 'test_dir' 'qemu_img', 'qemu_io',
- 'VM', 'QMPTestCase', 'notrun', 'main']
-# This will not work if arguments or path contain spaces but is necessary if we
+# This will not work if arguments contain spaces but is necessary if we
# want to support the override options that ./check supports.
-qemu_img_args = os.environ.get('QEMU_IMG', 'qemu-img').strip().split(' ')
-qemu_io_args = os.environ.get('QEMU_IO', 'qemu-io').strip().split(' ')
-qemu_args = os.environ.get('QEMU', 'qemu').strip().split(' ')
+qemu_img_args = [os.environ.get('QEMU_IMG_PROG', 'qemu-img')]
+if os.environ.get('QEMU_IMG_OPTIONS'):
+ qemu_img_args += os.environ['QEMU_IMG_OPTIONS'].strip().split(' ')
+
+qemu_io_args = [os.environ.get('QEMU_IO_PROG', 'qemu-io')]
+if os.environ.get('QEMU_IO_OPTIONS'):
+ qemu_io_args += os.environ['QEMU_IO_OPTIONS'].strip().split(' ')
+
+qemu_args = [os.environ.get('QEMU_PROG', 'qemu')]
+if os.environ.get('QEMU_OPTIONS'):
+ qemu_args += os.environ['QEMU_OPTIONS'].strip().split(' ')
imgfmt = os.environ.get('IMGFMT', 'raw')
imgproto = os.environ.get('IMGPROTO', 'file')
test_dir = os.environ.get('TEST_DIR', '/var/tmp')
output_dir = os.environ.get('OUTPUT_DIR', '.')
cachemode = os.environ.get('CACHEMODE')
+qemu_default_machine = os.environ.get('QEMU_DEFAULT_MACHINE')
socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
def qemu_img(*args):
'''Run qemu-img and return the exit code'''
devnull = open('/dev/null', 'r+')
- return subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull)
+ exitcode = subprocess.call(qemu_img_args + list(args), stdin=devnull, stdout=devnull)
+ if exitcode < 0:
+ sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
+ return exitcode
def qemu_img_verbose(*args):
'''Run qemu-img without suppressing its output and return the exit code'''
- return subprocess.call(qemu_img_args + list(args))
+ exitcode = subprocess.call(qemu_img_args + list(args))
+ if exitcode < 0:
+ sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
+ return exitcode
def qemu_img_pipe(*args):
'''Run qemu-img and return its output'''
- return subprocess.Popen(qemu_img_args + list(args), stdout=subprocess.PIPE).communicate()[0]
+ subp = subprocess.Popen(qemu_img_args + list(args),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ exitcode = subp.wait()
+ if exitcode < 0:
+ sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args))))
+ return subp.communicate()[0]
def qemu_io(*args):
'''Run qemu-io and return the stdout data'''
args = qemu_io_args + list(args)
- return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
+ subp = subprocess.Popen(args, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ exitcode = subp.wait()
+ if exitcode < 0:
+ sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args)))
+ return subp.communicate()[0]
def compare_images(img1, img2):
'''Return True if two image files are identical'''
@@ -78,6 +104,33 @@ def create_image(name, size):
i = i + 512
file.close()
+def image_size(img):
+ '''Return image's virtual size'''
+ r = qemu_img_pipe('info', '--output=json', '-f', imgfmt, img)
+ return json.loads(r)['virtual-size']
+
+test_dir_re = re.compile(r"%s" % test_dir)
+def filter_test_dir(msg):
+ return test_dir_re.sub("TEST_DIR", msg)
+
+win32_re = re.compile(r"\r")
+def filter_win32(msg):
+ return win32_re.sub("", msg)
+
+qemu_io_re = re.compile(r"[0-9]* ops; [0-9\/:. sec]* \([0-9\/.inf]* [EPTGMKiBbytes]*\/sec and [0-9\/.inf]* ops\/sec\)")
+def filter_qemu_io(msg):
+ msg = filter_win32(msg)
+ return qemu_io_re.sub("X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)", msg)
+
+chown_re = re.compile(r"chown [0-9]+:[0-9]+")
+def filter_chown(msg):
+ return chown_re.sub("chown UID:GID", msg)
+
+def log(msg, filters=[]):
+ for flt in filters:
+ msg = flt(msg)
+ print msg
+
# Test if 'match' is a recursive subset of 'event'
def event_match(event, match=None):
if match is None:
@@ -117,13 +170,21 @@ class VM(object):
self._args.append('-monitor')
self._args.append(args)
- def add_drive(self, path, opts=''):
+ def add_drive_raw(self, opts):
+ self._args.append('-drive')
+ self._args.append(opts)
+ return self
+
+ def add_drive(self, path, opts='', interface='virtio'):
'''Add a virtio-blk drive to the VM'''
- options = ['if=virtio',
- 'format=%s' % imgfmt,
- 'cache=%s' % cachemode,
- 'file=%s' % path,
+ options = ['if=%s' % interface,
'id=drive%d' % self._num_drives]
+
+ if path is not None:
+ options.append('file=%s' % path)
+ options.append('format=%s' % imgfmt)
+ options.append('cache=%s' % cachemode)
+
if opts:
options.append(opts)
@@ -189,14 +250,17 @@ class VM(object):
self._qmp.accept()
self._qtest.accept()
except:
- os.remove(self._monitor_path)
+ _remove_if_exists(self._monitor_path)
+ _remove_if_exists(self._qtest_path)
raise
def shutdown(self):
'''Terminate the VM and clean up'''
if not self._popen is None:
self._qmp.cmd('quit')
- self._popen.wait()
+ exitcode = self._popen.wait()
+ if exitcode < 0:
+ sys.stderr.write('qemu received signal %i: %s\n' % (-exitcode, ' '.join(self._args)))
os.remove(self._monitor_path)
os.remove(self._qtest_path)
os.remove(self._qemu_log_path)
@@ -290,6 +354,20 @@ class QMPTestCase(unittest.TestCase):
result = self.vm.qmp('query-block-jobs')
self.assert_qmp(result, 'return', [])
+ def assert_has_block_node(self, node_name=None, file_name=None):
+ """Issue a query-named-block-nodes and assert node_name and/or
+ file_name is present in the result"""
+ def check_equal_or_none(a, b):
+ return a == None or b == None or a == b
+ assert node_name or file_name
+ result = self.vm.qmp('query-named-block-nodes')
+ for x in result["return"]:
+ if check_equal_or_none(x.get("node-name"), node_name) and \
+ check_equal_or_none(x.get("file"), file_name):
+ return
+ self.assertTrue(False, "Cannot find %s %s in result:\n%s" % \
+ (node_name, file_name, result))
+
def cancel_and_wait(self, drive='drive0', force=False, resume=False):
'''Cancel a block job and wait for it to finish, returning the event'''
result = self.vm.qmp('block-job-cancel', device=drive, force=force)
@@ -349,6 +427,15 @@ class QMPTestCase(unittest.TestCase):
event = self.wait_until_completed(drive=drive)
self.assert_qmp(event, 'data/type', 'mirror')
+def _remove_if_exists(path):
+ '''Remove file object at path if it exists'''
+ try:
+ os.remove(path)
+ except OSError as exception:
+ if exception.errno == errno.ENOENT:
+ return
+ raise
+
def notrun(reason):
'''Skip this test suite'''
# Each test in qemu-iotests has a number ("seq")
@@ -358,17 +445,27 @@ def notrun(reason):
print '%s not run: %s' % (seq, reason)
sys.exit(0)
-def main(supported_fmts=[], supported_oses=['linux']):
- '''Run tests'''
-
- debug = '-d' in sys.argv
- verbosity = 1
+def verify_image_format(supported_fmts=[]):
if supported_fmts and (imgfmt not in supported_fmts):
notrun('not suitable for this image format: %s' % imgfmt)
+def verify_platform(supported_oses=['linux']):
if True not in [sys.platform.startswith(x) for x in supported_oses]:
notrun('not suitable for this OS: %s' % sys.platform)
+def verify_quorum():
+ '''Skip test suite if quorum support is not available'''
+ if 'quorum' not in qemu_img_pipe('--help'):
+ notrun('quorum support missing')
+
+def main(supported_fmts=[], supported_oses=['linux']):
+ '''Run tests'''
+
+ debug = '-d' in sys.argv
+ verbosity = 1
+ verify_image_format(supported_fmts)
+ verify_platform(supported_oses)
+
# We need to filter out the time taken from the output so that qemu-iotest
# can reliably diff the results against master output.
import StringIO
diff --git a/qemu/tests/qemu-iotests/qed.py b/qemu/tests/qemu-iotests/qed.py
index 52ff84559..748068d7f 100755
--- a/qemu/tests/qemu-iotests/qed.py
+++ b/qemu/tests/qemu-iotests/qed.py
@@ -227,7 +227,7 @@ def main():
qed = QED(open(filename, 'r+b'))
try:
globals()[cmd](qed, *sys.argv[3:])
- except TypeError, e:
+ except TypeError as e:
sys.stderr.write(globals()[cmd].__doc__ + '\n')
sys.exit(1)
diff --git a/qemu/tests/qemu-iotests/sample_images/d2v-zerofilled.vhd.bz2 b/qemu/tests/qemu-iotests/sample_images/d2v-zerofilled.vhd.bz2
new file mode 100644
index 000000000..f12cb9203
--- /dev/null
+++ b/qemu/tests/qemu-iotests/sample_images/d2v-zerofilled.vhd.bz2
Binary files differ
diff --git a/qemu/tests/qemu-iotests/sample_images/hyperv2012r2-dynamic.vhd.bz2 b/qemu/tests/qemu-iotests/sample_images/hyperv2012r2-dynamic.vhd.bz2
new file mode 100644
index 000000000..bfeccf7b9
--- /dev/null
+++ b/qemu/tests/qemu-iotests/sample_images/hyperv2012r2-dynamic.vhd.bz2
Binary files differ
diff --git a/qemu/tests/qemu-iotests/sample_images/virtualpc-dynamic.vhd.bz2 b/qemu/tests/qemu-iotests/sample_images/virtualpc-dynamic.vhd.bz2
new file mode 100644
index 000000000..783be3c8f
--- /dev/null
+++ b/qemu/tests/qemu-iotests/sample_images/virtualpc-dynamic.vhd.bz2
Binary files differ
diff --git a/qemu/tests/qemu-iotests/socket_scm_helper.c b/qemu/tests/qemu-iotests/socket_scm_helper.c
index 81959835e..80cadf43b 100644
--- a/qemu/tests/qemu-iotests/socket_scm_helper.c
+++ b/qemu/tests/qemu-iotests/socket_scm_helper.c
@@ -10,15 +10,9 @@
* See the COPYING.LIB file in the top-level directory.
*/
-#include <stdio.h>
-#include <errno.h>
+#include "qemu/osdep.h"
#include <sys/socket.h>
#include <sys/un.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
/* #define SOCKET_SCM_DEBUG */
diff --git a/qemu/tests/qom-test.c b/qemu/tests/qom-test.c
index fde04e7a1..bd5cdde26 100644
--- a/qemu/tests/qom-test.c
+++ b/qemu/tests/qom-test.c
@@ -7,12 +7,12 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "qemu-common.h"
+#include "qemu/cutils.h"
#include "libqtest.h"
-#include "qemu/osdep.h"
#include "qapi/qmp/types.h"
static const char *blacklist_x86[] = {
@@ -47,7 +47,7 @@ static bool is_blacklisted(const char *arch, const char *mach)
static void test_properties(const char *path, bool recurse)
{
char *child_path;
- QDict *response, *tuple;
+ QDict *response, *tuple, *tmp;
QList *list;
QListEntry *entry;
@@ -57,6 +57,7 @@ static void test_properties(const char *path, bool recurse)
g_assert(response);
if (!recurse) {
+ QDECREF(response);
return;
}
@@ -75,14 +76,16 @@ static void test_properties(const char *path, bool recurse)
} else {
const char *prop = qdict_get_str(tuple, "name");
g_test_message("Testing property %s.%s", path, prop);
- response = qmp("{ 'execute': 'qom-get',"
- " 'arguments': { 'path': %s,"
- " 'property': %s } }",
- path, prop);
+ tmp = qmp("{ 'execute': 'qom-get',"
+ " 'arguments': { 'path': %s,"
+ " 'property': %s } }",
+ path, prop);
/* qom-get may fail but should not, e.g., segfault. */
- g_assert(response);
+ g_assert(tmp);
+ QDECREF(tmp);
}
}
+ QDECREF(response);
}
static void test_machine(gconstpointer data)
@@ -98,9 +101,11 @@ static void test_machine(gconstpointer data)
response = qmp("{ 'execute': 'quit' }");
g_assert(qdict_haskey(response, "return"));
+ QDECREF(response);
qtest_end();
g_free(args);
+ g_free((void *)machine);
}
static void add_machine_test_cases(void)
@@ -129,10 +134,12 @@ static void add_machine_test_cases(void)
mname = qstring_get_str(qstr);
if (!is_blacklisted(arch, mname)) {
path = g_strdup_printf("qom/%s", mname);
- qtest_add_data_func(path, mname, test_machine);
+ qtest_add_data_func(path, g_strdup(mname), test_machine);
}
}
+
qtest_end();
+ QDECREF(response);
}
int main(int argc, char **argv)
diff --git a/qemu/tests/rcutorture.c b/qemu/tests/rcutorture.c
index d6b304d00..244f0f28b 100644
--- a/qemu/tests/rcutorture.c
+++ b/qemu/tests/rcutorture.c
@@ -60,13 +60,10 @@
* Test variables.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
#include "qemu/atomic.h"
#include "qemu/rcu.h"
-#include "qemu/compiler.h"
#include "qemu/thread.h"
long long n_reads = 0LL;
diff --git a/qemu/tests/rtc-test.c b/qemu/tests/rtc-test.c
index 4243624de..fa7029aa8 100644
--- a/qemu/tests/rtc-test.c
+++ b/qemu/tests/rtc-test.c
@@ -11,11 +11,8 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
#include "libqtest.h"
#include "hw/timer/mc146818rtc_regs.h"
diff --git a/qemu/tests/rtl8139-test.c b/qemu/tests/rtl8139-test.c
index e749be38e..54e5aa7d0 100644
--- a/qemu/tests/rtl8139-test.c
+++ b/qemu/tests/rtl8139-test.c
@@ -7,11 +7,10 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
#include "libqos/pci-pc.h"
-#include "qemu/osdep.h"
#include "qemu/timer.h"
#include "qemu-common.h"
@@ -20,7 +19,7 @@ static void nop(void)
{
}
-#define CLK 33000000
+#define CLK 33333333
static QPCIBus *pcibus;
static QPCIDevice *dev;
diff --git a/qemu/tests/spapr-phb-test.c b/qemu/tests/spapr-phb-test.c
index b629de475..f53911d9f 100644
--- a/qemu/tests/spapr-phb-test.c
+++ b/qemu/tests/spapr-phb-test.c
@@ -7,6 +7,7 @@
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqtest.h"
diff --git a/qemu/tests/tcg/linux-test.c b/qemu/tests/tcg/linux-test.c
index 1c6c01318..5070d3144 100644
--- a/qemu/tests/tcg/linux-test.c
+++ b/qemu/tests/tcg/linux-test.c
@@ -39,6 +39,7 @@
#include <dirent.h>
#include <setjmp.h>
#include <sys/shm.h>
+#include "qemu/cutils.h"
#define TESTPATH "/tmp/linux-test.tmp"
#define TESTPORT 7654
diff --git a/qemu/tests/tcg/test-i386-fprem.c b/qemu/tests/tcg/test-i386-fprem.c
index e91fb1ae9..1a7162320 100644
--- a/qemu/tests/tcg/test-i386-fprem.c
+++ b/qemu/tests/tcg/test-i386-fprem.c
@@ -22,10 +22,8 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "qemu/compiler.h"
+
#include "qemu/osdep.h"
-#include <stdio.h>
-#include <inttypes.h>
/*
* Inspired by <ieee754.h>'s union ieee854_long_double, but with single
diff --git a/qemu/tests/tcg/testthread.c b/qemu/tests/tcg/testthread.c
index 2679af119..810ba5de6 100644
--- a/qemu/tests/tcg/testthread.c
+++ b/qemu/tests/tcg/testthread.c
@@ -2,7 +2,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-#include <signal.h>
#include <unistd.h>
#include <inttypes.h>
#include <pthread.h>
diff --git a/qemu/tests/tco-test.c b/qemu/tests/tco-test.c
index 419f7cf46..ac11175e9 100644
--- a/qemu/tests/tco-test.c
+++ b/qemu/tests/tco-test.c
@@ -6,10 +6,8 @@
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
#include "libqtest.h"
#include "libqos/pci.h"
diff --git a/qemu/tests/test-aio.c b/qemu/tests/test-aio.c
index 217e33772..687dfa062 100644
--- a/qemu/tests/test-aio.c
+++ b/qemu/tests/test-aio.c
@@ -10,8 +10,10 @@
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "block/aio.h"
+#include "qapi/error.h"
#include "qemu/timer.h"
#include "qemu/sockets.h"
#include "qemu/error-report.h"
@@ -118,6 +120,12 @@ static void *test_acquire_thread(void *opaque)
return NULL;
}
+static void set_event_notifier(AioContext *ctx, EventNotifier *notifier,
+ EventNotifierHandler *handler)
+{
+ aio_set_event_notifier(ctx, notifier, false, handler);
+}
+
static void dummy_notifier_read(EventNotifier *unused)
{
g_assert(false); /* should never be invoked */
@@ -131,7 +139,7 @@ static void test_acquire(void)
/* Dummy event notifier ensures aio_poll() will block */
event_notifier_init(&notifier, false);
- aio_set_event_notifier(ctx, &notifier, dummy_notifier_read);
+ set_event_notifier(ctx, &notifier, dummy_notifier_read);
g_assert(!aio_poll(ctx, false)); /* consume aio_notify() */
qemu_mutex_init(&data.start_lock);
@@ -149,7 +157,7 @@ static void test_acquire(void)
aio_context_release(ctx);
qemu_thread_join(&thread);
- aio_set_event_notifier(ctx, &notifier, NULL);
+ set_event_notifier(ctx, &notifier, NULL);
event_notifier_cleanup(&notifier);
g_assert(data.thread_acquired);
@@ -308,11 +316,11 @@ static void test_set_event_notifier(void)
{
EventNotifierTestData data = { .n = 0, .active = 0 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ set_event_notifier(ctx, &data.e, event_ready_cb);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
- aio_set_event_notifier(ctx, &data.e, NULL);
+ set_event_notifier(ctx, &data.e, NULL);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
event_notifier_cleanup(&data.e);
@@ -322,7 +330,7 @@ static void test_wait_event_notifier(void)
{
EventNotifierTestData data = { .n = 0, .active = 1 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ set_event_notifier(ctx, &data.e, event_ready_cb);
while (aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
g_assert_cmpint(data.active, ==, 1);
@@ -336,7 +344,7 @@ static void test_wait_event_notifier(void)
g_assert_cmpint(data.n, ==, 1);
g_assert_cmpint(data.active, ==, 0);
- aio_set_event_notifier(ctx, &data.e, NULL);
+ set_event_notifier(ctx, &data.e, NULL);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 1);
@@ -347,7 +355,7 @@ static void test_flush_event_notifier(void)
{
EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ set_event_notifier(ctx, &data.e, event_ready_cb);
while (aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
g_assert_cmpint(data.active, ==, 10);
@@ -363,18 +371,42 @@ static void test_flush_event_notifier(void)
g_assert_cmpint(data.active, ==, 0);
g_assert(!aio_poll(ctx, false));
- aio_set_event_notifier(ctx, &data.e, NULL);
+ set_event_notifier(ctx, &data.e, NULL);
g_assert(!aio_poll(ctx, false));
event_notifier_cleanup(&data.e);
}
+static void test_aio_external_client(void)
+{
+ int i, j;
+
+ for (i = 1; i < 3; i++) {
+ EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
+ event_notifier_init(&data.e, false);
+ aio_set_event_notifier(ctx, &data.e, true, event_ready_cb);
+ event_notifier_set(&data.e);
+ for (j = 0; j < i; j++) {
+ aio_disable_external(ctx);
+ }
+ for (j = 0; j < i; j++) {
+ assert(!aio_poll(ctx, false));
+ assert(event_notifier_test_and_clear(&data.e));
+ event_notifier_set(&data.e);
+ aio_enable_external(ctx);
+ }
+ assert(aio_poll(ctx, false));
+ set_event_notifier(ctx, &data.e, NULL);
+ event_notifier_cleanup(&data.e);
+ }
+}
+
static void test_wait_event_notifier_noflush(void)
{
EventNotifierTestData data = { .n = 0 };
EventNotifierTestData dummy = { .n = 0, .active = 1 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ set_event_notifier(ctx, &data.e, event_ready_cb);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 0);
@@ -387,7 +419,7 @@ static void test_wait_event_notifier_noflush(void)
/* An active event notifier forces aio_poll to look at EventNotifiers. */
event_notifier_init(&dummy.e, false);
- aio_set_event_notifier(ctx, &dummy.e, event_ready_cb);
+ set_event_notifier(ctx, &dummy.e, event_ready_cb);
event_notifier_set(&data.e);
g_assert(aio_poll(ctx, false));
@@ -407,10 +439,10 @@ static void test_wait_event_notifier_noflush(void)
g_assert_cmpint(dummy.n, ==, 1);
g_assert_cmpint(dummy.active, ==, 0);
- aio_set_event_notifier(ctx, &dummy.e, NULL);
+ set_event_notifier(ctx, &dummy.e, NULL);
event_notifier_cleanup(&dummy.e);
- aio_set_event_notifier(ctx, &data.e, NULL);
+ set_event_notifier(ctx, &data.e, NULL);
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 2);
@@ -428,7 +460,7 @@ static void test_timer_schedule(void)
* an fd to wait on. Fixing this breaks other tests. So create a dummy one.
*/
event_notifier_init(&e, false);
- aio_set_event_notifier(ctx, &e, dummy_io_handler_read);
+ set_event_notifier(ctx, &e, dummy_io_handler_read);
aio_poll(ctx, false);
aio_timer_init(ctx, &data.timer, data.clock_type,
@@ -467,7 +499,7 @@ static void test_timer_schedule(void)
g_assert(!aio_poll(ctx, false));
g_assert_cmpint(data.n, ==, 2);
- aio_set_event_notifier(ctx, &e, NULL);
+ set_event_notifier(ctx, &e, NULL);
event_notifier_cleanup(&e);
timer_del(&data.timer);
@@ -638,11 +670,11 @@ static void test_source_set_event_notifier(void)
{
EventNotifierTestData data = { .n = 0, .active = 0 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ set_event_notifier(ctx, &data.e, event_ready_cb);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
- aio_set_event_notifier(ctx, &data.e, NULL);
+ set_event_notifier(ctx, &data.e, NULL);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
event_notifier_cleanup(&data.e);
@@ -652,7 +684,7 @@ static void test_source_wait_event_notifier(void)
{
EventNotifierTestData data = { .n = 0, .active = 1 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ set_event_notifier(ctx, &data.e, event_ready_cb);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
g_assert_cmpint(data.active, ==, 1);
@@ -666,7 +698,7 @@ static void test_source_wait_event_notifier(void)
g_assert_cmpint(data.n, ==, 1);
g_assert_cmpint(data.active, ==, 0);
- aio_set_event_notifier(ctx, &data.e, NULL);
+ set_event_notifier(ctx, &data.e, NULL);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 1);
@@ -677,7 +709,7 @@ static void test_source_flush_event_notifier(void)
{
EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ set_event_notifier(ctx, &data.e, event_ready_cb);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
g_assert_cmpint(data.active, ==, 10);
@@ -693,7 +725,7 @@ static void test_source_flush_event_notifier(void)
g_assert_cmpint(data.active, ==, 0);
g_assert(!g_main_context_iteration(NULL, false));
- aio_set_event_notifier(ctx, &data.e, NULL);
+ set_event_notifier(ctx, &data.e, NULL);
while (g_main_context_iteration(NULL, false));
event_notifier_cleanup(&data.e);
}
@@ -704,7 +736,7 @@ static void test_source_wait_event_notifier_noflush(void)
EventNotifierTestData dummy = { .n = 0, .active = 1 };
event_notifier_init(&data.e, false);
- aio_set_event_notifier(ctx, &data.e, event_ready_cb);
+ set_event_notifier(ctx, &data.e, event_ready_cb);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 0);
@@ -717,7 +749,7 @@ static void test_source_wait_event_notifier_noflush(void)
/* An active event notifier forces aio_poll to look at EventNotifiers. */
event_notifier_init(&dummy.e, false);
- aio_set_event_notifier(ctx, &dummy.e, event_ready_cb);
+ set_event_notifier(ctx, &dummy.e, event_ready_cb);
event_notifier_set(&data.e);
g_assert(g_main_context_iteration(NULL, false));
@@ -737,10 +769,10 @@ static void test_source_wait_event_notifier_noflush(void)
g_assert_cmpint(dummy.n, ==, 1);
g_assert_cmpint(dummy.active, ==, 0);
- aio_set_event_notifier(ctx, &dummy.e, NULL);
+ set_event_notifier(ctx, &dummy.e, NULL);
event_notifier_cleanup(&dummy.e);
- aio_set_event_notifier(ctx, &data.e, NULL);
+ set_event_notifier(ctx, &data.e, NULL);
while (g_main_context_iteration(NULL, false));
g_assert_cmpint(data.n, ==, 2);
@@ -759,7 +791,7 @@ static void test_source_timer_schedule(void)
* an fd to wait on. Fixing this breaks other tests. So create a dummy one.
*/
event_notifier_init(&e, false);
- aio_set_event_notifier(ctx, &e, dummy_io_handler_read);
+ set_event_notifier(ctx, &e, dummy_io_handler_read);
do {} while (g_main_context_iteration(NULL, false));
aio_timer_init(ctx, &data.timer, data.clock_type,
@@ -784,7 +816,7 @@ static void test_source_timer_schedule(void)
g_assert_cmpint(data.n, ==, 2);
g_assert(qemu_clock_get_ns(data.clock_type) > expiry);
- aio_set_event_notifier(ctx, &e, NULL);
+ set_event_notifier(ctx, &e, NULL);
event_notifier_cleanup(&e);
timer_del(&data.timer);
@@ -802,9 +834,7 @@ int main(int argc, char **argv)
ctx = aio_context_new(&local_error);
if (!ctx) {
- error_report("Failed to create AIO Context: '%s'",
- error_get_pretty(local_error));
- error_free(local_error);
+ error_reportf_err(local_error, "Failed to create AIO Context: ");
exit(1);
}
src = aio_get_g_source(ctx);
@@ -826,6 +856,7 @@ int main(int argc, char **argv)
g_test_add_func("/aio/event/wait", test_wait_event_notifier);
g_test_add_func("/aio/event/wait/no-flush-cb", test_wait_event_notifier_noflush);
g_test_add_func("/aio/event/flush", test_flush_event_notifier);
+ g_test_add_func("/aio/external-client", test_aio_external_client);
g_test_add_func("/aio/timer/schedule", test_timer_schedule);
g_test_add_func("/aio-gsource/flush", test_source_flush);
diff --git a/qemu/tests/test-base64.c b/qemu/tests/test-base64.c
new file mode 100644
index 000000000..922e839dd
--- /dev/null
+++ b/qemu/tests/test-base64.c
@@ -0,0 +1,110 @@
+/*
+ * QEMU base64 helper test
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+
+#include "qapi/error.h"
+#include "qemu/base64.h"
+
+static void test_base64_good(void)
+{
+ const char input[] =
+ "QmVjYXVzZSB3ZSBmb2N1c2VkIG9uIHRoZSBzbmFrZSwgd2UgbW\n"
+ "lzc2VkIHRoZSBzY29ycGlvbi4=";
+ const char expect[] = "Because we focused on the snake, "
+ "we missed the scorpion.";
+
+ size_t len;
+ uint8_t *actual = qbase64_decode(input,
+ -1,
+ &len,
+ &error_abort);
+
+ g_assert(actual != NULL);
+ g_assert_cmpint(len, ==, strlen(expect));
+ g_assert_cmpstr((char *)actual, ==, expect);
+ g_free(actual);
+}
+
+
+static void test_base64_bad(const char *input,
+ size_t input_len)
+{
+ size_t len;
+ Error *err = NULL;
+ uint8_t *actual = qbase64_decode(input,
+ input_len,
+ &len,
+ &err);
+
+ g_assert(err != NULL);
+ g_assert(actual == NULL);
+ g_assert_cmpint(len, ==, 0);
+ error_free(err);
+}
+
+
+static void test_base64_embedded_nul(void)
+{
+ /* We put a NUL character in the middle of the base64
+ * text which is invalid data, given the expected length */
+ const char input[] =
+ "QmVjYXVzZSB3ZSBmb2N1c2VkIG9uIHRoZSBzbmFrZSwgd2UgbW\0"
+ "lzc2VkIHRoZSBzY29ycGlvbi4=";
+
+ test_base64_bad(input, G_N_ELEMENTS(input) - 1);
+}
+
+
+static void test_base64_not_nul_terminated(void)
+{
+ const char input[] =
+ "QmVjYXVzZSB3ZSBmb2N1c2VkIG9uIHRoZSBzbmFrZSwgd2UgbW\n"
+ "lzc2VkIHRoZSBzY29ycGlvbi4=";
+
+ /* Using '-2' to make us drop the trailing NUL, thus
+ * creating an invalid base64 sequence for decoding */
+ test_base64_bad(input, G_N_ELEMENTS(input) - 2);
+}
+
+
+static void test_base64_invalid_chars(void)
+{
+ /* We put a single quote character in the middle
+ * of the base64 text which is invalid data */
+ const char input[] =
+ "QmVjYXVzZSB3ZSBmb2N1c2VkIG9uIHRoZSBzbmFrZSwgd2UgbW'"
+ "lzc2VkIHRoZSBzY29ycGlvbi4=";
+
+ test_base64_bad(input, strlen(input));
+}
+
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/util/base64/good", test_base64_good);
+ g_test_add_func("/util/base64/embedded-nul", test_base64_embedded_nul);
+ g_test_add_func("/util/base64/not-nul-terminated",
+ test_base64_not_nul_terminated);
+ g_test_add_func("/util/base64/invalid-chars", test_base64_invalid_chars);
+ return g_test_run();
+}
diff --git a/qemu/tests/test-bitops.c b/qemu/tests/test-bitops.c
index 47b5d3ed9..505095060 100644
--- a/qemu/tests/test-bitops.c
+++ b/qemu/tests/test-bitops.c
@@ -6,9 +6,8 @@
*
*/
-#include <glib.h>
-#include <stdint.h>
#include "qemu/osdep.h"
+#include <glib.h>
#include "qemu/bitops.h"
typedef struct {
diff --git a/qemu/tests/test-blockjob-txn.c b/qemu/tests/test-blockjob-txn.c
new file mode 100644
index 000000000..55fad9507
--- /dev/null
+++ b/qemu/tests/test-blockjob-txn.c
@@ -0,0 +1,251 @@
+/*
+ * Blockjob transactions tests
+ *
+ * Copyright Red Hat, Inc. 2015
+ *
+ * Authors:
+ * Stefan Hajnoczi <stefanha@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+#include "qapi/error.h"
+#include "qemu/main-loop.h"
+#include "block/blockjob.h"
+
+typedef struct {
+ BlockJob common;
+ unsigned int iterations;
+ bool use_timer;
+ int rc;
+ int *result;
+} TestBlockJob;
+
+static const BlockJobDriver test_block_job_driver = {
+ .instance_size = sizeof(TestBlockJob),
+};
+
+static void test_block_job_complete(BlockJob *job, void *opaque)
+{
+ BlockDriverState *bs = job->bs;
+ int rc = (intptr_t)opaque;
+
+ if (block_job_is_cancelled(job)) {
+ rc = -ECANCELED;
+ }
+
+ block_job_completed(job, rc);
+ bdrv_unref(bs);
+}
+
+static void coroutine_fn test_block_job_run(void *opaque)
+{
+ TestBlockJob *s = opaque;
+ BlockJob *job = &s->common;
+
+ while (s->iterations--) {
+ if (s->use_timer) {
+ block_job_sleep_ns(job, QEMU_CLOCK_REALTIME, 0);
+ } else {
+ block_job_yield(job);
+ }
+
+ if (block_job_is_cancelled(job)) {
+ break;
+ }
+ }
+
+ block_job_defer_to_main_loop(job, test_block_job_complete,
+ (void *)(intptr_t)s->rc);
+}
+
+typedef struct {
+ TestBlockJob *job;
+ int *result;
+} TestBlockJobCBData;
+
+static void test_block_job_cb(void *opaque, int ret)
+{
+ TestBlockJobCBData *data = opaque;
+ if (!ret && block_job_is_cancelled(&data->job->common)) {
+ ret = -ECANCELED;
+ }
+ *data->result = ret;
+ g_free(data);
+}
+
+/* Create a block job that completes with a given return code after a given
+ * number of event loop iterations. The return code is stored in the given
+ * result pointer.
+ *
+ * The event loop iterations can either be handled automatically with a 0 delay
+ * timer, or they can be stepped manually by entering the coroutine.
+ */
+static BlockJob *test_block_job_start(unsigned int iterations,
+ bool use_timer,
+ int rc, int *result)
+{
+ BlockDriverState *bs;
+ TestBlockJob *s;
+ TestBlockJobCBData *data;
+
+ data = g_new0(TestBlockJobCBData, 1);
+ bs = bdrv_new();
+ s = block_job_create(&test_block_job_driver, bs, 0, test_block_job_cb,
+ data, &error_abort);
+ s->iterations = iterations;
+ s->use_timer = use_timer;
+ s->rc = rc;
+ s->result = result;
+ s->common.co = qemu_coroutine_create(test_block_job_run);
+ data->job = s;
+ data->result = result;
+ qemu_coroutine_enter(s->common.co, s);
+ return &s->common;
+}
+
+static void test_single_job(int expected)
+{
+ BlockJob *job;
+ BlockJobTxn *txn;
+ int result = -EINPROGRESS;
+
+ txn = block_job_txn_new();
+ job = test_block_job_start(1, true, expected, &result);
+ block_job_txn_add_job(txn, job);
+
+ if (expected == -ECANCELED) {
+ block_job_cancel(job);
+ }
+
+ while (result == -EINPROGRESS) {
+ aio_poll(qemu_get_aio_context(), true);
+ }
+ g_assert_cmpint(result, ==, expected);
+
+ block_job_txn_unref(txn);
+}
+
+static void test_single_job_success(void)
+{
+ test_single_job(0);
+}
+
+static void test_single_job_failure(void)
+{
+ test_single_job(-EIO);
+}
+
+static void test_single_job_cancel(void)
+{
+ test_single_job(-ECANCELED);
+}
+
+static void test_pair_jobs(int expected1, int expected2)
+{
+ BlockJob *job1;
+ BlockJob *job2;
+ BlockJobTxn *txn;
+ int result1 = -EINPROGRESS;
+ int result2 = -EINPROGRESS;
+
+ txn = block_job_txn_new();
+ job1 = test_block_job_start(1, true, expected1, &result1);
+ block_job_txn_add_job(txn, job1);
+ job2 = test_block_job_start(2, true, expected2, &result2);
+ block_job_txn_add_job(txn, job2);
+
+ if (expected1 == -ECANCELED) {
+ block_job_cancel(job1);
+ }
+ if (expected2 == -ECANCELED) {
+ block_job_cancel(job2);
+ }
+
+ while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) {
+ aio_poll(qemu_get_aio_context(), true);
+ }
+
+ /* Failure or cancellation of one job cancels the other job */
+ if (expected1 != 0) {
+ expected2 = -ECANCELED;
+ } else if (expected2 != 0) {
+ expected1 = -ECANCELED;
+ }
+
+ g_assert_cmpint(result1, ==, expected1);
+ g_assert_cmpint(result2, ==, expected2);
+
+ block_job_txn_unref(txn);
+}
+
+static void test_pair_jobs_success(void)
+{
+ test_pair_jobs(0, 0);
+}
+
+static void test_pair_jobs_failure(void)
+{
+ /* Test both orderings. The two jobs run for a different number of
+ * iterations so the code path is different depending on which job fails
+ * first.
+ */
+ test_pair_jobs(-EIO, 0);
+ test_pair_jobs(0, -EIO);
+}
+
+static void test_pair_jobs_cancel(void)
+{
+ test_pair_jobs(-ECANCELED, 0);
+ test_pair_jobs(0, -ECANCELED);
+}
+
+static void test_pair_jobs_fail_cancel_race(void)
+{
+ BlockJob *job1;
+ BlockJob *job2;
+ BlockJobTxn *txn;
+ int result1 = -EINPROGRESS;
+ int result2 = -EINPROGRESS;
+
+ txn = block_job_txn_new();
+ job1 = test_block_job_start(1, true, -ECANCELED, &result1);
+ block_job_txn_add_job(txn, job1);
+ job2 = test_block_job_start(2, false, 0, &result2);
+ block_job_txn_add_job(txn, job2);
+
+ block_job_cancel(job1);
+
+ /* Now make job2 finish before the main loop kicks jobs. This simulates
+ * the race between a pending kick and another job completing.
+ */
+ block_job_enter(job2);
+ block_job_enter(job2);
+
+ while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) {
+ aio_poll(qemu_get_aio_context(), true);
+ }
+
+ g_assert_cmpint(result1, ==, -ECANCELED);
+ g_assert_cmpint(result2, ==, -ECANCELED);
+
+ block_job_txn_unref(txn);
+}
+
+int main(int argc, char **argv)
+{
+ qemu_init_main_loop(&error_abort);
+
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/single/success", test_single_job_success);
+ g_test_add_func("/single/failure", test_single_job_failure);
+ g_test_add_func("/single/cancel", test_single_job_cancel);
+ g_test_add_func("/pair/success", test_pair_jobs_success);
+ g_test_add_func("/pair/failure", test_pair_jobs_failure);
+ g_test_add_func("/pair/cancel", test_pair_jobs_cancel);
+ g_test_add_func("/pair/fail-cancel-race", test_pair_jobs_fail_cancel_race);
+ return g_test_run();
+}
diff --git a/qemu/tests/test-coroutine.c b/qemu/tests/test-coroutine.c
index b552d9f5e..dd4ced946 100644
--- a/qemu/tests/test-coroutine.c
+++ b/qemu/tests/test-coroutine.c
@@ -11,9 +11,10 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include "block/coroutine.h"
-#include "block/coroutine_int.h"
+#include "qemu/coroutine.h"
+#include "qemu/coroutine_int.h"
/*
* Check that qemu_in_coroutine() works
diff --git a/qemu/tests/test-crypto-afsplit.c b/qemu/tests/test-crypto-afsplit.c
new file mode 100644
index 000000000..f9f2fcd41
--- /dev/null
+++ b/qemu/tests/test-crypto-afsplit.c
@@ -0,0 +1,194 @@
+/*
+ * QEMU Crypto anti-forensic splitter
+ *
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/init.h"
+#include "crypto/afsplit.h"
+
+typedef struct QCryptoAFSplitTestData QCryptoAFSplitTestData;
+struct QCryptoAFSplitTestData {
+ const char *path;
+ QCryptoHashAlgorithm hash;
+ uint32_t stripes;
+ size_t blocklen;
+ const uint8_t *key;
+ const uint8_t *splitkey;
+};
+
+static QCryptoAFSplitTestData test_data[] = {
+ {
+ .path = "/crypto/afsplit/sha256/5",
+ .hash = QCRYPTO_HASH_ALG_SHA256,
+ .stripes = 5,
+ .blocklen = 32,
+ .key = (const uint8_t *)
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
+ .splitkey = (const uint8_t *)
+ "\xfd\xd2\x73\xb1\x7d\x99\x93\x34"
+ "\x70\xde\xfa\x07\xc5\xac\x58\xd2"
+ "\x30\x67\x2f\x1a\x35\x43\x60\x7d"
+ "\x77\x02\xdb\x62\x3c\xcb\x2c\x33"
+ "\x48\x08\xb6\xf1\x7c\xa3\x20\xa0"
+ "\xad\x2d\x4c\xf3\xcd\x18\x6f\x53"
+ "\xf9\xe8\xe7\x59\x27\x3c\xa9\x54"
+ "\x61\x87\xb3\xaf\xf6\xf7\x7e\x64"
+ "\x86\xaa\x89\x7f\x1f\x9f\xdb\x86"
+ "\xf4\xa2\x16\xff\xa3\x4f\x8c\xa1"
+ "\x59\xc4\x23\x34\x28\xc4\x77\x71"
+ "\x83\xd4\xcd\x8e\x89\x1b\xc7\xc5"
+ "\xae\x4d\xa9\xcd\xc9\x72\x85\x70"
+ "\x13\x68\x52\x83\xfc\xb8\x11\x72"
+ "\xba\x3d\xc6\x4a\x28\xfa\xe2\x86"
+ "\x7b\x27\xab\x58\xe1\xa4\xca\xf6"
+ "\x9e\xbc\xfe\x0c\x92\x79\xb3\xec"
+ "\x1c\x5f\x79\x3b\x0d\x1e\xaa\x1a"
+ "\x77\x0f\x70\x19\x4b\xc8\x80\xee"
+ "\x27\x7c\x6e\x4a\x91\x96\x5c\xf4"
+ },
+ {
+ .path = "/crypto/afsplit/sha256/5000",
+ .hash = QCRYPTO_HASH_ALG_SHA256,
+ .stripes = 5000,
+ .blocklen = 16,
+ .key = (const uint8_t *)
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ },
+ {
+ .path = "/crypto/afsplit/sha1/1000",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .stripes = 1000,
+ .blocklen = 32,
+ .key = (const uint8_t *)
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
+ },
+ {
+ .path = "/crypto/afsplit/sha256/big",
+ .hash = QCRYPTO_HASH_ALG_SHA256,
+ .stripes = 1000,
+ .blocklen = 64,
+ .key = (const uint8_t *)
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ },
+};
+
+
+static inline char hex(int i)
+{
+ if (i < 10) {
+ return '0' + i;
+ }
+ return 'a' + (i - 10);
+}
+
+static char *hex_string(const uint8_t *bytes,
+ size_t len)
+{
+ char *hexstr = g_new0(char, len * 2 + 1);
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ hexstr[i * 2] = hex((bytes[i] >> 4) & 0xf);
+ hexstr[i * 2 + 1] = hex(bytes[i] & 0xf);
+ }
+ hexstr[len * 2] = '\0';
+
+ return hexstr;
+}
+
+static void test_afsplit(const void *opaque)
+{
+ const QCryptoAFSplitTestData *data = opaque;
+ size_t splitlen = data->blocklen * data->stripes;
+ uint8_t *splitkey = g_new0(uint8_t, splitlen);
+ uint8_t *key = g_new0(uint8_t, data->blocklen);
+ gchar *expect, *actual;
+
+ /* First time we round-trip the key */
+ qcrypto_afsplit_encode(data->hash,
+ data->blocklen, data->stripes,
+ data->key, splitkey,
+ &error_abort);
+
+ qcrypto_afsplit_decode(data->hash,
+ data->blocklen, data->stripes,
+ splitkey, key,
+ &error_abort);
+
+ expect = hex_string(data->key, data->blocklen);
+ actual = hex_string(key, data->blocklen);
+
+ g_assert_cmpstr(actual, ==, expect);
+
+ g_free(actual);
+ g_free(expect);
+
+ /* Second time we merely try decoding a previous split */
+ if (data->splitkey) {
+ memset(key, 0, data->blocklen);
+
+ qcrypto_afsplit_decode(data->hash,
+ data->blocklen, data->stripes,
+ data->splitkey, key,
+ &error_abort);
+
+ expect = hex_string(data->key, data->blocklen);
+ actual = hex_string(key, data->blocklen);
+
+ g_assert_cmpstr(actual, ==, expect);
+
+ g_free(actual);
+ g_free(expect);
+ }
+
+ g_free(key);
+ g_free(splitkey);
+}
+
+int main(int argc, char **argv)
+{
+ size_t i;
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
+ if (!qcrypto_hash_supports(test_data[i].hash)) {
+ continue;
+ }
+ g_test_add_data_func(test_data[i].path, &test_data[i], test_afsplit);
+ }
+ return g_test_run();
+}
diff --git a/qemu/tests/test-crypto-block.c b/qemu/tests/test-crypto-block.c
new file mode 100644
index 000000000..a38110d3f
--- /dev/null
+++ b/qemu/tests/test-crypto-block.c
@@ -0,0 +1,363 @@
+/*
+ * QEMU Crypto block encryption
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/init.h"
+#include "crypto/block.h"
+#include "qemu/buffer.h"
+#include "crypto/secret.h"
+#ifndef _WIN32
+#include <sys/resource.h>
+#endif
+
+#if defined(CONFIG_UUID) && (defined(_WIN32) || defined RUSAGE_THREAD)
+#define TEST_LUKS
+#else
+#undef TEST_LUKS
+#endif
+
+static QCryptoBlockCreateOptions qcow_create_opts = {
+ .format = Q_CRYPTO_BLOCK_FORMAT_QCOW,
+ .u.qcow = {
+ .has_key_secret = true,
+ .key_secret = (char *)"sec0",
+ },
+};
+
+static QCryptoBlockOpenOptions qcow_open_opts = {
+ .format = Q_CRYPTO_BLOCK_FORMAT_QCOW,
+ .u.qcow = {
+ .has_key_secret = true,
+ .key_secret = (char *)"sec0",
+ },
+};
+
+
+#ifdef TEST_LUKS
+static QCryptoBlockOpenOptions luks_open_opts = {
+ .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
+ .u.luks = {
+ .has_key_secret = true,
+ .key_secret = (char *)"sec0",
+ },
+};
+
+
+/* Creation with all default values */
+static QCryptoBlockCreateOptions luks_create_opts_default = {
+ .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
+ .u.luks = {
+ .has_key_secret = true,
+ .key_secret = (char *)"sec0",
+ },
+};
+
+
+/* ...and with explicit values */
+static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_plain64 = {
+ .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
+ .u.luks = {
+ .has_key_secret = true,
+ .key_secret = (char *)"sec0",
+ .has_cipher_alg = true,
+ .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256,
+ .has_cipher_mode = true,
+ .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
+ .has_ivgen_alg = true,
+ .ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64,
+ },
+};
+
+
+static QCryptoBlockCreateOptions luks_create_opts_aes256_cbc_essiv = {
+ .format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
+ .u.luks = {
+ .has_key_secret = true,
+ .key_secret = (char *)"sec0",
+ .has_cipher_alg = true,
+ .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256,
+ .has_cipher_mode = true,
+ .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
+ .has_ivgen_alg = true,
+ .ivgen_alg = QCRYPTO_IVGEN_ALG_ESSIV,
+ .has_ivgen_hash_alg = true,
+ .ivgen_hash_alg = QCRYPTO_HASH_ALG_SHA256,
+ .has_hash_alg = true,
+ .hash_alg = QCRYPTO_HASH_ALG_SHA1,
+ },
+};
+#endif /* TEST_LUKS */
+
+
+static struct QCryptoBlockTestData {
+ const char *path;
+ QCryptoBlockCreateOptions *create_opts;
+ QCryptoBlockOpenOptions *open_opts;
+
+ bool expect_header;
+
+ QCryptoCipherAlgorithm cipher_alg;
+ QCryptoCipherMode cipher_mode;
+ QCryptoHashAlgorithm hash_alg;
+
+ QCryptoIVGenAlgorithm ivgen_alg;
+ QCryptoHashAlgorithm ivgen_hash;
+
+ bool slow;
+} test_data[] = {
+ {
+ .path = "/crypto/block/qcow",
+ .create_opts = &qcow_create_opts,
+ .open_opts = &qcow_open_opts,
+
+ .expect_header = false,
+
+ .cipher_alg = QCRYPTO_CIPHER_ALG_AES_128,
+ .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
+
+ .ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64,
+ },
+#ifdef TEST_LUKS
+ {
+ .path = "/crypto/block/luks/default",
+ .create_opts = &luks_create_opts_default,
+ .open_opts = &luks_open_opts,
+
+ .expect_header = true,
+
+ .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256,
+ .cipher_mode = QCRYPTO_CIPHER_MODE_XTS,
+ .hash_alg = QCRYPTO_HASH_ALG_SHA256,
+
+ .ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64,
+
+ .slow = true,
+ },
+ {
+ .path = "/crypto/block/luks/aes-256-cbc-plain64",
+ .create_opts = &luks_create_opts_aes256_cbc_plain64,
+ .open_opts = &luks_open_opts,
+
+ .expect_header = true,
+
+ .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256,
+ .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
+ .hash_alg = QCRYPTO_HASH_ALG_SHA256,
+
+ .ivgen_alg = QCRYPTO_IVGEN_ALG_PLAIN64,
+
+ .slow = true,
+ },
+ {
+ .path = "/crypto/block/luks/aes-256-cbc-essiv",
+ .create_opts = &luks_create_opts_aes256_cbc_essiv,
+ .open_opts = &luks_open_opts,
+
+ .expect_header = true,
+
+ .cipher_alg = QCRYPTO_CIPHER_ALG_AES_256,
+ .cipher_mode = QCRYPTO_CIPHER_MODE_CBC,
+ .hash_alg = QCRYPTO_HASH_ALG_SHA1,
+
+ .ivgen_alg = QCRYPTO_IVGEN_ALG_ESSIV,
+ .ivgen_hash = QCRYPTO_HASH_ALG_SHA256,
+
+ .slow = true,
+ },
+#endif
+};
+
+
+static ssize_t test_block_read_func(QCryptoBlock *block,
+ size_t offset,
+ uint8_t *buf,
+ size_t buflen,
+ Error **errp,
+ void *opaque)
+{
+ Buffer *header = opaque;
+
+ g_assert_cmpint(offset + buflen, <=, header->capacity);
+
+ memcpy(buf, header->buffer + offset, buflen);
+
+ return buflen;
+}
+
+
+static ssize_t test_block_init_func(QCryptoBlock *block,
+ size_t headerlen,
+ Error **errp,
+ void *opaque)
+{
+ Buffer *header = opaque;
+
+ g_assert_cmpint(header->capacity, ==, 0);
+
+ buffer_reserve(header, headerlen);
+
+ return headerlen;
+}
+
+
+static ssize_t test_block_write_func(QCryptoBlock *block,
+ size_t offset,
+ const uint8_t *buf,
+ size_t buflen,
+ Error **errp,
+ void *opaque)
+{
+ Buffer *header = opaque;
+
+ g_assert_cmpint(buflen + offset, <=, header->capacity);
+
+ memcpy(header->buffer + offset, buf, buflen);
+ header->offset = offset + buflen;
+
+ return buflen;
+}
+
+
+static Object *test_block_secret(void)
+{
+ return object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "123456",
+ NULL);
+}
+
+static void test_block_assert_setup(const struct QCryptoBlockTestData *data,
+ QCryptoBlock *blk)
+{
+ QCryptoIVGen *ivgen;
+ QCryptoCipher *cipher;
+
+ ivgen = qcrypto_block_get_ivgen(blk);
+ cipher = qcrypto_block_get_cipher(blk);
+
+ g_assert(ivgen);
+ g_assert(cipher);
+
+ g_assert_cmpint(data->cipher_alg, ==, cipher->alg);
+ g_assert_cmpint(data->cipher_mode, ==, cipher->mode);
+ g_assert_cmpint(data->hash_alg, ==,
+ qcrypto_block_get_kdf_hash(blk));
+
+ g_assert_cmpint(data->ivgen_alg, ==,
+ qcrypto_ivgen_get_algorithm(ivgen));
+ g_assert_cmpint(data->ivgen_hash, ==,
+ qcrypto_ivgen_get_hash(ivgen));
+}
+
+
+static void test_block(gconstpointer opaque)
+{
+ const struct QCryptoBlockTestData *data = opaque;
+ QCryptoBlock *blk;
+ Buffer header;
+ Object *sec = test_block_secret();
+
+ memset(&header, 0, sizeof(header));
+ buffer_init(&header, "header");
+
+ blk = qcrypto_block_create(data->create_opts,
+ test_block_init_func,
+ test_block_write_func,
+ &header,
+ &error_abort);
+ g_assert(blk);
+
+ if (data->expect_header) {
+ g_assert_cmpint(header.capacity, >, 0);
+ } else {
+ g_assert_cmpint(header.capacity, ==, 0);
+ }
+
+ test_block_assert_setup(data, blk);
+
+ qcrypto_block_free(blk);
+ object_unparent(sec);
+
+ /* Ensure we can't open without the secret */
+ blk = qcrypto_block_open(data->open_opts,
+ test_block_read_func,
+ &header,
+ 0,
+ NULL);
+ g_assert(blk == NULL);
+
+ /* Ensure we can't open without the secret, unless NO_IO */
+ blk = qcrypto_block_open(data->open_opts,
+ test_block_read_func,
+ &header,
+ QCRYPTO_BLOCK_OPEN_NO_IO,
+ &error_abort);
+
+ g_assert(qcrypto_block_get_cipher(blk) == NULL);
+ g_assert(qcrypto_block_get_ivgen(blk) == NULL);
+
+ qcrypto_block_free(blk);
+
+
+ /* Now open for real with secret */
+ sec = test_block_secret();
+ blk = qcrypto_block_open(data->open_opts,
+ test_block_read_func,
+ &header,
+ 0,
+ &error_abort);
+ g_assert(blk);
+
+ test_block_assert_setup(data, blk);
+
+ qcrypto_block_free(blk);
+
+ object_unparent(sec);
+
+ buffer_free(&header);
+}
+
+
+int main(int argc, char **argv)
+{
+ gsize i;
+
+ module_call_init(MODULE_INIT_QOM);
+ g_test_init(&argc, &argv, NULL);
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
+ if (test_data[i].open_opts->format == Q_CRYPTO_BLOCK_FORMAT_LUKS &&
+ !qcrypto_hash_supports(test_data[i].hash_alg)) {
+ continue;
+ }
+ if (!test_data[i].slow ||
+ g_test_slow()) {
+ g_test_add_data_func(test_data[i].path, &test_data[i], test_block);
+ }
+ }
+
+ return g_test_run();
+}
diff --git a/qemu/tests/test-crypto-cipher.c b/qemu/tests/test-crypto-cipher.c
index 9d38d2640..66d1c63fd 100644
--- a/qemu/tests/test-crypto-cipher.c
+++ b/qemu/tests/test-crypto-cipher.c
@@ -18,10 +18,12 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "crypto/init.h"
#include "crypto/cipher.h"
+#include "qapi/error.h"
typedef struct QCryptoCipherTestData QCryptoCipherTestData;
struct QCryptoCipherTestData {
@@ -164,6 +166,211 @@ static QCryptoCipherTestData test_data[] = {
"ffd29f1bb5596ad94ea2d8e6196b7f09"
"30d8ed0bf2773af36dd82a6280c20926",
},
+ {
+ /* RFC 2144, Appendix B.1 */
+ .path = "/crypto/cipher/cast5-128",
+ .alg = QCRYPTO_CIPHER_ALG_CAST5_128,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "0123456712345678234567893456789A",
+ .plaintext = "0123456789abcdef",
+ .ciphertext = "238b4fe5847e44b2",
+ },
+ {
+ /* libgcrypt serpent.c */
+ .path = "/crypto/cipher/serpent-128",
+ .alg = QCRYPTO_CIPHER_ALG_SERPENT_128,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "00000000000000000000000000000000",
+ .plaintext = "d29d576fcea3a3a7ed9099f29273d78e",
+ .ciphertext = "b2288b968ae8b08648d1ce9606fd992d",
+ },
+ {
+ /* libgcrypt serpent.c */
+ .path = "/crypto/cipher/serpent-192",
+ .alg = QCRYPTO_CIPHER_ALG_SERPENT_192,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "00000000000000000000000000000000"
+ "0000000000000000",
+ .plaintext = "d29d576fceaba3a7ed9899f2927bd78e",
+ .ciphertext = "130e353e1037c22405e8faefb2c3c3e9",
+ },
+ {
+ /* libgcrypt serpent.c */
+ .path = "/crypto/cipher/serpent-256a",
+ .alg = QCRYPTO_CIPHER_ALG_SERPENT_256,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "00000000000000000000000000000000"
+ "00000000000000000000000000000000",
+ .plaintext = "d095576fcea3e3a7ed98d9f29073d78e",
+ .ciphertext = "b90ee5862de69168f2bdd5125b45472b",
+ },
+ {
+ /* libgcrypt serpent.c */
+ .path = "/crypto/cipher/serpent-256b",
+ .alg = QCRYPTO_CIPHER_ALG_SERPENT_256,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "00000000000000000000000000000000"
+ "00000000000000000000000000000000",
+ .plaintext = "00000000010000000200000003000000",
+ .ciphertext = "2061a42782bd52ec691ec383b03ba77c",
+ },
+ {
+ /* Twofish paper "Known Answer Test" */
+ .path = "/crypto/cipher/twofish-128",
+ .alg = QCRYPTO_CIPHER_ALG_TWOFISH_128,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "d491db16e7b1c39e86cb086b789f5419",
+ .plaintext = "019f9809de1711858faac3a3ba20fbc3",
+ .ciphertext = "6363977de839486297e661c6c9d668eb",
+ },
+ {
+ /* Twofish paper "Known Answer Test", I=3 */
+ .path = "/crypto/cipher/twofish-192",
+ .alg = QCRYPTO_CIPHER_ALG_TWOFISH_192,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "88b2b2706b105e36b446bb6d731a1e88"
+ "efa71f788965bd44",
+ .plaintext = "39da69d6ba4997d585b6dc073ca341b2",
+ .ciphertext = "182b02d81497ea45f9daacdc29193a65",
+ },
+ {
+ /* Twofish paper "Known Answer Test", I=4 */
+ .path = "/crypto/cipher/twofish-256",
+ .alg = QCRYPTO_CIPHER_ALG_TWOFISH_256,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "d43bb7556ea32e46f2a282b7d45b4e0d"
+ "57ff739d4dc92c1bd7fc01700cc8216f",
+ .plaintext = "90afe91bb288544f2c32dc239b2635e6",
+ .ciphertext = "6cb4561c40bf0a9705931cb6d408e7fa",
+ },
+ {
+ /* #1 32 byte key, 32 byte PTX */
+ .path = "/crypto/cipher/aes-xts-128-1",
+ .alg = QCRYPTO_CIPHER_ALG_AES_128,
+ .mode = QCRYPTO_CIPHER_MODE_XTS,
+ .key =
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000",
+ .iv =
+ "00000000000000000000000000000000",
+ .plaintext =
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000",
+ .ciphertext =
+ "917cf69ebd68b2ec9b9fe9a3eadda692"
+ "cd43d2f59598ed858c02c2652fbf922e",
+ },
+ {
+ /* #2, 32 byte key, 32 byte PTX */
+ .path = "/crypto/cipher/aes-xts-128-2",
+ .alg = QCRYPTO_CIPHER_ALG_AES_128,
+ .mode = QCRYPTO_CIPHER_MODE_XTS,
+ .key =
+ "11111111111111111111111111111111"
+ "22222222222222222222222222222222",
+ .iv =
+ "33333333330000000000000000000000",
+ .plaintext =
+ "44444444444444444444444444444444"
+ "44444444444444444444444444444444",
+ .ciphertext =
+ "c454185e6a16936e39334038acef838b"
+ "fb186fff7480adc4289382ecd6d394f0",
+ },
+ {
+ /* #5 from xts.7, 32 byte key, 32 byte PTX */
+ .path = "/crypto/cipher/aes-xts-128-3",
+ .alg = QCRYPTO_CIPHER_ALG_AES_128,
+ .mode = QCRYPTO_CIPHER_MODE_XTS,
+ .key =
+ "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0"
+ "bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0",
+ .iv =
+ "9a785634120000000000000000000000",
+ .plaintext =
+ "44444444444444444444444444444444"
+ "44444444444444444444444444444444",
+ .ciphertext =
+ "b01f86f8edc1863706fa8a4253e34f28"
+ "af319de38334870f4dd1f94cbe9832f1",
+ },
+ {
+ /* #4, 32 byte key, 512 byte PTX */
+ .path = "/crypto/cipher/aes-xts-128-4",
+ .alg = QCRYPTO_CIPHER_ALG_AES_128,
+ .mode = QCRYPTO_CIPHER_MODE_XTS,
+ .key =
+ "27182818284590452353602874713526"
+ "31415926535897932384626433832795",
+ .iv =
+ "00000000000000000000000000000000",
+ .plaintext =
+ "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
+ "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+ .ciphertext =
+ "27a7479befa1d476489f308cd4cfa6e2"
+ "a96e4bbe3208ff25287dd3819616e89c"
+ "c78cf7f5e543445f8333d8fa7f560000"
+ "05279fa5d8b5e4ad40e736ddb4d35412"
+ "328063fd2aab53e5ea1e0a9f332500a5"
+ "df9487d07a5c92cc512c8866c7e860ce"
+ "93fdf166a24912b422976146ae20ce84"
+ "6bb7dc9ba94a767aaef20c0d61ad0265"
+ "5ea92dc4c4e41a8952c651d33174be51"
+ "a10c421110e6d81588ede82103a252d8"
+ "a750e8768defffed9122810aaeb99f91"
+ "72af82b604dc4b8e51bcb08235a6f434"
+ "1332e4ca60482a4ba1a03b3e65008fc5"
+ "da76b70bf1690db4eae29c5f1badd03c"
+ "5ccf2a55d705ddcd86d449511ceb7ec3"
+ "0bf12b1fa35b913f9f747a8afd1b130e"
+ "94bff94effd01a91735ca1726acd0b19"
+ "7c4e5b03393697e126826fb6bbde8ecc"
+ "1e08298516e2c9ed03ff3c1b7860f6de"
+ "76d4cecd94c8119855ef5297ca67e9f3"
+ "e7ff72b1e99785ca0a7e7720c5b36dc6"
+ "d72cac9574c8cbbc2f801e23e56fd344"
+ "b07f22154beba0f08ce8891e643ed995"
+ "c94d9a69c9f1b5f499027a78572aeebd"
+ "74d20cc39881c213ee770b1010e4bea7"
+ "18846977ae119f7a023ab58cca0ad752"
+ "afe656bb3c17256a9f6e9bf19fdd5a38"
+ "fc82bbe872c5539edb609ef4f79c203e"
+ "bb140f2e583cb2ad15b4aa5b655016a8"
+ "449277dbd477ef2c8d6c017db738b18d"
+ "eb4a427d1923ce3ff262735779a418f2"
+ "0a282df920147beabe421ee5319d0568",
+ },
};
@@ -229,6 +436,7 @@ static void test_cipher(const void *opaque)
uint8_t *key, *iv, *ciphertext, *plaintext, *outtext;
size_t nkey, niv, nciphertext, nplaintext;
char *outtexthex;
+ size_t ivsize, keysize, blocksize;
nkey = unhex_string(data->key, &key);
niv = unhex_string(data->iv, &iv);
@@ -245,6 +453,19 @@ static void test_cipher(const void *opaque)
&error_abort);
g_assert(cipher != NULL);
+ keysize = qcrypto_cipher_get_key_len(data->alg);
+ blocksize = qcrypto_cipher_get_block_len(data->alg);
+ ivsize = qcrypto_cipher_get_iv_len(data->alg, data->mode);
+
+ if (data->mode == QCRYPTO_CIPHER_MODE_XTS) {
+ g_assert_cmpint(keysize * 2, ==, nkey);
+ } else {
+ g_assert_cmpint(keysize, ==, nkey);
+ }
+ g_assert_cmpint(ivsize, ==, niv);
+ if (niv) {
+ g_assert_cmpint(blocksize, ==, niv);
+ }
if (iv) {
g_assert(qcrypto_cipher_setiv(cipher,
@@ -287,6 +508,79 @@ static void test_cipher(const void *opaque)
qcrypto_cipher_free(cipher);
}
+
+static void test_cipher_null_iv(void)
+{
+ QCryptoCipher *cipher;
+ uint8_t key[32] = { 0 };
+ uint8_t plaintext[32] = { 0 };
+ uint8_t ciphertext[32] = { 0 };
+
+ cipher = qcrypto_cipher_new(
+ QCRYPTO_CIPHER_ALG_AES_256,
+ QCRYPTO_CIPHER_MODE_CBC,
+ key, sizeof(key),
+ &error_abort);
+ g_assert(cipher != NULL);
+
+ /* Don't call qcrypto_cipher_setiv */
+
+ qcrypto_cipher_encrypt(cipher,
+ plaintext,
+ ciphertext,
+ sizeof(plaintext),
+ &error_abort);
+
+ qcrypto_cipher_free(cipher);
+}
+
+static void test_cipher_short_plaintext(void)
+{
+ Error *err = NULL;
+ QCryptoCipher *cipher;
+ uint8_t key[32] = { 0 };
+ uint8_t plaintext1[20] = { 0 };
+ uint8_t ciphertext1[20] = { 0 };
+ uint8_t plaintext2[40] = { 0 };
+ uint8_t ciphertext2[40] = { 0 };
+ int ret;
+
+ cipher = qcrypto_cipher_new(
+ QCRYPTO_CIPHER_ALG_AES_256,
+ QCRYPTO_CIPHER_MODE_CBC,
+ key, sizeof(key),
+ &error_abort);
+ g_assert(cipher != NULL);
+
+ /* Should report an error as plaintext is shorter
+ * than block size
+ */
+ ret = qcrypto_cipher_encrypt(cipher,
+ plaintext1,
+ ciphertext1,
+ sizeof(plaintext1),
+ &err);
+ g_assert(ret == -1);
+ g_assert(err != NULL);
+
+ error_free(err);
+ err = NULL;
+
+ /* Should report an error as plaintext is larger than
+ * block size, but not a multiple of block size
+ */
+ ret = qcrypto_cipher_encrypt(cipher,
+ plaintext2,
+ ciphertext2,
+ sizeof(plaintext2),
+ &err);
+ g_assert(ret == -1);
+ g_assert(err != NULL);
+
+ error_free(err);
+ qcrypto_cipher_free(cipher);
+}
+
int main(int argc, char **argv)
{
size_t i;
@@ -296,7 +590,16 @@ int main(int argc, char **argv)
g_assert(qcrypto_init(NULL) == 0);
for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
- g_test_add_data_func(test_data[i].path, &test_data[i], test_cipher);
+ if (qcrypto_cipher_supports(test_data[i].alg)) {
+ g_test_add_data_func(test_data[i].path, &test_data[i], test_cipher);
+ }
}
+
+ g_test_add_func("/crypto/cipher/null-iv",
+ test_cipher_null_iv);
+
+ g_test_add_func("/crypto/cipher/short-plaintext",
+ test_cipher_short_plaintext);
+
return g_test_run();
}
diff --git a/qemu/tests/test-crypto-hash.c b/qemu/tests/test-crypto-hash.c
index 911437e60..735d6d7e0 100644
--- a/qemu/tests/test-crypto-hash.c
+++ b/qemu/tests/test-crypto-hash.c
@@ -18,6 +18,7 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "crypto/init.h"
@@ -163,6 +164,11 @@ static void test_hash_digest(void)
for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
int ret;
char *digest;
+ size_t digestsize;
+
+ digestsize = qcrypto_hash_digest_len(i);
+
+ g_assert_cmpint(digestsize * 2, ==, strlen(expected_outputs[i]));
ret = qcrypto_hash_digest(i,
INPUT_TEXT,
diff --git a/qemu/tests/test-crypto-ivgen.c b/qemu/tests/test-crypto-ivgen.c
new file mode 100644
index 000000000..a5ff5d3da
--- /dev/null
+++ b/qemu/tests/test-crypto-ivgen.c
@@ -0,0 +1,174 @@
+/*
+ * QEMU Crypto IV generator algorithms
+ *
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/ivgen.h"
+
+
+struct QCryptoIVGenTestData {
+ const char *path;
+ uint64_t sector;
+ QCryptoIVGenAlgorithm ivalg;
+ QCryptoHashAlgorithm hashalg;
+ QCryptoCipherAlgorithm cipheralg;
+ const uint8_t *key;
+ size_t nkey;
+ const uint8_t *iv;
+ size_t niv;
+} test_data[] = {
+ /* Small */
+ {
+ "/crypto/ivgen/plain/1",
+ .sector = 0x1,
+ .ivalg = QCRYPTO_IVGEN_ALG_PLAIN,
+ .iv = (const uint8_t *)"\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .niv = 16,
+ },
+ /* Big ! */
+ {
+ "/crypto/ivgen/plain/1f2e3d4c",
+ .sector = 0x1f2e3d4cULL,
+ .ivalg = QCRYPTO_IVGEN_ALG_PLAIN,
+ .iv = (const uint8_t *)"\x4c\x3d\x2e\x1f\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .niv = 16,
+ },
+ /* Truncation */
+ {
+ "/crypto/ivgen/plain/1f2e3d4c5b6a7988",
+ .sector = 0x1f2e3d4c5b6a7988ULL,
+ .ivalg = QCRYPTO_IVGEN_ALG_PLAIN,
+ .iv = (const uint8_t *)"\x88\x79\x6a\x5b\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .niv = 16,
+ },
+ /* Small */
+ {
+ "/crypto/ivgen/plain64/1",
+ .sector = 0x1,
+ .ivalg = QCRYPTO_IVGEN_ALG_PLAIN64,
+ .iv = (const uint8_t *)"\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .niv = 16,
+ },
+ /* Big ! */
+ {
+ "/crypto/ivgen/plain64/1f2e3d4c",
+ .sector = 0x1f2e3d4cULL,
+ .ivalg = QCRYPTO_IVGEN_ALG_PLAIN64,
+ .iv = (const uint8_t *)"\x4c\x3d\x2e\x1f\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .niv = 16,
+ },
+ /* No Truncation */
+ {
+ "/crypto/ivgen/plain64/1f2e3d4c5b6a7988",
+ .sector = 0x1f2e3d4c5b6a7988ULL,
+ .ivalg = QCRYPTO_IVGEN_ALG_PLAIN64,
+ .iv = (const uint8_t *)"\x88\x79\x6a\x5b\x4c\x3d\x2e\x1f"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ .niv = 16,
+ },
+ /* Small */
+ {
+ "/crypto/ivgen/essiv/1",
+ .sector = 0x1,
+ .ivalg = QCRYPTO_IVGEN_ALG_ESSIV,
+ .cipheralg = QCRYPTO_CIPHER_ALG_AES_128,
+ .hashalg = QCRYPTO_HASH_ALG_SHA256,
+ .key = (const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .nkey = 16,
+ .iv = (const uint8_t *)"\xd4\x83\x71\xb2\xa1\x94\x53\x88"
+ "\x1c\x7a\x2d\06\x2d\x0b\x65\x46",
+ .niv = 16,
+ },
+ /* Big ! */
+ {
+ "/crypto/ivgen/essiv/1f2e3d4c",
+ .sector = 0x1f2e3d4cULL,
+ .ivalg = QCRYPTO_IVGEN_ALG_ESSIV,
+ .cipheralg = QCRYPTO_CIPHER_ALG_AES_128,
+ .hashalg = QCRYPTO_HASH_ALG_SHA256,
+ .key = (const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .nkey = 16,
+ .iv = (const uint8_t *)"\x5d\x36\x09\x5d\xc6\x9e\x5e\xe9"
+ "\xe3\x02\x8d\xd8\x7a\x3d\xe7\x8f",
+ .niv = 16,
+ },
+ /* No Truncation */
+ {
+ "/crypto/ivgen/essiv/1f2e3d4c5b6a7988",
+ .sector = 0x1f2e3d4c5b6a7988ULL,
+ .ivalg = QCRYPTO_IVGEN_ALG_ESSIV,
+ .cipheralg = QCRYPTO_CIPHER_ALG_AES_128,
+ .hashalg = QCRYPTO_HASH_ALG_SHA256,
+ .key = (const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ .nkey = 16,
+ .iv = (const uint8_t *)"\x58\xbb\x81\x94\x51\x83\x23\x23"
+ "\x7a\x08\x93\xa9\xdc\xd2\xd9\xab",
+ .niv = 16,
+ },
+};
+
+
+static void test_ivgen(const void *opaque)
+{
+ const struct QCryptoIVGenTestData *data = opaque;
+ uint8_t *iv = g_new0(uint8_t, data->niv);
+ QCryptoIVGen *ivgen = qcrypto_ivgen_new(
+ data->ivalg,
+ data->cipheralg,
+ data->hashalg,
+ data->key,
+ data->nkey,
+ &error_abort);
+
+ qcrypto_ivgen_calculate(ivgen,
+ data->sector,
+ iv,
+ data->niv,
+ &error_abort);
+
+ g_assert(memcmp(iv, data->iv, data->niv) == 0);
+
+ qcrypto_ivgen_free(ivgen);
+ g_free(iv);
+}
+
+int main(int argc, char **argv)
+{
+ size_t i;
+ g_test_init(&argc, &argv, NULL);
+ for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
+ if (test_data[i].ivalg == QCRYPTO_IVGEN_ALG_ESSIV &&
+ !qcrypto_hash_supports(test_data[i].hashalg)) {
+ continue;
+ }
+ g_test_add_data_func(test_data[i].path,
+ &(test_data[i]),
+ test_ivgen);
+ }
+ return g_test_run();
+}
diff --git a/qemu/tests/test-crypto-pbkdf.c b/qemu/tests/test-crypto-pbkdf.c
new file mode 100644
index 000000000..8ceceb182
--- /dev/null
+++ b/qemu/tests/test-crypto-pbkdf.c
@@ -0,0 +1,393 @@
+/*
+ * QEMU Crypto cipher algorithms
+ *
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/init.h"
+#ifndef _WIN32
+#include <sys/resource.h>
+#endif
+
+#if ((defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT)) && \
+ (defined(_WIN32) || defined(RUSAGE_THREAD)))
+#include "crypto/pbkdf.h"
+
+typedef struct QCryptoPbkdfTestData QCryptoPbkdfTestData;
+struct QCryptoPbkdfTestData {
+ const char *path;
+ QCryptoHashAlgorithm hash;
+ unsigned int iterations;
+ const char *key;
+ size_t nkey;
+ const char *salt;
+ size_t nsalt;
+ const char *out;
+ size_t nout;
+ bool slow;
+};
+
+/* This test data comes from cryptsetup package
+ *
+ * $SRC/lib/crypto_backend/pbkdf2_generic.c
+ *
+ * under LGPLv2.1+ license
+ */
+static QCryptoPbkdfTestData test_data[] = {
+ /* RFC 3962 test data */
+ {
+ .path = "/crypto/pbkdf/rfc3962/sha1/iter1",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 1,
+ .key = "password",
+ .nkey = 8,
+ .salt = "ATHENA.MIT.EDUraeburn",
+ .nsalt = 21,
+ .out = "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01"
+ "\x56\x5a\x11\x22\xb2\x56\x35\x15"
+ "\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3"
+ "\x33\xec\xc0\xe2\xe1\xf7\x08\x37",
+ .nout = 32
+ },
+ {
+ .path = "/crypto/pbkdf/rfc3962/sha1/iter2",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 2,
+ .key = "password",
+ .nkey = 8,
+ .salt = "ATHENA.MIT.EDUraeburn",
+ .nsalt = 21,
+ .out = "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e"
+ "\x98\x8b\x62\xc7\x3c\xda\x93\x5d"
+ "\xa0\x53\x78\xb9\x32\x44\xec\x8f"
+ "\x48\xa9\x9e\x61\xad\x79\x9d\x86",
+ .nout = 32
+ },
+ {
+ .path = "/crypto/pbkdf/rfc3962/sha1/iter1200a",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 1200,
+ .key = "password",
+ .nkey = 8,
+ .salt = "ATHENA.MIT.EDUraeburn",
+ .nsalt = 21,
+ .out = "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e"
+ "\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b"
+ "\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f"
+ "\x70\x8a\x31\xe2\xe6\x2b\x1e\x13",
+ .nout = 32
+ },
+ {
+ .path = "/crypto/pbkdf/rfc3962/sha1/iter5",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 5,
+ .key = "password",
+ .nkey = 8,
+ .salt = "\0224VxxV4\022", /* "\x1234567878563412 */
+ .nsalt = 8,
+ .out = "\xd1\xda\xa7\x86\x15\xf2\x87\xe6"
+ "\xa1\xc8\xb1\x20\xd7\x06\x2a\x49"
+ "\x3f\x98\xd2\x03\xe6\xbe\x49\xa6"
+ "\xad\xf4\xfa\x57\x4b\x6e\x64\xee",
+ .nout = 32
+ },
+ {
+ .path = "/crypto/pbkdf/rfc3962/sha1/iter1200b",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 1200,
+ .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ .nkey = 64,
+ .salt = "pass phrase equals block size",
+ .nsalt = 29,
+ .out = "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b"
+ "\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9"
+ "\xc5\xec\x59\xf1\xa4\x52\xf5\xcc"
+ "\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1",
+ .nout = 32
+ },
+ {
+ .path = "/crypto/pbkdf/rfc3962/sha1/iter1200c",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 1200,
+ .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ .nkey = 65,
+ .salt = "pass phrase exceeds block size",
+ .nsalt = 30,
+ .out = "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5"
+ "\x1b\x10\xe6\xa6\x87\x21\xbe\x61"
+ "\x1a\x8b\x4d\x28\x26\x01\xdb\x3b"
+ "\x36\xbe\x92\x46\x91\x5e\xc8\x2a",
+ .nout = 32
+ },
+ {
+ .path = "/crypto/pbkdf/rfc3962/sha1/iter50",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 50,
+ .key = "\360\235\204\236", /* g-clef ("\xf09d849e) */
+ .nkey = 4,
+ .salt = "EXAMPLE.COMpianist",
+ .nsalt = 18,
+ .out = "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43"
+ "\xa5\xb8\xbb\x27\x6a\x40\x3b\x39"
+ "\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2"
+ "\x81\xff\x30\x69\xe1\xe9\x4f\x52",
+ .nout = 32
+ },
+
+ /* RFC-6070 test data */
+ {
+ .path = "/crypto/pbkdf/rfc6070/sha1/iter1",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 1,
+ .key = "password",
+ .nkey = 8,
+ .salt = "salt",
+ .nsalt = 4,
+ .out = "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9"
+ "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6",
+ .nout = 20
+ },
+ {
+ .path = "/crypto/pbkdf/rfc6070/sha1/iter2",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 2,
+ .key = "password",
+ .nkey = 8,
+ .salt = "salt",
+ .nsalt = 4,
+ .out = "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e"
+ "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57",
+ .nout = 20
+ },
+ {
+ .path = "/crypto/pbkdf/rfc6070/sha1/iter4096",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 4096,
+ .key = "password",
+ .nkey = 8,
+ .salt = "salt",
+ .nsalt = 4,
+ .out = "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad"
+ "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1",
+ .nout = 20
+ },
+ {
+ .path = "/crypto/pbkdf/rfc6070/sha1/iter16777216",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 16777216,
+ .key = "password",
+ .nkey = 8,
+ .salt = "salt",
+ .nsalt = 4,
+ .out = "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94"
+ "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84",
+ .nout = 20,
+ .slow = true,
+ },
+ {
+ .path = "/crypto/pbkdf/rfc6070/sha1/iter4096a",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 4096,
+ .key = "passwordPASSWORDpassword",
+ .nkey = 24,
+ .salt = "saltSALTsaltSALTsaltSALTsaltSALTsalt",
+ .nsalt = 36,
+ .out = "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8"
+ "\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96"
+ "\x4c\xf2\xf0\x70\x38",
+ .nout = 25
+ },
+ {
+ .path = "/crypto/pbkdf/rfc6070/sha1/iter4096b",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 4096,
+ .key = "pass\0word",
+ .nkey = 9,
+ .salt = "sa\0lt",
+ .nsalt = 5,
+ .out = "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37"
+ "\xd7\xf0\x34\x25\xe0\xc3",
+ .nout = 16
+ },
+
+ /* non-RFC misc test data */
+#ifdef CONFIG_NETTLE
+ {
+ /* empty password test.
+ * Broken with libgcrypt <= 1.5.0, hence CONFIG_NETTLE */
+ .path = "/crypto/pbkdf/nonrfc/sha1/iter2",
+ .hash = QCRYPTO_HASH_ALG_SHA1,
+ .iterations = 2,
+ .key = "",
+ .nkey = 0,
+ .salt = "salt",
+ .nsalt = 4,
+ .out = "\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2"
+ "\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97",
+ .nout = 20
+ },
+#endif
+ {
+ /* Password exceeds block size test */
+ .path = "/crypto/pbkdf/nonrfc/sha256/iter1200",
+ .hash = QCRYPTO_HASH_ALG_SHA256,
+ .iterations = 1200,
+ .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ .nkey = 65,
+ .salt = "pass phrase exceeds block size",
+ .nsalt = 30,
+ .out = "\x22\x34\x4b\xc4\xb6\xe3\x26\x75"
+ "\xa8\x09\x0f\x3e\xa8\x0b\xe0\x1d"
+ "\x5f\x95\x12\x6a\x2c\xdd\xc3\xfa"
+ "\xcc\x4a\x5e\x6d\xca\x04\xec\x58",
+ .nout = 32
+ },
+#if 0
+ {
+ .path = "/crypto/pbkdf/nonrfc/sha512/iter1200",
+ .hash = QCRYPTO_HASH_ALG_SHA512,
+ .iterations = 1200,
+ .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ .nkey = 129,
+ .salt = "pass phrase exceeds block size",
+ .nsalt = 30,
+ .out = "\x0f\xb2\xed\x2c\x0e\x6e\xfb\x7d"
+ "\x7d\x8e\xdd\x58\x01\xb4\x59\x72"
+ "\x99\x92\x16\x30\x5e\xa4\x36\x8d"
+ "\x76\x14\x80\xf3\xe3\x7a\x22\xb9",
+ .nout = 32
+ },
+ {
+ .path = "/crypto/pbkdf/nonrfc/whirlpool/iter1200",
+ .hash = QCRYPTO_HASH_ALG_WHIRLPOOL,
+ .iterations = 1200,
+ .key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+ "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ .nkey = 65,
+ .salt = "pass phrase exceeds block size",
+ .nsalt = 30,
+ .out = "\x9c\x1c\x74\xf5\x88\x26\xe7\x6a"
+ "\x53\x58\xf4\x0c\x39\xe7\x80\x89"
+ "\x07\xc0\x31\x19\x9a\x50\xa2\x48"
+ "\xf1\xd9\xfe\x78\x64\xe5\x84\x50",
+ .nout = 32
+ }
+#endif
+};
+
+
+static inline char hex(int i)
+{
+ if (i < 10) {
+ return '0' + i;
+ }
+ return 'a' + (i - 10);
+}
+
+static char *hex_string(const uint8_t *bytes,
+ size_t len)
+{
+ char *hexstr = g_new0(char, len * 2 + 1);
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ hexstr[i * 2] = hex((bytes[i] >> 4) & 0xf);
+ hexstr[i * 2 + 1] = hex(bytes[i] & 0xf);
+ }
+ hexstr[len * 2] = '\0';
+
+ return hexstr;
+}
+
+static void test_pbkdf(const void *opaque)
+{
+ const QCryptoPbkdfTestData *data = opaque;
+ size_t nout = data->nout;
+ uint8_t *out = g_new0(uint8_t, nout);
+ gchar *expect, *actual;
+
+ qcrypto_pbkdf2(data->hash,
+ (uint8_t *)data->key, data->nkey,
+ (uint8_t *)data->salt, data->nsalt,
+ data->iterations,
+ (uint8_t *)out, nout,
+ &error_abort);
+
+ expect = hex_string((const uint8_t *)data->out, data->nout);
+ actual = hex_string(out, nout);
+
+ g_assert_cmpstr(actual, ==, expect);
+
+ g_free(actual);
+ g_free(expect);
+ g_free(out);
+}
+
+
+static void test_pbkdf_timing(void)
+{
+ uint8_t key[32];
+ uint8_t salt[32];
+ int iters;
+
+ memset(key, 0x5d, sizeof(key));
+ memset(salt, 0x7c, sizeof(salt));
+
+ iters = qcrypto_pbkdf2_count_iters(QCRYPTO_HASH_ALG_SHA256,
+ key, sizeof(key),
+ salt, sizeof(salt),
+ &error_abort);
+
+ g_assert(iters >= (1 << 15));
+}
+
+
+int main(int argc, char **argv)
+{
+ size_t i;
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
+ if (!test_data[i].slow ||
+ g_test_slow()) {
+ g_test_add_data_func(test_data[i].path, &test_data[i], test_pbkdf);
+ }
+ }
+
+ if (g_test_slow()) {
+ g_test_add_func("/crypt0/pbkdf/timing", test_pbkdf_timing);
+ }
+
+ return g_test_run();
+}
+#else
+int main(int argc, char **argv)
+{
+ return 0;
+}
+#endif
diff --git a/qemu/tests/test-crypto-secret.c b/qemu/tests/test-crypto-secret.c
new file mode 100644
index 000000000..aa26c2049
--- /dev/null
+++ b/qemu/tests/test-crypto-secret.c
@@ -0,0 +1,455 @@
+/*
+ * QEMU Crypto secret handling
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+
+#include "crypto/init.h"
+#include "crypto/secret.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+
+static void test_secret_direct(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "123456",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_indirect_good(void)
+{
+ Object *sec;
+ char *fname = NULL;
+ int fd = g_file_open_tmp("secretXXXXXX",
+ &fname,
+ NULL);
+
+ g_assert(fd >= 0);
+ g_assert_nonnull(fname);
+
+ g_assert(write(fd, "123456", 6) == 6);
+
+ sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "file", fname,
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ g_free(pw);
+ close(fd);
+ g_free(fname);
+}
+
+
+static void test_secret_indirect_badfile(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "file", "does-not-exist",
+ NULL);
+
+ g_assert(sec == NULL);
+}
+
+
+static void test_secret_indirect_emptyfile(void)
+{
+ Object *sec;
+ char *fname = NULL;
+ int fd = g_file_open_tmp("secretXXXXXX",
+ &fname,
+ NULL);
+
+ g_assert(fd >= 0);
+ g_assert_nonnull(fname);
+
+ sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "file", fname,
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "");
+
+ object_unparent(sec);
+ g_free(pw);
+ close(fd);
+ g_free(fname);
+}
+
+
+static void test_secret_noconv_base64_good(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "MTIzNDU2",
+ "format", "base64",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_base64("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "MTIzNDU2");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_noconv_base64_bad(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "MTI$NDU2",
+ "format", "base64",
+ NULL);
+
+ g_assert(sec == NULL);
+}
+
+
+static void test_secret_noconv_utf8(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "123456",
+ "format", "raw",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_conv_base64_utf8valid(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "MTIzNDU2",
+ "format", "base64",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_conv_base64_utf8invalid(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "f0VMRgIBAQAAAA==",
+ "format", "base64",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ NULL);
+ g_assert(pw == NULL);
+
+ object_unparent(sec);
+}
+
+
+static void test_secret_conv_utf8_base64(void)
+{
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "123456",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_base64("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "MTIzNDU2");
+
+ object_unparent(sec);
+ g_free(pw);
+}
+
+
+static void test_secret_crypt_raw(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data",
+ "\xCC\xBF\xF7\x09\x46\x19\x0B\x52\x2A\x3A\xB4\x6B\xCD\x7A\xB0\xB0",
+ "format", "raw",
+ "keyid", "master",
+ "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ object_unparent(master);
+ g_free(pw);
+}
+
+
+static void test_secret_crypt_base64(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ &error_abort,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "base64",
+ "keyid", "master",
+ "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
+ NULL);
+
+ char *pw = qcrypto_secret_lookup_as_utf8("sec0",
+ &error_abort);
+
+ g_assert_cmpstr(pw, ==, "123456");
+
+ object_unparent(sec);
+ object_unparent(master);
+ g_free(pw);
+}
+
+
+static void test_secret_crypt_short_key(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVc",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "raw",
+ "keyid", "master",
+ "iv", "0I7Gw/TKuA+Old2W2apQ3g==",
+ NULL);
+
+ g_assert(sec == NULL);
+ object_unparent(master);
+}
+
+
+static void test_secret_crypt_short_iv(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "raw",
+ "keyid", "master",
+ "iv", "0I7Gw/TKuA+Old2W2a",
+ NULL);
+
+ g_assert(sec == NULL);
+ object_unparent(master);
+}
+
+
+static void test_secret_crypt_missing_iv(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "raw",
+ "keyid", "master",
+ NULL);
+
+ g_assert(sec == NULL);
+ object_unparent(master);
+}
+
+
+static void test_secret_crypt_bad_iv(void)
+{
+ Object *master = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "master",
+ &error_abort,
+ "data", "9miloPQCzGy+TL6aonfzVcptibCmCIhKzrnlfwiWivk=",
+ "format", "base64",
+ NULL);
+ Object *sec = object_new_with_props(
+ TYPE_QCRYPTO_SECRET,
+ object_get_objects_root(),
+ "sec0",
+ NULL,
+ "data", "zL/3CUYZC1IqOrRrzXqwsA==",
+ "format", "raw",
+ "keyid", "master",
+ "iv", "0I7Gw/TK$$uA+Old2W2a",
+ NULL);
+
+ g_assert(sec == NULL);
+ object_unparent(master);
+}
+
+
+int main(int argc, char **argv)
+{
+ module_call_init(MODULE_INIT_QOM);
+ g_test_init(&argc, &argv, NULL);
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ g_test_add_func("/crypto/secret/direct",
+ test_secret_direct);
+ g_test_add_func("/crypto/secret/indirect/good",
+ test_secret_indirect_good);
+ g_test_add_func("/crypto/secret/indirect/badfile",
+ test_secret_indirect_badfile);
+ g_test_add_func("/crypto/secret/indirect/emptyfile",
+ test_secret_indirect_emptyfile);
+
+ g_test_add_func("/crypto/secret/noconv/base64/good",
+ test_secret_noconv_base64_good);
+ g_test_add_func("/crypto/secret/noconv/base64/bad",
+ test_secret_noconv_base64_bad);
+ g_test_add_func("/crypto/secret/noconv/utf8",
+ test_secret_noconv_utf8);
+ g_test_add_func("/crypto/secret/conv/base64/utf8valid",
+ test_secret_conv_base64_utf8valid);
+ g_test_add_func("/crypto/secret/conv/base64/utf8invalid",
+ test_secret_conv_base64_utf8invalid);
+ g_test_add_func("/crypto/secret/conv/utf8/base64",
+ test_secret_conv_utf8_base64);
+
+ g_test_add_func("/crypto/secret/crypt/raw",
+ test_secret_crypt_raw);
+ g_test_add_func("/crypto/secret/crypt/base64",
+ test_secret_crypt_base64);
+ g_test_add_func("/crypto/secret/crypt/shortkey",
+ test_secret_crypt_short_key);
+ g_test_add_func("/crypto/secret/crypt/shortiv",
+ test_secret_crypt_short_iv);
+ g_test_add_func("/crypto/secret/crypt/missingiv",
+ test_secret_crypt_missing_iv);
+ g_test_add_func("/crypto/secret/crypt/badiv",
+ test_secret_crypt_bad_iv);
+
+ return g_test_run();
+}
diff --git a/qemu/tests/test-crypto-tlscredsx509.c b/qemu/tests/test-crypto-tlscredsx509.c
new file mode 100644
index 000000000..af2f80e89
--- /dev/null
+++ b/qemu/tests/test-crypto-tlscredsx509.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#include "qemu/osdep.h"
+
+#include "crypto-tls-x509-helpers.h"
+#include "crypto/tlscredsx509.h"
+#include "qapi/error.h"
+
+#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
+
+#define WORKDIR "tests/test-crypto-tlscredsx509-work/"
+#define KEYFILE WORKDIR "key-ctx.pem"
+
+struct QCryptoTLSCredsTestData {
+ bool isServer;
+ const char *cacrt;
+ const char *crt;
+ bool expectFail;
+};
+
+
+static QCryptoTLSCreds *test_tls_creds_create(QCryptoTLSCredsEndpoint endpoint,
+ const char *certdir,
+ Error **errp)
+{
+ Object *parent = object_get_objects_root();
+ Object *creds = object_new_with_props(
+ TYPE_QCRYPTO_TLS_CREDS_X509,
+ parent,
+ "testtlscreds",
+ errp,
+ "endpoint", (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ?
+ "server" : "client"),
+ "dir", certdir,
+ "verify-peer", "yes",
+ "sanity-check", "yes",
+ NULL);
+
+ if (*errp) {
+ return NULL;
+ }
+ return QCRYPTO_TLS_CREDS(creds);
+}
+
+/*
+ * This tests sanity checking of our own certificates
+ *
+ * The code being tested is used when TLS creds are created,
+ * and aim to ensure QMEU has been configured with sane
+ * certificates. This allows us to give much much much
+ * clearer error messages to the admin when they misconfigure
+ * things.
+ */
+static void test_tls_creds(const void *opaque)
+{
+ struct QCryptoTLSCredsTestData *data =
+ (struct QCryptoTLSCredsTestData *)opaque;
+ QCryptoTLSCreds *creds;
+ Error *err = NULL;
+
+#define CERT_DIR "tests/test-crypto-tlscredsx509-certs/"
+ mkdir(CERT_DIR, 0700);
+
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ if (data->isServer) {
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT);
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY);
+ } else {
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
+ }
+
+ if (access(data->cacrt, R_OK) == 0) {
+ g_assert(link(data->cacrt,
+ CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0);
+ }
+ if (data->isServer) {
+ if (access(data->crt, R_OK) == 0) {
+ g_assert(link(data->crt,
+ CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT) == 0);
+ }
+ g_assert(link(KEYFILE,
+ CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY) == 0);
+ } else {
+ if (access(data->crt, R_OK) == 0) {
+ g_assert(link(data->crt,
+ CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT) == 0);
+ }
+ g_assert(link(KEYFILE,
+ CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY) == 0);
+ }
+
+ creds = test_tls_creds_create(
+ (data->isServer ?
+ QCRYPTO_TLS_CREDS_ENDPOINT_SERVER :
+ QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT),
+ CERT_DIR,
+ &err);
+
+ if (data->expectFail) {
+ error_free(err);
+ g_assert(creds == NULL);
+ } else {
+ if (err) {
+ g_printerr("Failed to generate creds: %s\n",
+ error_get_pretty(err));
+ error_free(err);
+ }
+ g_assert(creds != NULL);
+ }
+
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ if (data->isServer) {
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT);
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY);
+ } else {
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
+ unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
+ }
+ rmdir(CERT_DIR);
+ if (creds) {
+ object_unparent(OBJECT(creds));
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ module_call_init(MODULE_INIT_QOM);
+ g_test_init(&argc, &argv, NULL);
+ setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1);
+
+ mkdir(WORKDIR, 0700);
+
+ test_tls_init(KEYFILE);
+
+# define TLS_TEST_REG(name, isServer, caCrt, crt, expectFail) \
+ struct QCryptoTLSCredsTestData name = { \
+ isServer, caCrt, crt, expectFail \
+ }; \
+ g_test_add_data_func("/qcrypto/tlscredsx509/" # name, \
+ &name, test_tls_creds); \
+
+ /* A perfect CA, perfect client & perfect server */
+
+ /* Basic:CA:critical */
+ TLS_ROOT_REQ(cacertreq,
+ "UK", "qemu CA", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+
+ TLS_CERT_REQ(servercertreq, cacertreq,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ TLS_CERT_REQ(clientcertreq, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+
+ TLS_TEST_REG(perfectserver, true,
+ cacertreq.filename, servercertreq.filename, false);
+ TLS_TEST_REG(perfectclient, false,
+ cacertreq.filename, clientcertreq.filename, false);
+
+
+ /* Some other CAs which are good */
+
+ /* Basic:CA:critical */
+ TLS_ROOT_REQ(cacert1req,
+ "UK", "qemu CA 1", NULL, NULL, NULL, NULL,
+ true, true, true,
+ false, false, 0,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercert1req, cacert1req,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+
+ /* Basic:CA:not-critical */
+ TLS_ROOT_REQ(cacert2req,
+ "UK", "qemu CA 2", NULL, NULL, NULL, NULL,
+ true, false, true,
+ false, false, 0,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercert2req, cacert2req,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+
+ /* Key usage:cert-sign:critical */
+ TLS_ROOT_REQ(cacert3req,
+ "UK", "qemu CA 3", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercert3req, cacert3req,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+
+ TLS_TEST_REG(goodca1, true,
+ cacert1req.filename, servercert1req.filename, false);
+ TLS_TEST_REG(goodca2, true,
+ cacert2req.filename, servercert2req.filename, false);
+ TLS_TEST_REG(goodca3, true,
+ cacert3req.filename, servercert3req.filename, false);
+
+ /* Now some bad certs */
+
+ /* Key usage:dig-sig:not-critical */
+ TLS_ROOT_REQ(cacert4req,
+ "UK", "qemu CA 4", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, false, GNUTLS_KEY_DIGITAL_SIGNATURE,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercert4req, cacert4req,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ /* no-basic */
+ TLS_ROOT_REQ(cacert5req,
+ "UK", "qemu CA 5", NULL, NULL, NULL, NULL,
+ false, false, false,
+ false, false, 0,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercert5req, cacert5req,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ /* Key usage:dig-sig:critical */
+ TLS_ROOT_REQ(cacert6req,
+ "UK", "qemu CA 6", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_DIGITAL_SIGNATURE,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercert6req, cacert6req,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+
+ /* Technically a CA cert with basic constraints
+ * key purpose == key signing + non-critical should
+ * be rejected. GNUTLS < 3.1 does not reject it and
+ * we don't anticipate them changing this behaviour
+ */
+ TLS_TEST_REG(badca1, true, cacert4req.filename, servercert4req.filename,
+ (GNUTLS_VERSION_MAJOR == 3 && GNUTLS_VERSION_MINOR >= 1) ||
+ GNUTLS_VERSION_MAJOR > 3);
+ TLS_TEST_REG(badca2, true,
+ cacert5req.filename, servercert5req.filename, true);
+ TLS_TEST_REG(badca3, true,
+ cacert6req.filename, servercert6req.filename, true);
+
+
+ /* Various good servers */
+ /* no usage or purpose */
+ TLS_CERT_REQ(servercert7req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ false, false, NULL, NULL,
+ 0, 0);
+ /* usage:cert-sign+dig-sig+encipher:critical */
+ TLS_CERT_REQ(servercert8req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT |
+ GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ /* usage:cert-sign:not-critical */
+ TLS_CERT_REQ(servercert9req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, false, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ /* purpose:server:critical */
+ TLS_CERT_REQ(servercert10req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ /* purpose:server:not-critical */
+ TLS_CERT_REQ(servercert11req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, false, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ /* purpose:client+server:critical */
+ TLS_CERT_REQ(servercert12req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, true,
+ GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+ 0, 0);
+ /* purpose:client+server:not-critical */
+ TLS_CERT_REQ(servercert13req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, false,
+ GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+ 0, 0);
+
+ TLS_TEST_REG(goodserver1, true,
+ cacertreq.filename, servercert7req.filename, false);
+ TLS_TEST_REG(goodserver2, true,
+ cacertreq.filename, servercert8req.filename, false);
+ TLS_TEST_REG(goodserver3, true,
+ cacertreq.filename, servercert9req.filename, false);
+ TLS_TEST_REG(goodserver4, true,
+ cacertreq.filename, servercert10req.filename, false);
+ TLS_TEST_REG(goodserver5, true,
+ cacertreq.filename, servercert11req.filename, false);
+ TLS_TEST_REG(goodserver6, true,
+ cacertreq.filename, servercert12req.filename, false);
+ TLS_TEST_REG(goodserver7, true,
+ cacertreq.filename, servercert13req.filename, false);
+
+ /* Bad servers */
+
+ /* usage:cert-sign:critical */
+ TLS_CERT_REQ(servercert14req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ /* purpose:client:critical */
+ TLS_CERT_REQ(servercert15req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+ /* usage: none:critical */
+ TLS_CERT_REQ(servercert16req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true, 0,
+ false, false, NULL, NULL,
+ 0, 0);
+
+ TLS_TEST_REG(badserver1, true,
+ cacertreq.filename, servercert14req.filename, true);
+ TLS_TEST_REG(badserver2, true,
+ cacertreq.filename, servercert15req.filename, true);
+ TLS_TEST_REG(badserver3, true,
+ cacertreq.filename, servercert16req.filename, true);
+
+
+
+ /* Various good clients */
+ /* no usage or purpose */
+ TLS_CERT_REQ(clientcert1req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ false, false, NULL, NULL,
+ 0, 0);
+ /* usage:cert-sign+dig-sig+encipher:critical */
+ TLS_CERT_REQ(clientcert2req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT |
+ GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ /* usage:cert-sign:not-critical */
+ TLS_CERT_REQ(clientcert3req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, false, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ /* purpose:client:critical */
+ TLS_CERT_REQ(clientcert4req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+ /* purpose:client:not-critical */
+ TLS_CERT_REQ(clientcert5req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, false, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+ /* purpose:client+client:critical */
+ TLS_CERT_REQ(clientcert6req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, true,
+ GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+ 0, 0);
+ /* purpose:client+client:not-critical */
+ TLS_CERT_REQ(clientcert7req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, false,
+ GNUTLS_KP_TLS_WWW_CLIENT, GNUTLS_KP_TLS_WWW_SERVER,
+ 0, 0);
+
+ TLS_TEST_REG(goodclient1, false,
+ cacertreq.filename, clientcert1req.filename, false);
+ TLS_TEST_REG(goodclient2, false,
+ cacertreq.filename, clientcert2req.filename, false);
+ TLS_TEST_REG(goodclient3, false,
+ cacertreq.filename, clientcert3req.filename, false);
+ TLS_TEST_REG(goodclient4, false,
+ cacertreq.filename, clientcert4req.filename, false);
+ TLS_TEST_REG(goodclient5, false,
+ cacertreq.filename, clientcert5req.filename, false);
+ TLS_TEST_REG(goodclient6, false,
+ cacertreq.filename, clientcert6req.filename, false);
+ TLS_TEST_REG(goodclient7, false,
+ cacertreq.filename, clientcert7req.filename, false);
+
+ /* Bad clients */
+
+ /* usage:cert-sign:critical */
+ TLS_CERT_REQ(clientcert8req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ /* purpose:client:critical */
+ TLS_CERT_REQ(clientcert9req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ false, false, 0,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ /* usage: none:critical */
+ TLS_CERT_REQ(clientcert10req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true, 0,
+ false, false, NULL, NULL,
+ 0, 0);
+
+ TLS_TEST_REG(badclient1, false,
+ cacertreq.filename, clientcert8req.filename, true);
+ TLS_TEST_REG(badclient2, false,
+ cacertreq.filename, clientcert9req.filename, true);
+ TLS_TEST_REG(badclient3, false,
+ cacertreq.filename, clientcert10req.filename, true);
+
+
+
+ /* Expired stuff */
+
+ TLS_ROOT_REQ(cacertexpreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, -1);
+ TLS_CERT_REQ(servercertexpreq, cacertexpreq,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercertexp1req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, -1);
+ TLS_CERT_REQ(clientcertexp1req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, -1);
+
+ TLS_TEST_REG(expired1, true,
+ cacertexpreq.filename, servercertexpreq.filename, true);
+ TLS_TEST_REG(expired2, true,
+ cacertreq.filename, servercertexp1req.filename, true);
+ TLS_TEST_REG(expired3, false,
+ cacertreq.filename, clientcertexp1req.filename, true);
+
+
+ /* Not activated stuff */
+
+ TLS_ROOT_REQ(cacertnewreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 1, 2);
+ TLS_CERT_REQ(servercertnewreq, cacertnewreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercertnew1req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 1, 2);
+ TLS_CERT_REQ(clientcertnew1req, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 1, 2);
+
+ TLS_TEST_REG(inactive1, true,
+ cacertnewreq.filename, servercertnewreq.filename, true);
+ TLS_TEST_REG(inactive2, true,
+ cacertreq.filename, servercertnew1req.filename, true);
+ TLS_TEST_REG(inactive3, false,
+ cacertreq.filename, clientcertnew1req.filename, true);
+
+ TLS_ROOT_REQ(cacertrootreq,
+ "UK", "qemu root", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(cacertlevel1areq, cacertrootreq,
+ "UK", "qemu level 1a", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(cacertlevel1breq, cacertrootreq,
+ "UK", "qemu level 1b", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(cacertlevel2areq, cacertlevel1areq,
+ "UK", "qemu level 2a", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercertlevel3areq, cacertlevel2areq,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ TLS_CERT_REQ(clientcertlevel2breq, cacertlevel1breq,
+ "UK", "qemu client level 2b", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+
+ gnutls_x509_crt_t certchain[] = {
+ cacertrootreq.crt,
+ cacertlevel1areq.crt,
+ cacertlevel1breq.crt,
+ cacertlevel2areq.crt,
+ };
+
+ test_tls_write_cert_chain(WORKDIR "cacertchain-ctx.pem",
+ certchain,
+ G_N_ELEMENTS(certchain));
+
+ TLS_TEST_REG(chain1, true,
+ WORKDIR "cacertchain-ctx.pem",
+ servercertlevel3areq.filename, false);
+ TLS_TEST_REG(chain2, false,
+ WORKDIR "cacertchain-ctx.pem",
+ clientcertlevel2breq.filename, false);
+
+ /* Some missing certs - first two are fatal, the last
+ * is ok
+ */
+ TLS_TEST_REG(missingca, true,
+ "cacertdoesnotexist.pem",
+ servercert1req.filename, true);
+ TLS_TEST_REG(missingserver, true,
+ cacert1req.filename,
+ "servercertdoesnotexist.pem", true);
+ TLS_TEST_REG(missingclient, false,
+ cacert1req.filename,
+ "clientcertdoesnotexist.pem", false);
+
+ ret = g_test_run();
+
+ test_tls_discard_cert(&cacertreq);
+ test_tls_discard_cert(&cacert1req);
+ test_tls_discard_cert(&cacert2req);
+ test_tls_discard_cert(&cacert3req);
+ test_tls_discard_cert(&cacert4req);
+ test_tls_discard_cert(&cacert5req);
+ test_tls_discard_cert(&cacert6req);
+
+ test_tls_discard_cert(&servercertreq);
+ test_tls_discard_cert(&servercert1req);
+ test_tls_discard_cert(&servercert2req);
+ test_tls_discard_cert(&servercert3req);
+ test_tls_discard_cert(&servercert4req);
+ test_tls_discard_cert(&servercert5req);
+ test_tls_discard_cert(&servercert6req);
+ test_tls_discard_cert(&servercert7req);
+ test_tls_discard_cert(&servercert8req);
+ test_tls_discard_cert(&servercert9req);
+ test_tls_discard_cert(&servercert10req);
+ test_tls_discard_cert(&servercert11req);
+ test_tls_discard_cert(&servercert12req);
+ test_tls_discard_cert(&servercert13req);
+ test_tls_discard_cert(&servercert14req);
+ test_tls_discard_cert(&servercert15req);
+ test_tls_discard_cert(&servercert16req);
+
+ test_tls_discard_cert(&clientcertreq);
+ test_tls_discard_cert(&clientcert1req);
+ test_tls_discard_cert(&clientcert2req);
+ test_tls_discard_cert(&clientcert3req);
+ test_tls_discard_cert(&clientcert4req);
+ test_tls_discard_cert(&clientcert5req);
+ test_tls_discard_cert(&clientcert6req);
+ test_tls_discard_cert(&clientcert7req);
+ test_tls_discard_cert(&clientcert8req);
+ test_tls_discard_cert(&clientcert9req);
+ test_tls_discard_cert(&clientcert10req);
+
+ test_tls_discard_cert(&cacertexpreq);
+ test_tls_discard_cert(&servercertexpreq);
+ test_tls_discard_cert(&servercertexp1req);
+ test_tls_discard_cert(&clientcertexp1req);
+
+ test_tls_discard_cert(&cacertnewreq);
+ test_tls_discard_cert(&servercertnewreq);
+ test_tls_discard_cert(&servercertnew1req);
+ test_tls_discard_cert(&clientcertnew1req);
+
+ test_tls_discard_cert(&cacertrootreq);
+ test_tls_discard_cert(&cacertlevel1areq);
+ test_tls_discard_cert(&cacertlevel1breq);
+ test_tls_discard_cert(&cacertlevel2areq);
+ test_tls_discard_cert(&servercertlevel3areq);
+ test_tls_discard_cert(&clientcertlevel2breq);
+ unlink(WORKDIR "cacertchain-ctx.pem");
+
+ test_tls_cleanup(KEYFILE);
+ rmdir(WORKDIR);
+
+ return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+#else /* ! QCRYPTO_HAVE_TLS_TEST_SUPPORT */
+
+int
+main(void)
+{
+ return EXIT_SUCCESS;
+}
+
+#endif /* ! QCRYPTO_HAVE_TLS_TEST_SUPPORT */
diff --git a/qemu/tests/test-crypto-tlssession.c b/qemu/tests/test-crypto-tlssession.c
new file mode 100644
index 000000000..1a4a066d7
--- /dev/null
+++ b/qemu/tests/test-crypto-tlssession.c
@@ -0,0 +1,534 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+#include "qemu/osdep.h"
+
+#include "crypto-tls-x509-helpers.h"
+#include "crypto/tlscredsx509.h"
+#include "crypto/tlssession.h"
+#include "qom/object_interfaces.h"
+#include "qapi/error.h"
+#include "qemu/sockets.h"
+#include "qemu/acl.h"
+
+#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
+
+#define WORKDIR "tests/test-crypto-tlssession-work/"
+#define KEYFILE WORKDIR "key-ctx.pem"
+
+struct QCryptoTLSSessionTestData {
+ const char *servercacrt;
+ const char *clientcacrt;
+ const char *servercrt;
+ const char *clientcrt;
+ bool expectServerFail;
+ bool expectClientFail;
+ const char *hostname;
+ const char *const *wildcards;
+};
+
+
+static ssize_t testWrite(const char *buf, size_t len, void *opaque)
+{
+ int *fd = opaque;
+
+ return write(*fd, buf, len);
+}
+
+static ssize_t testRead(char *buf, size_t len, void *opaque)
+{
+ int *fd = opaque;
+
+ return read(*fd, buf, len);
+}
+
+static QCryptoTLSCreds *test_tls_creds_create(QCryptoTLSCredsEndpoint endpoint,
+ const char *certdir,
+ Error **errp)
+{
+ Error *err = NULL;
+ Object *parent = object_get_objects_root();
+ Object *creds = object_new_with_props(
+ TYPE_QCRYPTO_TLS_CREDS_X509,
+ parent,
+ (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ?
+ "testtlscredsserver" : "testtlscredsclient"),
+ &err,
+ "endpoint", (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ?
+ "server" : "client"),
+ "dir", certdir,
+ "verify-peer", "yes",
+ /* We skip initial sanity checks here because we
+ * want to make sure that problems are being
+ * detected at the TLS session validation stage,
+ * and the test-crypto-tlscreds test already
+ * validate the sanity check code.
+ */
+ "sanity-check", "no",
+ NULL
+ );
+
+ if (err) {
+ error_propagate(errp, err);
+ return NULL;
+ }
+ return QCRYPTO_TLS_CREDS(creds);
+}
+
+
+/*
+ * This tests validation checking of peer certificates
+ *
+ * This is replicating the checks that are done for an
+ * active TLS session after handshake completes. To
+ * simulate that we create our TLS contexts, skipping
+ * sanity checks. We then get a socketpair, and
+ * initiate a TLS session across them. Finally do
+ * do actual cert validation tests
+ */
+static void test_crypto_tls_session(const void *opaque)
+{
+ struct QCryptoTLSSessionTestData *data =
+ (struct QCryptoTLSSessionTestData *)opaque;
+ QCryptoTLSCreds *clientCreds;
+ QCryptoTLSCreds *serverCreds;
+ QCryptoTLSSession *clientSess = NULL;
+ QCryptoTLSSession *serverSess = NULL;
+ qemu_acl *acl;
+ const char * const *wildcards;
+ int channel[2];
+ bool clientShake = false;
+ bool serverShake = false;
+ Error *err = NULL;
+ int ret;
+
+ /* We'll use this for our fake client-server connection */
+ ret = socketpair(AF_UNIX, SOCK_STREAM, 0, channel);
+ g_assert(ret == 0);
+
+ /*
+ * We have an evil loop to do the handshake in a single
+ * thread, so we need these non-blocking to avoid deadlock
+ * of ourselves
+ */
+ qemu_set_nonblock(channel[0]);
+ qemu_set_nonblock(channel[1]);
+
+#define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/"
+#define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/"
+ mkdir(CLIENT_CERT_DIR, 0700);
+ mkdir(SERVER_CERT_DIR, 0700);
+
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT);
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY);
+
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
+
+ g_assert(link(data->servercacrt,
+ SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0);
+ g_assert(link(data->servercrt,
+ SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT) == 0);
+ g_assert(link(KEYFILE,
+ SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY) == 0);
+
+ g_assert(link(data->clientcacrt,
+ CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0);
+ g_assert(link(data->clientcrt,
+ CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT) == 0);
+ g_assert(link(KEYFILE,
+ CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY) == 0);
+
+ clientCreds = test_tls_creds_create(
+ QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
+ CLIENT_CERT_DIR,
+ &err);
+ g_assert(clientCreds != NULL);
+
+ serverCreds = test_tls_creds_create(
+ QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
+ SERVER_CERT_DIR,
+ &err);
+ g_assert(serverCreds != NULL);
+
+ acl = qemu_acl_init("tlssessionacl");
+ qemu_acl_reset(acl);
+ wildcards = data->wildcards;
+ while (wildcards && *wildcards) {
+ qemu_acl_append(acl, 0, *wildcards);
+ wildcards++;
+ }
+
+ /* Now the real part of the test, setup the sessions */
+ clientSess = qcrypto_tls_session_new(
+ clientCreds, data->hostname, NULL,
+ QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, &err);
+ serverSess = qcrypto_tls_session_new(
+ serverCreds, NULL,
+ data->wildcards ? "tlssessionacl" : NULL,
+ QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, &err);
+
+ g_assert(clientSess != NULL);
+ g_assert(serverSess != NULL);
+
+ /* For handshake to work, we need to set the I/O callbacks
+ * to read/write over the socketpair
+ */
+ qcrypto_tls_session_set_callbacks(serverSess,
+ testWrite, testRead,
+ &channel[0]);
+ qcrypto_tls_session_set_callbacks(clientSess,
+ testWrite, testRead,
+ &channel[1]);
+
+ /*
+ * Finally we loop around & around doing handshake on each
+ * session until we get an error, or the handshake completes.
+ * This relies on the socketpair being nonblocking to avoid
+ * deadlocking ourselves upon handshake
+ */
+ do {
+ int rv;
+ if (!serverShake) {
+ rv = qcrypto_tls_session_handshake(serverSess,
+ &err);
+ g_assert(rv >= 0);
+ if (qcrypto_tls_session_get_handshake_status(serverSess) ==
+ QCRYPTO_TLS_HANDSHAKE_COMPLETE) {
+ serverShake = true;
+ }
+ }
+ if (!clientShake) {
+ rv = qcrypto_tls_session_handshake(clientSess,
+ &err);
+ g_assert(rv >= 0);
+ if (qcrypto_tls_session_get_handshake_status(clientSess) ==
+ QCRYPTO_TLS_HANDSHAKE_COMPLETE) {
+ clientShake = true;
+ }
+ }
+ } while (!clientShake && !serverShake);
+
+
+ /* Finally make sure the server validation does what
+ * we were expecting
+ */
+ if (qcrypto_tls_session_check_credentials(serverSess, &err) < 0) {
+ g_assert(data->expectServerFail);
+ error_free(err);
+ err = NULL;
+ } else {
+ g_assert(!data->expectServerFail);
+ }
+
+ /*
+ * And the same for the client validation check
+ */
+ if (qcrypto_tls_session_check_credentials(clientSess, &err) < 0) {
+ g_assert(data->expectClientFail);
+ error_free(err);
+ err = NULL;
+ } else {
+ g_assert(!data->expectClientFail);
+ }
+
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT);
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY);
+
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
+
+ rmdir(CLIENT_CERT_DIR);
+ rmdir(SERVER_CERT_DIR);
+
+ object_unparent(OBJECT(serverCreds));
+ object_unparent(OBJECT(clientCreds));
+
+ qcrypto_tls_session_free(serverSess);
+ qcrypto_tls_session_free(clientSess);
+
+ close(channel[0]);
+ close(channel[1]);
+}
+
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ module_call_init(MODULE_INIT_QOM);
+ g_test_init(&argc, &argv, NULL);
+ setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1);
+
+ mkdir(WORKDIR, 0700);
+
+ test_tls_init(KEYFILE);
+
+# define TEST_SESS_REG(name, caCrt, \
+ serverCrt, clientCrt, \
+ expectServerFail, expectClientFail, \
+ hostname, wildcards) \
+ struct QCryptoTLSSessionTestData name = { \
+ caCrt, caCrt, serverCrt, clientCrt, \
+ expectServerFail, expectClientFail, \
+ hostname, wildcards \
+ }; \
+ g_test_add_data_func("/qcrypto/tlssession/" # name, \
+ &name, test_crypto_tls_session); \
+
+
+# define TEST_SESS_REG_EXT(name, serverCaCrt, clientCaCrt, \
+ serverCrt, clientCrt, \
+ expectServerFail, expectClientFail, \
+ hostname, wildcards) \
+ struct QCryptoTLSSessionTestData name = { \
+ serverCaCrt, clientCaCrt, serverCrt, clientCrt, \
+ expectServerFail, expectClientFail, \
+ hostname, wildcards \
+ }; \
+ g_test_add_data_func("/qcrypto/tlssession/" # name, \
+ &name, test_crypto_tls_session); \
+
+ /* A perfect CA, perfect client & perfect server */
+
+ /* Basic:CA:critical */
+ TLS_ROOT_REQ(cacertreq,
+ "UK", "qemu CA", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+
+ TLS_ROOT_REQ(altcacertreq,
+ "UK", "qemu CA 1", NULL, NULL, NULL, NULL,
+ true, true, true,
+ false, false, 0,
+ false, false, NULL, NULL,
+ 0, 0);
+
+ TLS_CERT_REQ(servercertreq, cacertreq,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ TLS_CERT_REQ(clientcertreq, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+
+ TLS_CERT_REQ(clientcertaltreq, altcacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+
+ TEST_SESS_REG(basicca, cacertreq.filename,
+ servercertreq.filename, clientcertreq.filename,
+ false, false, "qemu.org", NULL);
+ TEST_SESS_REG_EXT(differentca, cacertreq.filename,
+ altcacertreq.filename, servercertreq.filename,
+ clientcertaltreq.filename, true, true, "qemu.org", NULL);
+
+
+ /* When an altname is set, the CN is ignored, so it must be duplicated
+ * as an altname for it to match */
+ TLS_CERT_REQ(servercertalt1req, cacertreq,
+ "UK", "qemu.org", "www.qemu.org", "qemu.org",
+ "192.168.122.1", "fec0::dead:beaf",
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ /* This intentionally doesn't replicate */
+ TLS_CERT_REQ(servercertalt2req, cacertreq,
+ "UK", "qemu.org", "www.qemu.org", "wiki.qemu.org",
+ "192.168.122.1", "fec0::dead:beaf",
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+
+ TEST_SESS_REG(altname1, cacertreq.filename,
+ servercertalt1req.filename, clientcertreq.filename,
+ false, false, "qemu.org", NULL);
+ TEST_SESS_REG(altname2, cacertreq.filename,
+ servercertalt1req.filename, clientcertreq.filename,
+ false, false, "www.qemu.org", NULL);
+ TEST_SESS_REG(altname3, cacertreq.filename,
+ servercertalt1req.filename, clientcertreq.filename,
+ false, true, "wiki.qemu.org", NULL);
+
+ TEST_SESS_REG(altname4, cacertreq.filename,
+ servercertalt2req.filename, clientcertreq.filename,
+ false, true, "qemu.org", NULL);
+ TEST_SESS_REG(altname5, cacertreq.filename,
+ servercertalt2req.filename, clientcertreq.filename,
+ false, false, "www.qemu.org", NULL);
+ TEST_SESS_REG(altname6, cacertreq.filename,
+ servercertalt2req.filename, clientcertreq.filename,
+ false, false, "wiki.qemu.org", NULL);
+
+ const char *const wildcards1[] = {
+ "C=UK,CN=dogfood",
+ NULL,
+ };
+ const char *const wildcards2[] = {
+ "C=UK,CN=qemu",
+ NULL,
+ };
+ const char *const wildcards3[] = {
+ "C=UK,CN=dogfood",
+ "C=UK,CN=qemu",
+ NULL,
+ };
+ const char *const wildcards4[] = {
+ "C=UK,CN=qemustuff",
+ NULL,
+ };
+ const char *const wildcards5[] = {
+ "C=UK,CN=qemu*",
+ NULL,
+ };
+ const char *const wildcards6[] = {
+ "C=UK,CN=*emu*",
+ NULL,
+ };
+
+ TEST_SESS_REG(wildcard1, cacertreq.filename,
+ servercertreq.filename, clientcertreq.filename,
+ true, false, "qemu.org", wildcards1);
+ TEST_SESS_REG(wildcard2, cacertreq.filename,
+ servercertreq.filename, clientcertreq.filename,
+ false, false, "qemu.org", wildcards2);
+ TEST_SESS_REG(wildcard3, cacertreq.filename,
+ servercertreq.filename, clientcertreq.filename,
+ false, false, "qemu.org", wildcards3);
+ TEST_SESS_REG(wildcard4, cacertreq.filename,
+ servercertreq.filename, clientcertreq.filename,
+ true, false, "qemu.org", wildcards4);
+ TEST_SESS_REG(wildcard5, cacertreq.filename,
+ servercertreq.filename, clientcertreq.filename,
+ false, false, "qemu.org", wildcards5);
+ TEST_SESS_REG(wildcard6, cacertreq.filename,
+ servercertreq.filename, clientcertreq.filename,
+ false, false, "qemu.org", wildcards6);
+
+ TLS_ROOT_REQ(cacertrootreq,
+ "UK", "qemu root", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(cacertlevel1areq, cacertrootreq,
+ "UK", "qemu level 1a", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(cacertlevel1breq, cacertrootreq,
+ "UK", "qemu level 1b", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(cacertlevel2areq, cacertlevel1areq,
+ "UK", "qemu level 2a", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercertlevel3areq, cacertlevel2areq,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ TLS_CERT_REQ(clientcertlevel2breq, cacertlevel1breq,
+ "UK", "qemu client level 2b", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+
+ gnutls_x509_crt_t certchain[] = {
+ cacertrootreq.crt,
+ cacertlevel1areq.crt,
+ cacertlevel1breq.crt,
+ cacertlevel2areq.crt,
+ };
+
+ test_tls_write_cert_chain(WORKDIR "cacertchain-sess.pem",
+ certchain,
+ G_N_ELEMENTS(certchain));
+
+ TEST_SESS_REG(cachain, WORKDIR "cacertchain-sess.pem",
+ servercertlevel3areq.filename, clientcertlevel2breq.filename,
+ false, false, "qemu.org", NULL);
+
+ ret = g_test_run();
+
+ test_tls_discard_cert(&clientcertreq);
+ test_tls_discard_cert(&clientcertaltreq);
+
+ test_tls_discard_cert(&servercertreq);
+ test_tls_discard_cert(&servercertalt1req);
+ test_tls_discard_cert(&servercertalt2req);
+
+ test_tls_discard_cert(&cacertreq);
+ test_tls_discard_cert(&altcacertreq);
+
+ test_tls_discard_cert(&cacertrootreq);
+ test_tls_discard_cert(&cacertlevel1areq);
+ test_tls_discard_cert(&cacertlevel1breq);
+ test_tls_discard_cert(&cacertlevel2areq);
+ test_tls_discard_cert(&servercertlevel3areq);
+ test_tls_discard_cert(&clientcertlevel2breq);
+ unlink(WORKDIR "cacertchain-sess.pem");
+
+ test_tls_cleanup(KEYFILE);
+ rmdir(WORKDIR);
+
+ return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+#else /* ! QCRYPTO_HAVE_TLS_TEST_SUPPORT */
+
+int
+main(void)
+{
+ return EXIT_SUCCESS;
+}
+
+#endif /* ! QCRYPTO_HAVE_TLS_TEST_SUPPORT */
diff --git a/qemu/tests/test-crypto-xts.c b/qemu/tests/test-crypto-xts.c
new file mode 100644
index 000000000..7f68b063c
--- /dev/null
+++ b/qemu/tests/test-crypto-xts.c
@@ -0,0 +1,423 @@
+/*
+ * QEMU Crypto XTS cipher mode
+ *
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * This code is originally derived from public domain / WTFPL code in
+ * LibTomCrypt crytographic library http://libtom.org. The XTS code
+ * was donated by Elliptic Semiconductor Inc (www.ellipticsemi.com)
+ * to the LibTom Projects
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "crypto/init.h"
+#include "crypto/xts.h"
+#include "crypto/aes.h"
+
+typedef struct {
+ const char *path;
+ int keylen;
+ unsigned char key1[32];
+ unsigned char key2[32];
+ uint64_t seqnum;
+ unsigned long PTLEN;
+ unsigned char PTX[512], CTX[512];
+} QCryptoXTSTestData;
+
+static const QCryptoXTSTestData test_data[] = {
+ /* #1 32 byte key, 32 byte PTX */
+ {
+ "/crypto/xts/t-1-key-32-ptx-32",
+ 32,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ 0,
+ 32,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+ 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+ 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+ 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
+ },
+
+ /* #2, 32 byte key, 32 byte PTX */
+ {
+ "/crypto/xts/t-2-key-32-ptx-32",
+ 32,
+ { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11 },
+ { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+ 0x3333333333LL,
+ 32,
+ { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+ { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+ 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+ 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+ 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
+ },
+
+ /* #5 from xts.7, 32 byte key, 32 byte PTX */
+ {
+ "/crypto/xts/t-5-key-32-ptx-32",
+ 32,
+ { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+ 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0 },
+ { 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
+ 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0 },
+ 0x123456789aLL,
+ 32,
+ { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+ { 0xb0, 0x1f, 0x86, 0xf8, 0xed, 0xc1, 0x86, 0x37,
+ 0x06, 0xfa, 0x8a, 0x42, 0x53, 0xe3, 0x4f, 0x28,
+ 0xaf, 0x31, 0x9d, 0xe3, 0x83, 0x34, 0x87, 0x0f,
+ 0x4d, 0xd1, 0xf9, 0x4c, 0xbe, 0x98, 0x32, 0xf1 },
+ },
+
+ /* #4, 32 byte key, 512 byte PTX */
+ {
+ "/crypto/xts/t-4-key-32-ptx-512",
+ 32,
+ { 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
+ 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26 },
+ { 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
+ 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95 },
+ 0,
+ 512,
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ },
+ {
+ 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
+ 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
+ 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
+ 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
+ 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
+ 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
+ 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
+ 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
+ 0x32, 0x80, 0x63, 0xfd, 0x2a, 0xab, 0x53, 0xe5,
+ 0xea, 0x1e, 0x0a, 0x9f, 0x33, 0x25, 0x00, 0xa5,
+ 0xdf, 0x94, 0x87, 0xd0, 0x7a, 0x5c, 0x92, 0xcc,
+ 0x51, 0x2c, 0x88, 0x66, 0xc7, 0xe8, 0x60, 0xce,
+ 0x93, 0xfd, 0xf1, 0x66, 0xa2, 0x49, 0x12, 0xb4,
+ 0x22, 0x97, 0x61, 0x46, 0xae, 0x20, 0xce, 0x84,
+ 0x6b, 0xb7, 0xdc, 0x9b, 0xa9, 0x4a, 0x76, 0x7a,
+ 0xae, 0xf2, 0x0c, 0x0d, 0x61, 0xad, 0x02, 0x65,
+ 0x5e, 0xa9, 0x2d, 0xc4, 0xc4, 0xe4, 0x1a, 0x89,
+ 0x52, 0xc6, 0x51, 0xd3, 0x31, 0x74, 0xbe, 0x51,
+ 0xa1, 0x0c, 0x42, 0x11, 0x10, 0xe6, 0xd8, 0x15,
+ 0x88, 0xed, 0xe8, 0x21, 0x03, 0xa2, 0x52, 0xd8,
+ 0xa7, 0x50, 0xe8, 0x76, 0x8d, 0xef, 0xff, 0xed,
+ 0x91, 0x22, 0x81, 0x0a, 0xae, 0xb9, 0x9f, 0x91,
+ 0x72, 0xaf, 0x82, 0xb6, 0x04, 0xdc, 0x4b, 0x8e,
+ 0x51, 0xbc, 0xb0, 0x82, 0x35, 0xa6, 0xf4, 0x34,
+ 0x13, 0x32, 0xe4, 0xca, 0x60, 0x48, 0x2a, 0x4b,
+ 0xa1, 0xa0, 0x3b, 0x3e, 0x65, 0x00, 0x8f, 0xc5,
+ 0xda, 0x76, 0xb7, 0x0b, 0xf1, 0x69, 0x0d, 0xb4,
+ 0xea, 0xe2, 0x9c, 0x5f, 0x1b, 0xad, 0xd0, 0x3c,
+ 0x5c, 0xcf, 0x2a, 0x55, 0xd7, 0x05, 0xdd, 0xcd,
+ 0x86, 0xd4, 0x49, 0x51, 0x1c, 0xeb, 0x7e, 0xc3,
+ 0x0b, 0xf1, 0x2b, 0x1f, 0xa3, 0x5b, 0x91, 0x3f,
+ 0x9f, 0x74, 0x7a, 0x8a, 0xfd, 0x1b, 0x13, 0x0e,
+ 0x94, 0xbf, 0xf9, 0x4e, 0xff, 0xd0, 0x1a, 0x91,
+ 0x73, 0x5c, 0xa1, 0x72, 0x6a, 0xcd, 0x0b, 0x19,
+ 0x7c, 0x4e, 0x5b, 0x03, 0x39, 0x36, 0x97, 0xe1,
+ 0x26, 0x82, 0x6f, 0xb6, 0xbb, 0xde, 0x8e, 0xcc,
+ 0x1e, 0x08, 0x29, 0x85, 0x16, 0xe2, 0xc9, 0xed,
+ 0x03, 0xff, 0x3c, 0x1b, 0x78, 0x60, 0xf6, 0xde,
+ 0x76, 0xd4, 0xce, 0xcd, 0x94, 0xc8, 0x11, 0x98,
+ 0x55, 0xef, 0x52, 0x97, 0xca, 0x67, 0xe9, 0xf3,
+ 0xe7, 0xff, 0x72, 0xb1, 0xe9, 0x97, 0x85, 0xca,
+ 0x0a, 0x7e, 0x77, 0x20, 0xc5, 0xb3, 0x6d, 0xc6,
+ 0xd7, 0x2c, 0xac, 0x95, 0x74, 0xc8, 0xcb, 0xbc,
+ 0x2f, 0x80, 0x1e, 0x23, 0xe5, 0x6f, 0xd3, 0x44,
+ 0xb0, 0x7f, 0x22, 0x15, 0x4b, 0xeb, 0xa0, 0xf0,
+ 0x8c, 0xe8, 0x89, 0x1e, 0x64, 0x3e, 0xd9, 0x95,
+ 0xc9, 0x4d, 0x9a, 0x69, 0xc9, 0xf1, 0xb5, 0xf4,
+ 0x99, 0x02, 0x7a, 0x78, 0x57, 0x2a, 0xee, 0xbd,
+ 0x74, 0xd2, 0x0c, 0xc3, 0x98, 0x81, 0xc2, 0x13,
+ 0xee, 0x77, 0x0b, 0x10, 0x10, 0xe4, 0xbe, 0xa7,
+ 0x18, 0x84, 0x69, 0x77, 0xae, 0x11, 0x9f, 0x7a,
+ 0x02, 0x3a, 0xb5, 0x8c, 0xca, 0x0a, 0xd7, 0x52,
+ 0xaf, 0xe6, 0x56, 0xbb, 0x3c, 0x17, 0x25, 0x6a,
+ 0x9f, 0x6e, 0x9b, 0xf1, 0x9f, 0xdd, 0x5a, 0x38,
+ 0xfc, 0x82, 0xbb, 0xe8, 0x72, 0xc5, 0x53, 0x9e,
+ 0xdb, 0x60, 0x9e, 0xf4, 0xf7, 0x9c, 0x20, 0x3e,
+ 0xbb, 0x14, 0x0f, 0x2e, 0x58, 0x3c, 0xb2, 0xad,
+ 0x15, 0xb4, 0xaa, 0x5b, 0x65, 0x50, 0x16, 0xa8,
+ 0x44, 0x92, 0x77, 0xdb, 0xd4, 0x77, 0xef, 0x2c,
+ 0x8d, 0x6c, 0x01, 0x7d, 0xb7, 0x38, 0xb1, 0x8d,
+ 0xeb, 0x4a, 0x42, 0x7d, 0x19, 0x23, 0xce, 0x3f,
+ 0xf2, 0x62, 0x73, 0x57, 0x79, 0xa4, 0x18, 0xf2,
+ 0x0a, 0x28, 0x2d, 0xf9, 0x20, 0x14, 0x7b, 0xea,
+ 0xbe, 0x42, 0x1e, 0xe5, 0x31, 0x9d, 0x05, 0x68,
+ }
+ },
+
+ /* #7, 32 byte key, 17 byte PTX */
+ {
+ "/crypto/xts/t-7-key-32-ptx-17",
+ 32,
+ { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+ 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0 },
+ { 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
+ 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0 },
+ 0x123456789aLL,
+ 17,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 },
+ { 0x6c, 0x16, 0x25, 0xdb, 0x46, 0x71, 0x52, 0x2d,
+ 0x3d, 0x75, 0x99, 0x60, 0x1d, 0xe7, 0xca, 0x09, 0xed },
+ },
+
+ /* #15, 32 byte key, 25 byte PTX */
+ {
+ "/crypto/xts/t-15-key-32-ptx-25",
+ 32,
+ { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+ 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0 },
+ { 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
+ 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0 },
+ 0x123456789aLL,
+ 25,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 },
+ { 0x8f, 0x4d, 0xcb, 0xad, 0x55, 0x55, 0x8d, 0x7b,
+ 0x4e, 0x01, 0xd9, 0x37, 0x9c, 0xd4, 0xea, 0x22,
+ 0xed, 0xbf, 0x9d, 0xac, 0xe4, 0x5d, 0x6f, 0x6a, 0x73 },
+ },
+
+ /* #21, 32 byte key, 31 byte PTX */
+ {
+ "/crypto/xts/t-21-key-32-ptx-31",
+ 32,
+ { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+ 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0 },
+ { 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
+ 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0 },
+ 0x123456789aLL,
+ 31,
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
+ { 0xd0, 0x5b, 0xc0, 0x90, 0xa8, 0xe0, 0x4f, 0x1b,
+ 0x3d, 0x3e, 0xcd, 0xd5, 0xba, 0xec, 0x0f, 0xd4,
+ 0xed, 0xbf, 0x9d, 0xac, 0xe4, 0x5d, 0x6f, 0x6a,
+ 0x73, 0x06, 0xe6, 0x4b, 0xe5, 0xdd, 0x82 },
+ },
+};
+
+#define STORE64L(x, y) \
+ do { \
+ (y)[7] = (unsigned char)(((x) >> 56) & 255); \
+ (y)[6] = (unsigned char)(((x) >> 48) & 255); \
+ (y)[5] = (unsigned char)(((x) >> 40) & 255); \
+ (y)[4] = (unsigned char)(((x) >> 32) & 255); \
+ (y)[3] = (unsigned char)(((x) >> 24) & 255); \
+ (y)[2] = (unsigned char)(((x) >> 16) & 255); \
+ (y)[1] = (unsigned char)(((x) >> 8) & 255); \
+ (y)[0] = (unsigned char)((x) & 255); \
+ } while (0)
+
+struct TestAES {
+ AES_KEY enc;
+ AES_KEY dec;
+};
+
+static void test_xts_aes_encrypt(const void *ctx,
+ size_t length,
+ uint8_t *dst,
+ const uint8_t *src)
+{
+ const struct TestAES *aesctx = ctx;
+
+ AES_encrypt(src, dst, &aesctx->enc);
+}
+
+
+static void test_xts_aes_decrypt(const void *ctx,
+ size_t length,
+ uint8_t *dst,
+ const uint8_t *src)
+{
+ const struct TestAES *aesctx = ctx;
+
+ AES_decrypt(src, dst, &aesctx->dec);
+}
+
+
+static void test_xts(const void *opaque)
+{
+ const QCryptoXTSTestData *data = opaque;
+ unsigned char OUT[512], Torg[16], T[16];
+ uint64_t seq;
+ int j;
+ unsigned long len;
+ struct TestAES aesdata;
+ struct TestAES aestweak;
+
+ for (j = 0; j < 2; j++) {
+ /* skip the cases where
+ * the length is smaller than 2*blocklen
+ * or the length is not a multiple of 32
+ */
+ if ((j == 1) && ((data->PTLEN < 32) || (data->PTLEN % 32))) {
+ continue;
+ }
+ len = data->PTLEN / 2;
+
+ AES_set_encrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.enc);
+ AES_set_decrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.dec);
+ AES_set_encrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.enc);
+ AES_set_decrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.dec);
+
+ seq = data->seqnum;
+ STORE64L(seq, Torg);
+ memset(Torg + 8, 0, 8);
+
+ memcpy(T, Torg, sizeof(T));
+ if (j == 0) {
+ xts_encrypt(&aesdata, &aestweak,
+ test_xts_aes_encrypt,
+ test_xts_aes_decrypt,
+ T, data->PTLEN, OUT, data->PTX);
+ } else {
+ xts_encrypt(&aesdata, &aestweak,
+ test_xts_aes_encrypt,
+ test_xts_aes_decrypt,
+ T, len, OUT, data->PTX);
+ xts_encrypt(&aesdata, &aestweak,
+ test_xts_aes_encrypt,
+ test_xts_aes_decrypt,
+ T, len, &OUT[len], &data->PTX[len]);
+ }
+
+ g_assert(memcmp(OUT, data->CTX, data->PTLEN) == 0);
+
+ memcpy(T, Torg, sizeof(T));
+ if (j == 0) {
+ xts_decrypt(&aesdata, &aestweak,
+ test_xts_aes_encrypt,
+ test_xts_aes_decrypt,
+ T, data->PTLEN, OUT, data->CTX);
+ } else {
+ xts_decrypt(&aesdata, &aestweak,
+ test_xts_aes_encrypt,
+ test_xts_aes_decrypt,
+ T, len, OUT, data->CTX);
+ xts_decrypt(&aesdata, &aestweak,
+ test_xts_aes_encrypt,
+ test_xts_aes_decrypt,
+ T, len, &OUT[len], &data->CTX[len]);
+ }
+
+ g_assert(memcmp(OUT, data->PTX, data->PTLEN) == 0);
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ size_t i;
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
+ g_test_add_data_func(test_data[i].path, &test_data[i], test_xts);
+ }
+
+ return g_test_run();
+}
diff --git a/qemu/tests/test-cutils.c b/qemu/tests/test-cutils.c
index 2a4556d3a..fb8f5b532 100644
--- a/qemu/tests/test-cutils.c
+++ b/qemu/tests/test-cutils.c
@@ -25,12 +25,10 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <errno.h>
-#include <string.h>
-
-#include "qemu-common.h"
+#include "qemu/cutils.h"
static void test_parse_uint_null(void)
{
@@ -226,6 +224,1212 @@ static void test_parse_uint_full_correct(void)
g_assert_cmpint(i, ==, 123);
}
+static void test_qemu_strtol_correct(void)
+{
+ const char *str = "12345 foo";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 12345);
+ g_assert(endptr == str + 5);
+}
+
+static void test_qemu_strtol_null(void)
+{
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(NULL, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtol_empty(void)
+{
+ const char *str = "";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtol_whitespace(void)
+{
+ const char *str = " \t ";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtol_invalid(void)
+{
+ const char *str = " xxxx \t abc";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtol_trailing(void)
+{
+ const char *str = "123xxx";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + 3);
+}
+
+static void test_qemu_strtol_octal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 8, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+
+ res = 999;
+ endptr = &f;
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_decimal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 10, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "123";
+ res = 999;
+ endptr = &f;
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_hex(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 16, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "0x123";
+ res = 999;
+ endptr = &f;
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_max(void)
+{
+ const char *str = g_strdup_printf("%ld", LONG_MAX);
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, LONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_overflow(void)
+{
+ const char *str = "99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, LONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_underflow(void)
+{
+ const char *str = "-99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, LONG_MIN);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_negative(void)
+{
+ const char *str = " \t -321";
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_full_correct(void)
+{
+ const char *str = "123";
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+}
+
+static void test_qemu_strtol_full_null(void)
+{
+ char f = 'X';
+ const char *endptr = &f;
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(NULL, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtol_full_empty(void)
+{
+ const char *str = "";
+ long res = 999L;
+ int err;
+
+ err = qemu_strtol(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtol_full_negative(void)
+{
+ const char *str = " \t -321";
+ long res = 999;
+ int err;
+
+ err = qemu_strtol(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321);
+}
+
+static void test_qemu_strtol_full_trailing(void)
+{
+ const char *str = "123xxx";
+ long res;
+ int err;
+
+ err = qemu_strtol(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtol_full_max(void)
+{
+ const char *str = g_strdup_printf("%ld", LONG_MAX);
+ long res;
+ int err;
+
+ err = qemu_strtol(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, LONG_MAX);
+}
+
+static void test_qemu_strtoul_correct(void)
+{
+ const char *str = "12345 foo";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 12345);
+ g_assert(endptr == str + 5);
+}
+
+static void test_qemu_strtoul_null(void)
+{
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(NULL, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtoul_empty(void)
+{
+ const char *str = "";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoul_whitespace(void)
+{
+ const char *str = " \t ";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoul_invalid(void)
+{
+ const char *str = " xxxx \t abc";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoul_trailing(void)
+{
+ const char *str = "123xxx";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + 3);
+}
+
+static void test_qemu_strtoul_octal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 8, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+
+ res = 999;
+ endptr = &f;
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoul_decimal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 10, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "123";
+ res = 999;
+ endptr = &f;
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoul_hex(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 16, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "0x123";
+ res = 999;
+ endptr = &f;
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoul_max(void)
+{
+ const char *str = g_strdup_printf("%lu", ULONG_MAX);
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, ULONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoul_overflow(void)
+{
+ const char *str = "99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, ULONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoul_underflow(void)
+{
+ const char *str = "-99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, -1ul);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoul_negative(void)
+{
+ const char *str = " \t -321";
+ char f = 'X';
+ const char *endptr = &f;
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321ul);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoul_full_correct(void)
+{
+ const char *str = "123";
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+}
+
+static void test_qemu_strtoul_full_null(void)
+{
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(NULL, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoul_full_empty(void)
+{
+ const char *str = "";
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+static void test_qemu_strtoul_full_negative(void)
+{
+ const char *str = " \t -321";
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, NULL, 0, &res);
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321ul);
+}
+
+static void test_qemu_strtoul_full_trailing(void)
+{
+ const char *str = "123xxx";
+ unsigned long res;
+ int err;
+
+ err = qemu_strtoul(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoul_full_max(void)
+{
+ const char *str = g_strdup_printf("%lu", ULONG_MAX);
+ unsigned long res = 999;
+ int err;
+
+ err = qemu_strtoul(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, ULONG_MAX);
+}
+
+static void test_qemu_strtoll_correct(void)
+{
+ const char *str = "12345 foo";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 12345);
+ g_assert(endptr == str + 5);
+}
+
+static void test_qemu_strtoll_null(void)
+{
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(NULL, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtoll_empty(void)
+{
+ const char *str = "";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoll_whitespace(void)
+{
+ const char *str = " \t ";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoll_invalid(void)
+{
+ const char *str = " xxxx \t abc";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoll_trailing(void)
+{
+ const char *str = "123xxx";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + 3);
+}
+
+static void test_qemu_strtoll_octal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 8, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+
+ endptr = &f;
+ res = 999;
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_decimal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 10, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "123";
+ endptr = &f;
+ res = 999;
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_hex(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 16, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "0x123";
+ endptr = &f;
+ res = 999;
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_max(void)
+{
+ const char *str = g_strdup_printf("%lld", LLONG_MAX);
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, LLONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_overflow(void)
+{
+ const char *str = "99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, LLONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_underflow(void)
+{
+ const char *str = "-99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, LLONG_MIN);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_negative(void)
+{
+ const char *str = " \t -321";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_full_correct(void)
+{
+ const char *str = "123";
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+}
+
+static void test_qemu_strtoll_full_null(void)
+{
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(NULL, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoll_full_empty(void)
+{
+ const char *str = "";
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoll_full_negative(void)
+{
+ const char *str = " \t -321";
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321);
+}
+
+static void test_qemu_strtoll_full_trailing(void)
+{
+ const char *str = "123xxx";
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoll_full_max(void)
+{
+
+ const char *str = g_strdup_printf("%lld", LLONG_MAX);
+ int64_t res;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, LLONG_MAX);
+}
+
+static void test_qemu_strtoull_correct(void)
+{
+ const char *str = "12345 foo";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 12345);
+ g_assert(endptr == str + 5);
+}
+
+static void test_qemu_strtoull_null(void)
+{
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(NULL, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtoull_empty(void)
+{
+ const char *str = "";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoull_whitespace(void)
+{
+ const char *str = " \t ";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoull_invalid(void)
+{
+ const char *str = " xxxx \t abc";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoull_trailing(void)
+{
+ const char *str = "123xxx";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + 3);
+}
+
+static void test_qemu_strtoull_octal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 8, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+
+ endptr = &f;
+ res = 999;
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoull_decimal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 10, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "123";
+ endptr = &f;
+ res = 999;
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoull_hex(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 16, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "0x123";
+ endptr = &f;
+ res = 999;
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoull_max(void)
+{
+ const char *str = g_strdup_printf("%llu", ULLONG_MAX);
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, ULLONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoull_overflow(void)
+{
+ const char *str = "99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, ULLONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoull_underflow(void)
+{
+ const char *str = "-99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, -1);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoull_negative(void)
+{
+ const char *str = " \t -321";
+ char f = 'X';
+ const char *endptr = &f;
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoull_full_correct(void)
+{
+ const char *str = "18446744073709551614";
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 18446744073709551614LLU);
+}
+
+static void test_qemu_strtoull_full_null(void)
+{
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(NULL, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoull_full_empty(void)
+{
+ const char *str = "";
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoull_full_negative(void)
+{
+ const char *str = " \t -321";
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 18446744073709551295LLU);
+}
+
+static void test_qemu_strtoull_full_trailing(void)
+{
+ const char *str = "18446744073709551614xxxxxx";
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoull_full_max(void)
+{
+ const char *str = g_strdup_printf("%lld", ULLONG_MAX);
+ uint64_t res = 999;
+ int err;
+
+ err = qemu_strtoull(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, ULLONG_MAX);
+}
+
+static void test_qemu_strtosz_simple(void)
+{
+ const char *str = "12345M";
+ char *endptr = NULL;
+ int64_t res;
+
+ res = qemu_strtosz(str, &endptr);
+ g_assert_cmpint(res, ==, 12345 * M_BYTE);
+ g_assert(endptr == str + 6);
+
+ res = qemu_strtosz(str, NULL);
+ g_assert_cmpint(res, ==, 12345 * M_BYTE);
+}
+
+static void test_qemu_strtosz_units(void)
+{
+ const char *none = "1";
+ const char *b = "1B";
+ const char *k = "1K";
+ const char *m = "1M";
+ const char *g = "1G";
+ const char *t = "1T";
+ const char *p = "1P";
+ const char *e = "1E";
+ int64_t res;
+
+ /* default is M */
+ res = qemu_strtosz(none, NULL);
+ g_assert_cmpint(res, ==, M_BYTE);
+
+ res = qemu_strtosz(b, NULL);
+ g_assert_cmpint(res, ==, 1);
+
+ res = qemu_strtosz(k, NULL);
+ g_assert_cmpint(res, ==, K_BYTE);
+
+ res = qemu_strtosz(m, NULL);
+ g_assert_cmpint(res, ==, M_BYTE);
+
+ res = qemu_strtosz(g, NULL);
+ g_assert_cmpint(res, ==, G_BYTE);
+
+ res = qemu_strtosz(t, NULL);
+ g_assert_cmpint(res, ==, T_BYTE);
+
+ res = qemu_strtosz(p, NULL);
+ g_assert_cmpint(res, ==, P_BYTE);
+
+ res = qemu_strtosz(e, NULL);
+ g_assert_cmpint(res, ==, E_BYTE);
+}
+
+static void test_qemu_strtosz_float(void)
+{
+ const char *str = "12.345M";
+ int64_t res;
+
+ res = qemu_strtosz(str, NULL);
+ g_assert_cmpint(res, ==, 12.345 * M_BYTE);
+}
+
+static void test_qemu_strtosz_erange(void)
+{
+ const char *str = "10E";
+ int64_t res;
+
+ res = qemu_strtosz(str, NULL);
+ g_assert_cmpint(res, ==, -ERANGE);
+}
+
+static void test_qemu_strtosz_suffix_unit(void)
+{
+ const char *str = "12345";
+ int64_t res;
+
+ res = qemu_strtosz_suffix_unit(str, NULL,
+ QEMU_STRTOSZ_DEFSUFFIX_KB, 1000);
+ g_assert_cmpint(res, ==, 12345000);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
@@ -247,5 +1451,145 @@ int main(int argc, char **argv)
g_test_add_func("/cutils/parse_uint_full/correct",
test_parse_uint_full_correct);
+ /* qemu_strtol() tests */
+ g_test_add_func("/cutils/qemu_strtol/correct", test_qemu_strtol_correct);
+ g_test_add_func("/cutils/qemu_strtol/null", test_qemu_strtol_null);
+ g_test_add_func("/cutils/qemu_strtol/empty", test_qemu_strtol_empty);
+ g_test_add_func("/cutils/qemu_strtol/whitespace",
+ test_qemu_strtol_whitespace);
+ g_test_add_func("/cutils/qemu_strtol/invalid", test_qemu_strtol_invalid);
+ g_test_add_func("/cutils/qemu_strtol/trailing", test_qemu_strtol_trailing);
+ g_test_add_func("/cutils/qemu_strtol/octal", test_qemu_strtol_octal);
+ g_test_add_func("/cutils/qemu_strtol/decimal", test_qemu_strtol_decimal);
+ g_test_add_func("/cutils/qemu_strtol/hex", test_qemu_strtol_hex);
+ g_test_add_func("/cutils/qemu_strtol/max", test_qemu_strtol_max);
+ g_test_add_func("/cutils/qemu_strtol/overflow", test_qemu_strtol_overflow);
+ g_test_add_func("/cutils/qemu_strtol/underflow",
+ test_qemu_strtol_underflow);
+ g_test_add_func("/cutils/qemu_strtol/negative", test_qemu_strtol_negative);
+ g_test_add_func("/cutils/qemu_strtol_full/correct",
+ test_qemu_strtol_full_correct);
+ g_test_add_func("/cutils/qemu_strtol_full/null",
+ test_qemu_strtol_full_null);
+ g_test_add_func("/cutils/qemu_strtol_full/empty",
+ test_qemu_strtol_full_empty);
+ g_test_add_func("/cutils/qemu_strtol_full/negative",
+ test_qemu_strtol_full_negative);
+ g_test_add_func("/cutils/qemu_strtol_full/trailing",
+ test_qemu_strtol_full_trailing);
+ g_test_add_func("/cutils/qemu_strtol_full/max",
+ test_qemu_strtol_full_max);
+
+ /* qemu_strtoul() tests */
+ g_test_add_func("/cutils/qemu_strtoul/correct", test_qemu_strtoul_correct);
+ g_test_add_func("/cutils/qemu_strtoul/null", test_qemu_strtoul_null);
+ g_test_add_func("/cutils/qemu_strtoul/empty", test_qemu_strtoul_empty);
+ g_test_add_func("/cutils/qemu_strtoul/whitespace",
+ test_qemu_strtoul_whitespace);
+ g_test_add_func("/cutils/qemu_strtoul/invalid", test_qemu_strtoul_invalid);
+ g_test_add_func("/cutils/qemu_strtoul/trailing",
+ test_qemu_strtoul_trailing);
+ g_test_add_func("/cutils/qemu_strtoul/octal", test_qemu_strtoul_octal);
+ g_test_add_func("/cutils/qemu_strtoul/decimal", test_qemu_strtoul_decimal);
+ g_test_add_func("/cutils/qemu_strtoul/hex", test_qemu_strtoul_hex);
+ g_test_add_func("/cutils/qemu_strtoul/max", test_qemu_strtoul_max);
+ g_test_add_func("/cutils/qemu_strtoul/overflow",
+ test_qemu_strtoul_overflow);
+ g_test_add_func("/cutils/qemu_strtoul/underflow",
+ test_qemu_strtoul_underflow);
+ g_test_add_func("/cutils/qemu_strtoul/negative",
+ test_qemu_strtoul_negative);
+ g_test_add_func("/cutils/qemu_strtoul_full/correct",
+ test_qemu_strtoul_full_correct);
+ g_test_add_func("/cutils/qemu_strtoul_full/null",
+ test_qemu_strtoul_full_null);
+ g_test_add_func("/cutils/qemu_strtoul_full/empty",
+ test_qemu_strtoul_full_empty);
+ g_test_add_func("/cutils/qemu_strtoul_full/negative",
+ test_qemu_strtoul_full_negative);
+ g_test_add_func("/cutils/qemu_strtoul_full/trailing",
+ test_qemu_strtoul_full_trailing);
+ g_test_add_func("/cutils/qemu_strtoul_full/max",
+ test_qemu_strtoul_full_max);
+
+ /* qemu_strtoll() tests */
+ g_test_add_func("/cutils/qemu_strtoll/correct", test_qemu_strtoll_correct);
+ g_test_add_func("/cutils/qemu_strtoll/null", test_qemu_strtoll_null);
+ g_test_add_func("/cutils/qemu_strtoll/empty", test_qemu_strtoll_empty);
+ g_test_add_func("/cutils/qemu_strtoll/whitespace",
+ test_qemu_strtoll_whitespace);
+ g_test_add_func("/cutils/qemu_strtoll/invalid", test_qemu_strtoll_invalid);
+ g_test_add_func("/cutils/qemu_strtoll/trailing",
+ test_qemu_strtoll_trailing);
+ g_test_add_func("/cutils/qemu_strtoll/octal", test_qemu_strtoll_octal);
+ g_test_add_func("/cutils/qemu_strtoll/decimal", test_qemu_strtoll_decimal);
+ g_test_add_func("/cutils/qemu_strtoll/hex", test_qemu_strtoll_hex);
+ g_test_add_func("/cutils/qemu_strtoll/max", test_qemu_strtoll_max);
+ g_test_add_func("/cutils/qemu_strtoll/overflow",
+ test_qemu_strtoll_overflow);
+ g_test_add_func("/cutils/qemu_strtoll/underflow",
+ test_qemu_strtoll_underflow);
+ g_test_add_func("/cutils/qemu_strtoll/negative",
+ test_qemu_strtoll_negative);
+ g_test_add_func("/cutils/qemu_strtoll_full/correct",
+ test_qemu_strtoll_full_correct);
+ g_test_add_func("/cutils/qemu_strtoll_full/null",
+ test_qemu_strtoll_full_null);
+ g_test_add_func("/cutils/qemu_strtoll_full/empty",
+ test_qemu_strtoll_full_empty);
+ g_test_add_func("/cutils/qemu_strtoll_full/negative",
+ test_qemu_strtoll_full_negative);
+ g_test_add_func("/cutils/qemu_strtoll_full/trailing",
+ test_qemu_strtoll_full_trailing);
+ g_test_add_func("/cutils/qemu_strtoll_full/max",
+ test_qemu_strtoll_full_max);
+
+ /* qemu_strtoull() tests */
+ g_test_add_func("/cutils/qemu_strtoull/correct",
+ test_qemu_strtoull_correct);
+ g_test_add_func("/cutils/qemu_strtoull/null",
+ test_qemu_strtoull_null);
+ g_test_add_func("/cutils/qemu_strtoull/empty", test_qemu_strtoull_empty);
+ g_test_add_func("/cutils/qemu_strtoull/whitespace",
+ test_qemu_strtoull_whitespace);
+ g_test_add_func("/cutils/qemu_strtoull/invalid",
+ test_qemu_strtoull_invalid);
+ g_test_add_func("/cutils/qemu_strtoull/trailing",
+ test_qemu_strtoull_trailing);
+ g_test_add_func("/cutils/qemu_strtoull/octal", test_qemu_strtoull_octal);
+ g_test_add_func("/cutils/qemu_strtoull/decimal",
+ test_qemu_strtoull_decimal);
+ g_test_add_func("/cutils/qemu_strtoull/hex", test_qemu_strtoull_hex);
+ g_test_add_func("/cutils/qemu_strtoull/max", test_qemu_strtoull_max);
+ g_test_add_func("/cutils/qemu_strtoull/overflow",
+ test_qemu_strtoull_overflow);
+ g_test_add_func("/cutils/qemu_strtoull/underflow",
+ test_qemu_strtoull_underflow);
+ g_test_add_func("/cutils/qemu_strtoull/negative",
+ test_qemu_strtoull_negative);
+ g_test_add_func("/cutils/qemu_strtoull_full/correct",
+ test_qemu_strtoull_full_correct);
+ g_test_add_func("/cutils/qemu_strtoull_full/null",
+ test_qemu_strtoull_full_null);
+ g_test_add_func("/cutils/qemu_strtoull_full/empty",
+ test_qemu_strtoull_full_empty);
+ g_test_add_func("/cutils/qemu_strtoull_full/negative",
+ test_qemu_strtoull_full_negative);
+ g_test_add_func("/cutils/qemu_strtoull_full/trailing",
+ test_qemu_strtoull_full_trailing);
+ g_test_add_func("/cutils/qemu_strtoull_full/max",
+ test_qemu_strtoull_full_max);
+
+ g_test_add_func("/cutils/strtosz/simple",
+ test_qemu_strtosz_simple);
+ g_test_add_func("/cutils/strtosz/units",
+ test_qemu_strtosz_units);
+ g_test_add_func("/cutils/strtosz/float",
+ test_qemu_strtosz_float);
+ g_test_add_func("/cutils/strtosz/erange",
+ test_qemu_strtosz_erange);
+ g_test_add_func("/cutils/strtosz/suffix-unit",
+ test_qemu_strtosz_suffix_unit);
+
return g_test_run();
}
diff --git a/qemu/tests/test-filter-mirror.c b/qemu/tests/test-filter-mirror.c
new file mode 100644
index 000000000..f60bf2adb
--- /dev/null
+++ b/qemu/tests/test-filter-mirror.c
@@ -0,0 +1,93 @@
+/*
+ * QTest testcase for filter-mirror
+ *
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Author: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+#include "libqtest.h"
+#include "qemu/iov.h"
+#include "qemu/sockets.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+
+static void test_mirror(void)
+{
+#ifndef _WIN32
+/* socketpair(PF_UNIX) which does not exist on windows */
+
+ int send_sock[2], recv_sock;
+ char *cmdline;
+ uint32_t ret = 0, len = 0;
+ char send_buf[] = "Hello! filter-mirror~";
+ char sock_path[] = "filter-mirror.XXXXXX";
+ char *recv_buf;
+ uint32_t size = sizeof(send_buf);
+ size = htonl(size);
+
+ ret = socketpair(PF_UNIX, SOCK_STREAM, 0, send_sock);
+ g_assert_cmpint(ret, !=, -1);
+
+ ret = mkstemp(sock_path);
+ g_assert_cmpint(ret, !=, -1);
+
+ cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
+ "-device e1000,netdev=qtest-bn0,id=qtest-e0 "
+ "-chardev socket,id=mirror0,path=%s,server,nowait "
+ "-object filter-mirror,id=qtest-f0,netdev=qtest-bn0,queue=tx,outdev=mirror0 "
+ , send_sock[1], sock_path);
+ qtest_start(cmdline);
+ g_free(cmdline);
+
+ recv_sock = unix_connect(sock_path, NULL);
+ g_assert_cmpint(recv_sock, !=, -1);
+
+ struct iovec iov[] = {
+ {
+ .iov_base = &size,
+ .iov_len = sizeof(size),
+ }, {
+ .iov_base = send_buf,
+ .iov_len = sizeof(send_buf),
+ },
+ };
+
+ /* send a qmp command to guarantee that 'connected' is setting to true. */
+ qmp("{ 'execute' : 'query-status'}");
+ ret = iov_send(send_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_buf));
+ g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
+ close(send_sock[0]);
+
+ ret = qemu_recv(recv_sock, &len, sizeof(len), 0);
+ g_assert_cmpint(ret, ==, sizeof(len));
+ len = ntohl(len);
+
+ g_assert_cmpint(len, ==, sizeof(send_buf));
+ recv_buf = g_malloc(len);
+ ret = qemu_recv(recv_sock, recv_buf, len, 0);
+ g_assert_cmpstr(recv_buf, ==, send_buf);
+
+ g_free(recv_buf);
+ close(recv_sock);
+ unlink(sock_path);
+
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_func("/netfilter/mirror", test_mirror);
+ ret = g_test_run();
+ qtest_end();
+
+ return ret;
+}
diff --git a/qemu/tests/test-filter-redirector.c b/qemu/tests/test-filter-redirector.c
new file mode 100644
index 000000000..b93012cea
--- /dev/null
+++ b/qemu/tests/test-filter-redirector.c
@@ -0,0 +1,221 @@
+/*
+ * QTest testcase for filter-redirector
+ *
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Author: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ *
+ * Case 1, tx traffic flow:
+ *
+ * qemu side | test side
+ * |
+ * +---------+ | +-------+
+ * | backend <---------------+ sock0 |
+ * +----+----+ | +-------+
+ * | |
+ * +----v----+ +-------+ |
+ * | rd0 +->+chardev| |
+ * +---------+ +---+---+ |
+ * | |
+ * +---------+ | |
+ * | rd1 <------+ |
+ * +----+----+ |
+ * | |
+ * +----v----+ | +-------+
+ * | rd2 +--------------->sock1 |
+ * +---------+ | +-------+
+ * +
+ *
+ * --------------------------------------
+ * Case 2, rx traffic flow
+ * qemu side | test side
+ * |
+ * +---------+ | +-------+
+ * | backend +---------------> sock1 |
+ * +----^----+ | +-------+
+ * | |
+ * +----+----+ +-------+ |
+ * | rd0 +<-+chardev| |
+ * +---------+ +---+---+ |
+ * ^ |
+ * +---------+ | |
+ * | rd1 +------+ |
+ * +----^----+ |
+ * | |
+ * +----+----+ | +-------+
+ * | rd2 <---------------+sock0 |
+ * +---------+ | +-------+
+ * +
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+#include "libqtest.h"
+#include "qemu/iov.h"
+#include "qemu/sockets.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+
+static void test_redirector_tx(void)
+{
+#ifndef _WIN32
+/* socketpair(PF_UNIX) which does not exist on windows */
+
+ int backend_sock[2], recv_sock;
+ char *cmdline;
+ uint32_t ret = 0, len = 0;
+ char send_buf[] = "Hello!!";
+ char sock_path0[] = "filter-redirector0.XXXXXX";
+ char sock_path1[] = "filter-redirector1.XXXXXX";
+ char *recv_buf;
+ uint32_t size = sizeof(send_buf);
+ size = htonl(size);
+
+ ret = socketpair(PF_UNIX, SOCK_STREAM, 0, backend_sock);
+ g_assert_cmpint(ret, !=, -1);
+
+ ret = mkstemp(sock_path0);
+ g_assert_cmpint(ret, !=, -1);
+ ret = mkstemp(sock_path1);
+ g_assert_cmpint(ret, !=, -1);
+
+ cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
+ "-device rtl8139,netdev=qtest-bn0,id=qtest-e0 "
+ "-chardev socket,id=redirector0,path=%s,server,nowait "
+ "-chardev socket,id=redirector1,path=%s,server,nowait "
+ "-chardev socket,id=redirector2,path=%s,nowait "
+ "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0,"
+ "queue=tx,outdev=redirector0 "
+ "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
+ "queue=tx,indev=redirector2 "
+ "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0,"
+ "queue=tx,outdev=redirector1 "
+ , backend_sock[1], sock_path0, sock_path1, sock_path0);
+ qtest_start(cmdline);
+ g_free(cmdline);
+
+ recv_sock = unix_connect(sock_path1, NULL);
+ g_assert_cmpint(recv_sock, !=, -1);
+
+ /* send a qmp command to guarantee that 'connected' is setting to true. */
+ qmp("{ 'execute' : 'query-status'}");
+
+ struct iovec iov[] = {
+ {
+ .iov_base = &size,
+ .iov_len = sizeof(size),
+ }, {
+ .iov_base = send_buf,
+ .iov_len = sizeof(send_buf),
+ },
+ };
+
+ ret = iov_send(backend_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_buf));
+ g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
+ close(backend_sock[0]);
+
+ ret = qemu_recv(recv_sock, &len, sizeof(len), 0);
+ g_assert_cmpint(ret, ==, sizeof(len));
+ len = ntohl(len);
+
+ g_assert_cmpint(len, ==, sizeof(send_buf));
+ recv_buf = g_malloc(len);
+ ret = qemu_recv(recv_sock, recv_buf, len, 0);
+ g_assert_cmpstr(recv_buf, ==, send_buf);
+
+ g_free(recv_buf);
+ close(recv_sock);
+ unlink(sock_path0);
+ unlink(sock_path1);
+ qtest_end();
+
+#endif
+}
+
+static void test_redirector_rx(void)
+{
+#ifndef _WIN32
+/* socketpair(PF_UNIX) which does not exist on windows */
+
+ int backend_sock[2], send_sock;
+ char *cmdline;
+ uint32_t ret = 0, len = 0;
+ char send_buf[] = "Hello!!";
+ char sock_path0[] = "filter-redirector0.XXXXXX";
+ char sock_path1[] = "filter-redirector1.XXXXXX";
+ char *recv_buf;
+ uint32_t size = sizeof(send_buf);
+ size = htonl(size);
+
+ ret = socketpair(PF_UNIX, SOCK_STREAM, 0, backend_sock);
+ g_assert_cmpint(ret, !=, -1);
+
+ ret = mkstemp(sock_path0);
+ g_assert_cmpint(ret, !=, -1);
+ ret = mkstemp(sock_path1);
+ g_assert_cmpint(ret, !=, -1);
+
+ cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
+ "-device rtl8139,netdev=qtest-bn0,id=qtest-e0 "
+ "-chardev socket,id=redirector0,path=%s,server,nowait "
+ "-chardev socket,id=redirector1,path=%s,server,nowait "
+ "-chardev socket,id=redirector2,path=%s,nowait "
+ "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0,"
+ "queue=rx,indev=redirector0 "
+ "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
+ "queue=rx,outdev=redirector2 "
+ "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0,"
+ "queue=rx,indev=redirector1 "
+ , backend_sock[1], sock_path0, sock_path1, sock_path0);
+ qtest_start(cmdline);
+ g_free(cmdline);
+
+ struct iovec iov[] = {
+ {
+ .iov_base = &size,
+ .iov_len = sizeof(size),
+ }, {
+ .iov_base = send_buf,
+ .iov_len = sizeof(send_buf),
+ },
+ };
+
+ send_sock = unix_connect(sock_path1, NULL);
+ g_assert_cmpint(send_sock, !=, -1);
+ /* send a qmp command to guarantee that 'connected' is setting to true. */
+ qmp("{ 'execute' : 'query-status'}");
+
+ ret = iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf));
+ g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
+ close(send_sock);
+
+ ret = qemu_recv(backend_sock[0], &len, sizeof(len), 0);
+ g_assert_cmpint(ret, ==, sizeof(len));
+ len = ntohl(len);
+
+ g_assert_cmpint(len, ==, sizeof(send_buf));
+ recv_buf = g_malloc(len);
+ ret = qemu_recv(backend_sock[0], recv_buf, len, 0);
+ g_assert_cmpstr(recv_buf, ==, send_buf);
+
+ g_free(recv_buf);
+ unlink(sock_path0);
+ unlink(sock_path1);
+ qtest_end();
+
+#endif
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/netfilter/redirector_tx", test_redirector_tx);
+ qtest_add_func("/netfilter/redirector_rx", test_redirector_rx);
+ ret = g_test_run();
+
+ return ret;
+}
diff --git a/qemu/tests/test-hbitmap.c b/qemu/tests/test-hbitmap.c
index 161eeb496..abe142791 100644
--- a/qemu/tests/test-hbitmap.c
+++ b/qemu/tests/test-hbitmap.c
@@ -9,10 +9,8 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <sys/types.h>
#include "qemu/hbitmap.h"
#define LOG_BITS_PER_LONG (BITS_PER_LONG == 32 ? 5 : 6)
@@ -139,10 +137,8 @@ static void hbitmap_test_teardown(TestHBitmapData *data,
hbitmap_free(data->hb);
data->hb = NULL;
}
- if (data->bits) {
- g_free(data->bits);
- data->bits = NULL;
- }
+ g_free(data->bits);
+ data->bits = NULL;
}
/* Set a range in the HBitmap and in the shadow "simple" bitmap.
diff --git a/qemu/tests/test-int128.c b/qemu/tests/test-int128.c
index 0772ef753..cacf6beac 100644
--- a/qemu/tests/test-int128.c
+++ b/qemu/tests/test-int128.c
@@ -6,10 +6,9 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdio.h>
#include "qemu/int128.h"
-#include "qemu/osdep.h"
/* clang doesn't support __noclone__ but it does have a mechanism for
* telling us this. We assume that if we don't have __has_attribute()
diff --git a/qemu/tests/test-io-channel-buffer.c b/qemu/tests/test-io-channel-buffer.c
new file mode 100644
index 000000000..64722a214
--- /dev/null
+++ b/qemu/tests/test-io-channel-buffer.c
@@ -0,0 +1,51 @@
+/*
+ * QEMU I/O channel buffer test
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "io/channel-buffer.h"
+#include "io-channel-helpers.h"
+
+
+static void test_io_channel_buf(void)
+{
+ QIOChannelBuffer *buf;
+ QIOChannelTest *test;
+
+ buf = qio_channel_buffer_new(0);
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_writer(test, QIO_CHANNEL(buf));
+ buf->offset = 0;
+ qio_channel_test_run_reader(test, QIO_CHANNEL(buf));
+ qio_channel_test_validate(test);
+
+ object_unref(OBJECT(buf));
+}
+
+
+int main(int argc, char **argv)
+{
+ module_call_init(MODULE_INIT_QOM);
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/io/channel/buf", test_io_channel_buf);
+ return g_test_run();
+}
diff --git a/qemu/tests/test-io-channel-command.c b/qemu/tests/test-io-channel-command.c
new file mode 100644
index 000000000..1d1f461be
--- /dev/null
+++ b/qemu/tests/test-io-channel-command.c
@@ -0,0 +1,131 @@
+/*
+ * QEMU I/O channel command test
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "io/channel-command.h"
+#include "io-channel-helpers.h"
+#include "qapi/error.h"
+
+#ifndef WIN32
+static void test_io_channel_command_fifo(bool async)
+{
+#define TEST_FIFO "tests/test-io-channel-command.fifo"
+ QIOChannel *src, *dst;
+ QIOChannelTest *test;
+ char *srcfifo = g_strdup_printf("PIPE:%s,wronly", TEST_FIFO);
+ char *dstfifo = g_strdup_printf("PIPE:%s,rdonly", TEST_FIFO);
+ const char *srcargv[] = {
+ "/bin/socat", "-", srcfifo, NULL,
+ };
+ const char *dstargv[] = {
+ "/bin/socat", dstfifo, "-", NULL,
+ };
+
+ unlink(TEST_FIFO);
+ if (access("/bin/socat", X_OK) < 0) {
+ return; /* Pretend success if socat is not present */
+ }
+ if (mkfifo(TEST_FIFO, 0600) < 0) {
+ abort();
+ }
+ src = QIO_CHANNEL(qio_channel_command_new_spawn(srcargv,
+ O_WRONLY,
+ &error_abort));
+ dst = QIO_CHANNEL(qio_channel_command_new_spawn(dstargv,
+ O_RDONLY,
+ &error_abort));
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_threads(test, async, src, dst);
+ qio_channel_test_validate(test);
+
+ object_unref(OBJECT(src));
+ object_unref(OBJECT(dst));
+
+ g_free(srcfifo);
+ g_free(dstfifo);
+ unlink(TEST_FIFO);
+}
+
+
+static void test_io_channel_command_fifo_async(void)
+{
+ test_io_channel_command_fifo(true);
+}
+
+static void test_io_channel_command_fifo_sync(void)
+{
+ test_io_channel_command_fifo(false);
+}
+
+
+static void test_io_channel_command_echo(bool async)
+{
+ QIOChannel *ioc;
+ QIOChannelTest *test;
+ const char *socatargv[] = {
+ "/bin/socat", "-", "-", NULL,
+ };
+
+ if (access("/bin/socat", X_OK) < 0) {
+ return; /* Pretend success if socat is not present */
+ }
+
+ ioc = QIO_CHANNEL(qio_channel_command_new_spawn(socatargv,
+ O_RDWR,
+ &error_abort));
+ test = qio_channel_test_new();
+ qio_channel_test_run_threads(test, async, ioc, ioc);
+ qio_channel_test_validate(test);
+
+ object_unref(OBJECT(ioc));
+}
+
+
+static void test_io_channel_command_echo_async(void)
+{
+ test_io_channel_command_echo(true);
+}
+
+static void test_io_channel_command_echo_sync(void)
+{
+ test_io_channel_command_echo(false);
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ module_call_init(MODULE_INIT_QOM);
+
+ g_test_init(&argc, &argv, NULL);
+
+#ifndef WIN32
+ g_test_add_func("/io/channel/command/fifo/sync",
+ test_io_channel_command_fifo_sync);
+ g_test_add_func("/io/channel/command/fifo/async",
+ test_io_channel_command_fifo_async);
+ g_test_add_func("/io/channel/command/echo/sync",
+ test_io_channel_command_echo_sync);
+ g_test_add_func("/io/channel/command/echo/async",
+ test_io_channel_command_echo_async);
+#endif
+
+ return g_test_run();
+}
diff --git a/qemu/tests/test-io-channel-file.c b/qemu/tests/test-io-channel-file.c
new file mode 100644
index 000000000..6bfede6bb
--- /dev/null
+++ b/qemu/tests/test-io-channel-file.c
@@ -0,0 +1,123 @@
+/*
+ * QEMU I/O channel file test
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "io/channel-file.h"
+#include "io/channel-util.h"
+#include "io-channel-helpers.h"
+#include "qapi/error.h"
+
+static void test_io_channel_file(void)
+{
+ QIOChannel *src, *dst;
+ QIOChannelTest *test;
+
+#define TEST_FILE "tests/test-io-channel-file.txt"
+ unlink(TEST_FILE);
+ src = QIO_CHANNEL(qio_channel_file_new_path(
+ TEST_FILE,
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600,
+ &error_abort));
+ dst = QIO_CHANNEL(qio_channel_file_new_path(
+ TEST_FILE,
+ O_RDONLY | O_BINARY, 0,
+ &error_abort));
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_writer(test, src);
+ qio_channel_test_run_reader(test, dst);
+ qio_channel_test_validate(test);
+
+ unlink(TEST_FILE);
+ object_unref(OBJECT(src));
+ object_unref(OBJECT(dst));
+}
+
+
+static void test_io_channel_fd(void)
+{
+ QIOChannel *ioc;
+ int fd = -1;
+
+#define TEST_FILE "tests/test-io-channel-file.txt"
+ fd = open(TEST_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0600);
+ g_assert_cmpint(fd, >, -1);
+
+ ioc = qio_channel_new_fd(fd, &error_abort);
+
+ g_assert_cmpstr(object_get_typename(OBJECT(ioc)),
+ ==,
+ TYPE_QIO_CHANNEL_FILE);
+
+ unlink(TEST_FILE);
+ object_unref(OBJECT(ioc));
+}
+
+
+#ifndef _WIN32
+static void test_io_channel_pipe(bool async)
+{
+ QIOChannel *src, *dst;
+ QIOChannelTest *test;
+ int fd[2];
+
+ if (pipe(fd) < 0) {
+ perror("pipe");
+ abort();
+ }
+
+ src = QIO_CHANNEL(qio_channel_file_new_fd(fd[1]));
+ dst = QIO_CHANNEL(qio_channel_file_new_fd(fd[0]));
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_threads(test, async, src, dst);
+ qio_channel_test_validate(test);
+
+ object_unref(OBJECT(src));
+ object_unref(OBJECT(dst));
+}
+
+
+static void test_io_channel_pipe_async(void)
+{
+ test_io_channel_pipe(true);
+}
+
+static void test_io_channel_pipe_sync(void)
+{
+ test_io_channel_pipe(false);
+}
+#endif /* ! _WIN32 */
+
+
+int main(int argc, char **argv)
+{
+ module_call_init(MODULE_INIT_QOM);
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/io/channel/file", test_io_channel_file);
+ g_test_add_func("/io/channel/file/fd", test_io_channel_fd);
+#ifndef _WIN32
+ g_test_add_func("/io/channel/pipe/sync", test_io_channel_pipe_sync);
+ g_test_add_func("/io/channel/pipe/async", test_io_channel_pipe_async);
+#endif
+ return g_test_run();
+}
diff --git a/qemu/tests/test-io-channel-socket.c b/qemu/tests/test-io-channel-socket.c
new file mode 100644
index 000000000..855306b8d
--- /dev/null
+++ b/qemu/tests/test-io-channel-socket.c
@@ -0,0 +1,568 @@
+/*
+ * QEMU I/O channel sockets test
+ *
+ * Copyright (c) 2015-2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "io/channel-socket.h"
+#include "io/channel-util.h"
+#include "io-channel-helpers.h"
+#include "qapi/error.h"
+
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+#ifndef EAI_ADDRFAMILY
+# define EAI_ADDRFAMILY 0
+#endif
+
+static int check_bind(const char *hostname, bool *has_proto)
+{
+ int fd = -1;
+ struct addrinfo ai, *res = NULL;
+ int rc;
+ int ret = -1;
+
+ memset(&ai, 0, sizeof(ai));
+ ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
+ ai.ai_family = AF_UNSPEC;
+ ai.ai_socktype = SOCK_STREAM;
+
+ /* lookup */
+ rc = getaddrinfo(hostname, NULL, &ai, &res);
+ if (rc != 0) {
+ if (rc == EAI_ADDRFAMILY ||
+ rc == EAI_FAMILY) {
+ *has_proto = false;
+ goto done;
+ }
+ goto cleanup;
+ }
+
+ fd = qemu_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (fd < 0) {
+ goto cleanup;
+ }
+
+ if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
+ if (errno == EADDRNOTAVAIL) {
+ *has_proto = false;
+ goto done;
+ }
+ goto cleanup;
+ }
+
+ *has_proto = true;
+ done:
+ ret = 0;
+
+ cleanup:
+ if (fd != -1) {
+ close(fd);
+ }
+ if (res) {
+ freeaddrinfo(res);
+ }
+ return ret;
+}
+
+static int check_protocol_support(bool *has_ipv4, bool *has_ipv6)
+{
+ if (check_bind("127.0.0.1", has_ipv4) < 0) {
+ return -1;
+ }
+ if (check_bind("::1", has_ipv6) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void test_io_channel_set_socket_bufs(QIOChannel *src,
+ QIOChannel *dst)
+{
+ int buflen = 64 * 1024;
+
+ /*
+ * Make the socket buffers small so that we see
+ * the effects of partial reads/writes
+ */
+ setsockopt(((QIOChannelSocket *)src)->fd,
+ SOL_SOCKET, SO_SNDBUF,
+ (char *)&buflen,
+ sizeof(buflen));
+
+ setsockopt(((QIOChannelSocket *)dst)->fd,
+ SOL_SOCKET, SO_SNDBUF,
+ (char *)&buflen,
+ sizeof(buflen));
+}
+
+
+static void test_io_channel_setup_sync(SocketAddress *listen_addr,
+ SocketAddress *connect_addr,
+ QIOChannel **src,
+ QIOChannel **dst)
+{
+ QIOChannelSocket *lioc;
+
+ lioc = qio_channel_socket_new();
+ qio_channel_socket_listen_sync(lioc, listen_addr, &error_abort);
+
+ if (listen_addr->type == SOCKET_ADDRESS_KIND_INET) {
+ SocketAddress *laddr = qio_channel_socket_get_local_address(
+ lioc, &error_abort);
+
+ g_free(connect_addr->u.inet.data->port);
+ connect_addr->u.inet.data->port = g_strdup(laddr->u.inet.data->port);
+
+ qapi_free_SocketAddress(laddr);
+ }
+
+ *src = QIO_CHANNEL(qio_channel_socket_new());
+ qio_channel_socket_connect_sync(
+ QIO_CHANNEL_SOCKET(*src), connect_addr, &error_abort);
+ qio_channel_set_delay(*src, false);
+
+ qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN);
+ *dst = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort));
+ g_assert(*dst);
+
+ test_io_channel_set_socket_bufs(*src, *dst);
+
+ object_unref(OBJECT(lioc));
+}
+
+
+struct TestIOChannelData {
+ bool err;
+ GMainLoop *loop;
+};
+
+
+static void test_io_channel_complete(Object *src,
+ Error *err,
+ gpointer opaque)
+{
+ struct TestIOChannelData *data = opaque;
+ data->err = err != NULL;
+ g_main_loop_quit(data->loop);
+}
+
+
+static void test_io_channel_setup_async(SocketAddress *listen_addr,
+ SocketAddress *connect_addr,
+ QIOChannel **src,
+ QIOChannel **dst)
+{
+ QIOChannelSocket *lioc;
+ struct TestIOChannelData data;
+
+ data.loop = g_main_loop_new(g_main_context_default(),
+ TRUE);
+
+ lioc = qio_channel_socket_new();
+ qio_channel_socket_listen_async(
+ lioc, listen_addr,
+ test_io_channel_complete, &data, NULL);
+
+ g_main_loop_run(data.loop);
+ g_main_context_iteration(g_main_context_default(), FALSE);
+
+ g_assert(!data.err);
+
+ if (listen_addr->type == SOCKET_ADDRESS_KIND_INET) {
+ SocketAddress *laddr = qio_channel_socket_get_local_address(
+ lioc, &error_abort);
+
+ g_free(connect_addr->u.inet.data->port);
+ connect_addr->u.inet.data->port = g_strdup(laddr->u.inet.data->port);
+
+ qapi_free_SocketAddress(laddr);
+ }
+
+ *src = QIO_CHANNEL(qio_channel_socket_new());
+
+ qio_channel_socket_connect_async(
+ QIO_CHANNEL_SOCKET(*src), connect_addr,
+ test_io_channel_complete, &data, NULL);
+
+ g_main_loop_run(data.loop);
+ g_main_context_iteration(g_main_context_default(), FALSE);
+
+ g_assert(!data.err);
+
+ qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN);
+ *dst = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort));
+ g_assert(*dst);
+
+ qio_channel_set_delay(*src, false);
+ test_io_channel_set_socket_bufs(*src, *dst);
+
+ object_unref(OBJECT(lioc));
+
+ g_main_loop_unref(data.loop);
+}
+
+
+static void test_io_channel(bool async,
+ SocketAddress *listen_addr,
+ SocketAddress *connect_addr,
+ bool passFD)
+{
+ QIOChannel *src, *dst;
+ QIOChannelTest *test;
+ if (async) {
+ test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst);
+
+ g_assert(!passFD ||
+ qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
+ g_assert(!passFD ||
+ qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_threads(test, true, src, dst);
+ qio_channel_test_validate(test);
+
+ object_unref(OBJECT(src));
+ object_unref(OBJECT(dst));
+
+ test_io_channel_setup_async(listen_addr, connect_addr, &src, &dst);
+
+ g_assert(!passFD ||
+ qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
+ g_assert(!passFD ||
+ qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_threads(test, false, src, dst);
+ qio_channel_test_validate(test);
+
+ object_unref(OBJECT(src));
+ object_unref(OBJECT(dst));
+ } else {
+ test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
+
+ g_assert(!passFD ||
+ qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
+ g_assert(!passFD ||
+ qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_threads(test, true, src, dst);
+ qio_channel_test_validate(test);
+
+ object_unref(OBJECT(src));
+ object_unref(OBJECT(dst));
+
+ test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
+
+ g_assert(!passFD ||
+ qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
+ g_assert(!passFD ||
+ qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_threads(test, false, src, dst);
+ qio_channel_test_validate(test);
+
+ object_unref(OBJECT(src));
+ object_unref(OBJECT(dst));
+ }
+}
+
+
+static void test_io_channel_ipv4(bool async)
+{
+ SocketAddress *listen_addr = g_new0(SocketAddress, 1);
+ SocketAddress *connect_addr = g_new0(SocketAddress, 1);
+
+ listen_addr->type = SOCKET_ADDRESS_KIND_INET;
+ listen_addr->u.inet.data = g_new(InetSocketAddress, 1);
+ *listen_addr->u.inet.data = (InetSocketAddress) {
+ .host = g_strdup("127.0.0.1"),
+ .port = NULL, /* Auto-select */
+ };
+
+ connect_addr->type = SOCKET_ADDRESS_KIND_INET;
+ connect_addr->u.inet.data = g_new(InetSocketAddress, 1);
+ *connect_addr->u.inet.data = (InetSocketAddress) {
+ .host = g_strdup("127.0.0.1"),
+ .port = NULL, /* Filled in later */
+ };
+
+ test_io_channel(async, listen_addr, connect_addr, false);
+
+ qapi_free_SocketAddress(listen_addr);
+ qapi_free_SocketAddress(connect_addr);
+}
+
+
+static void test_io_channel_ipv4_sync(void)
+{
+ return test_io_channel_ipv4(false);
+}
+
+
+static void test_io_channel_ipv4_async(void)
+{
+ return test_io_channel_ipv4(true);
+}
+
+
+static void test_io_channel_ipv6(bool async)
+{
+ SocketAddress *listen_addr = g_new0(SocketAddress, 1);
+ SocketAddress *connect_addr = g_new0(SocketAddress, 1);
+
+ listen_addr->type = SOCKET_ADDRESS_KIND_INET;
+ listen_addr->u.inet.data = g_new(InetSocketAddress, 1);
+ *listen_addr->u.inet.data = (InetSocketAddress) {
+ .host = g_strdup("::1"),
+ .port = NULL, /* Auto-select */
+ };
+
+ connect_addr->type = SOCKET_ADDRESS_KIND_INET;
+ connect_addr->u.inet.data = g_new(InetSocketAddress, 1);
+ *connect_addr->u.inet.data = (InetSocketAddress) {
+ .host = g_strdup("::1"),
+ .port = NULL, /* Filled in later */
+ };
+
+ test_io_channel(async, listen_addr, connect_addr, false);
+
+ qapi_free_SocketAddress(listen_addr);
+ qapi_free_SocketAddress(connect_addr);
+}
+
+
+static void test_io_channel_ipv6_sync(void)
+{
+ return test_io_channel_ipv6(false);
+}
+
+
+static void test_io_channel_ipv6_async(void)
+{
+ return test_io_channel_ipv6(true);
+}
+
+
+#ifndef _WIN32
+static void test_io_channel_unix(bool async)
+{
+ SocketAddress *listen_addr = g_new0(SocketAddress, 1);
+ SocketAddress *connect_addr = g_new0(SocketAddress, 1);
+
+#define TEST_SOCKET "test-io-channel-socket.sock"
+ listen_addr->type = SOCKET_ADDRESS_KIND_UNIX;
+ listen_addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
+ listen_addr->u.q_unix.data->path = g_strdup(TEST_SOCKET);
+
+ connect_addr->type = SOCKET_ADDRESS_KIND_UNIX;
+ connect_addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
+ connect_addr->u.q_unix.data->path = g_strdup(TEST_SOCKET);
+
+ test_io_channel(async, listen_addr, connect_addr, true);
+
+ qapi_free_SocketAddress(listen_addr);
+ qapi_free_SocketAddress(connect_addr);
+ unlink(TEST_SOCKET);
+}
+
+
+static void test_io_channel_unix_sync(void)
+{
+ return test_io_channel_unix(false);
+}
+
+
+static void test_io_channel_unix_async(void)
+{
+ return test_io_channel_unix(true);
+}
+
+static void test_io_channel_unix_fd_pass(void)
+{
+ SocketAddress *listen_addr = g_new0(SocketAddress, 1);
+ SocketAddress *connect_addr = g_new0(SocketAddress, 1);
+ QIOChannel *src, *dst;
+ int testfd;
+ int fdsend[3];
+ int *fdrecv = NULL;
+ size_t nfdrecv = 0;
+ size_t i;
+ char bufsend[12], bufrecv[12];
+ struct iovec iosend[1], iorecv[1];
+
+#define TEST_SOCKET "test-io-channel-socket.sock"
+#define TEST_FILE "test-io-channel-socket.txt"
+
+ testfd = open(TEST_FILE, O_RDWR|O_TRUNC|O_CREAT, 0700);
+ g_assert(testfd != -1);
+ fdsend[0] = testfd;
+ fdsend[1] = testfd;
+ fdsend[2] = testfd;
+
+ listen_addr->type = SOCKET_ADDRESS_KIND_UNIX;
+ listen_addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
+ listen_addr->u.q_unix.data->path = g_strdup(TEST_SOCKET);
+
+ connect_addr->type = SOCKET_ADDRESS_KIND_UNIX;
+ connect_addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
+ connect_addr->u.q_unix.data->path = g_strdup(TEST_SOCKET);
+
+ test_io_channel_setup_sync(listen_addr, connect_addr, &src, &dst);
+
+ memcpy(bufsend, "Hello World", G_N_ELEMENTS(bufsend));
+
+ iosend[0].iov_base = bufsend;
+ iosend[0].iov_len = G_N_ELEMENTS(bufsend);
+
+ iorecv[0].iov_base = bufrecv;
+ iorecv[0].iov_len = G_N_ELEMENTS(bufrecv);
+
+ g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS));
+ g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS));
+
+ qio_channel_writev_full(src,
+ iosend,
+ G_N_ELEMENTS(iosend),
+ fdsend,
+ G_N_ELEMENTS(fdsend),
+ &error_abort);
+
+ qio_channel_readv_full(dst,
+ iorecv,
+ G_N_ELEMENTS(iorecv),
+ &fdrecv,
+ &nfdrecv,
+ &error_abort);
+
+ g_assert(nfdrecv == G_N_ELEMENTS(fdsend));
+ /* Each recvd FD should be different from sent FD */
+ for (i = 0; i < nfdrecv; i++) {
+ g_assert_cmpint(fdrecv[i], !=, testfd);
+ }
+ /* Each recvd FD should be different from each other */
+ g_assert_cmpint(fdrecv[0], !=, fdrecv[1]);
+ g_assert_cmpint(fdrecv[0], !=, fdrecv[2]);
+ g_assert_cmpint(fdrecv[1], !=, fdrecv[2]);
+
+ /* Check the I/O buf we sent at the same time matches */
+ g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);
+
+ /* Write some data into the FD we received */
+ g_assert(write(fdrecv[0], bufsend, G_N_ELEMENTS(bufsend)) ==
+ G_N_ELEMENTS(bufsend));
+
+ /* Read data from the original FD and make sure it matches */
+ memset(bufrecv, 0, G_N_ELEMENTS(bufrecv));
+ g_assert(lseek(testfd, 0, SEEK_SET) == 0);
+ g_assert(read(testfd, bufrecv, G_N_ELEMENTS(bufrecv)) ==
+ G_N_ELEMENTS(bufrecv));
+ g_assert(memcmp(bufsend, bufrecv, G_N_ELEMENTS(bufsend)) == 0);
+
+ object_unref(OBJECT(src));
+ object_unref(OBJECT(dst));
+ qapi_free_SocketAddress(listen_addr);
+ qapi_free_SocketAddress(connect_addr);
+ unlink(TEST_SOCKET);
+ unlink(TEST_FILE);
+ close(testfd);
+ for (i = 0; i < nfdrecv; i++) {
+ close(fdrecv[i]);
+ }
+ g_free(fdrecv);
+}
+#endif /* _WIN32 */
+
+
+static void test_io_channel_ipv4_fd(void)
+{
+ QIOChannel *ioc;
+ int fd = -1;
+ struct sockaddr_in sa = {
+ .sin_family = AF_INET,
+ .sin_addr = {
+ .s_addr = htonl(INADDR_LOOPBACK),
+ }
+ /* Leave port unset for auto-assign */
+ };
+ socklen_t salen = sizeof(sa);
+
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ g_assert_cmpint(fd, >, -1);
+
+ g_assert_cmpint(bind(fd, (struct sockaddr *)&sa, salen), ==, 0);
+
+ ioc = qio_channel_new_fd(fd, &error_abort);
+
+ g_assert_cmpstr(object_get_typename(OBJECT(ioc)),
+ ==,
+ TYPE_QIO_CHANNEL_SOCKET);
+
+ object_unref(OBJECT(ioc));
+}
+
+
+int main(int argc, char **argv)
+{
+ bool has_ipv4, has_ipv6;
+
+ module_call_init(MODULE_INIT_QOM);
+ socket_init();
+
+ g_test_init(&argc, &argv, NULL);
+
+ /* We're creating actual IPv4/6 sockets, so we should
+ * check if the host running tests actually supports
+ * each protocol to avoid breaking tests on machines
+ * with either IPv4 or IPv6 disabled.
+ */
+ if (check_protocol_support(&has_ipv4, &has_ipv6) < 0) {
+ return 1;
+ }
+
+ if (has_ipv4) {
+ g_test_add_func("/io/channel/socket/ipv4-sync",
+ test_io_channel_ipv4_sync);
+ g_test_add_func("/io/channel/socket/ipv4-async",
+ test_io_channel_ipv4_async);
+ g_test_add_func("/io/channel/socket/ipv4-fd",
+ test_io_channel_ipv4_fd);
+ }
+ if (has_ipv6) {
+ g_test_add_func("/io/channel/socket/ipv6-sync",
+ test_io_channel_ipv6_sync);
+ g_test_add_func("/io/channel/socket/ipv6-async",
+ test_io_channel_ipv6_async);
+ }
+
+#ifndef _WIN32
+ g_test_add_func("/io/channel/socket/unix-sync",
+ test_io_channel_unix_sync);
+ g_test_add_func("/io/channel/socket/unix-async",
+ test_io_channel_unix_async);
+ g_test_add_func("/io/channel/socket/unix-fd-pass",
+ test_io_channel_unix_fd_pass);
+#endif /* _WIN32 */
+
+ return g_test_run();
+}
diff --git a/qemu/tests/test-io-channel-tls.c b/qemu/tests/test-io-channel-tls.c
new file mode 100644
index 000000000..3c361a7be
--- /dev/null
+++ b/qemu/tests/test-io-channel-tls.c
@@ -0,0 +1,340 @@
+/*
+ * QEMU I/O channel TLS test
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Daniel P. Berrange <berrange@redhat.com>
+ */
+
+
+#include "qemu/osdep.h"
+
+#include "crypto-tls-x509-helpers.h"
+#include "io/channel-tls.h"
+#include "io/channel-socket.h"
+#include "io-channel-helpers.h"
+#include "crypto/tlscredsx509.h"
+#include "qemu/acl.h"
+#include "qom/object_interfaces.h"
+
+#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT
+
+#define WORKDIR "tests/test-io-channel-tls-work/"
+#define KEYFILE WORKDIR "key-ctx.pem"
+
+struct QIOChannelTLSTestData {
+ const char *servercacrt;
+ const char *clientcacrt;
+ const char *servercrt;
+ const char *clientcrt;
+ bool expectServerFail;
+ bool expectClientFail;
+ const char *hostname;
+ const char *const *wildcards;
+};
+
+struct QIOChannelTLSHandshakeData {
+ bool finished;
+ bool failed;
+};
+
+static void test_tls_handshake_done(Object *source,
+ Error *err,
+ gpointer opaque)
+{
+ struct QIOChannelTLSHandshakeData *data = opaque;
+
+ data->finished = true;
+ data->failed = err != NULL;
+}
+
+
+static QCryptoTLSCreds *test_tls_creds_create(QCryptoTLSCredsEndpoint endpoint,
+ const char *certdir,
+ Error **errp)
+{
+ Object *parent = object_get_objects_root();
+ Object *creds = object_new_with_props(
+ TYPE_QCRYPTO_TLS_CREDS_X509,
+ parent,
+ (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ?
+ "testtlscredsserver" : "testtlscredsclient"),
+ errp,
+ "endpoint", (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ?
+ "server" : "client"),
+ "dir", certdir,
+ "verify-peer", "yes",
+ /* We skip initial sanity checks here because we
+ * want to make sure that problems are being
+ * detected at the TLS session validation stage,
+ * and the test-crypto-tlscreds test already
+ * validate the sanity check code.
+ */
+ "sanity-check", "no",
+ NULL
+ );
+
+ if (*errp) {
+ return NULL;
+ }
+ return QCRYPTO_TLS_CREDS(creds);
+}
+
+
+/*
+ * This tests validation checking of peer certificates
+ *
+ * This is replicating the checks that are done for an
+ * active TLS session after handshake completes. To
+ * simulate that we create our TLS contexts, skipping
+ * sanity checks. When then get a socketpair, and
+ * initiate a TLS session across them. Finally do
+ * do actual cert validation tests
+ */
+static void test_io_channel_tls(const void *opaque)
+{
+ struct QIOChannelTLSTestData *data =
+ (struct QIOChannelTLSTestData *)opaque;
+ QCryptoTLSCreds *clientCreds;
+ QCryptoTLSCreds *serverCreds;
+ QIOChannelTLS *clientChanTLS;
+ QIOChannelTLS *serverChanTLS;
+ QIOChannelSocket *clientChanSock;
+ QIOChannelSocket *serverChanSock;
+ qemu_acl *acl;
+ const char * const *wildcards;
+ int channel[2];
+ struct QIOChannelTLSHandshakeData clientHandshake = { false, false };
+ struct QIOChannelTLSHandshakeData serverHandshake = { false, false };
+ Error *err = NULL;
+ QIOChannelTest *test;
+ GMainContext *mainloop;
+
+ /* We'll use this for our fake client-server connection */
+ g_assert(socketpair(AF_UNIX, SOCK_STREAM, 0, channel) == 0);
+
+#define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/"
+#define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/"
+ mkdir(CLIENT_CERT_DIR, 0700);
+ mkdir(SERVER_CERT_DIR, 0700);
+
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT);
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY);
+
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
+
+ g_assert(link(data->servercacrt,
+ SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0);
+ g_assert(link(data->servercrt,
+ SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT) == 0);
+ g_assert(link(KEYFILE,
+ SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY) == 0);
+
+ g_assert(link(data->clientcacrt,
+ CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0);
+ g_assert(link(data->clientcrt,
+ CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT) == 0);
+ g_assert(link(KEYFILE,
+ CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY) == 0);
+
+ clientCreds = test_tls_creds_create(
+ QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
+ CLIENT_CERT_DIR,
+ &err);
+ g_assert(clientCreds != NULL);
+
+ serverCreds = test_tls_creds_create(
+ QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
+ SERVER_CERT_DIR,
+ &err);
+ g_assert(serverCreds != NULL);
+
+ acl = qemu_acl_init("channeltlsacl");
+ qemu_acl_reset(acl);
+ wildcards = data->wildcards;
+ while (wildcards && *wildcards) {
+ qemu_acl_append(acl, 0, *wildcards);
+ wildcards++;
+ }
+
+ clientChanSock = qio_channel_socket_new_fd(
+ channel[0], &err);
+ g_assert(clientChanSock != NULL);
+ serverChanSock = qio_channel_socket_new_fd(
+ channel[1], &err);
+ g_assert(serverChanSock != NULL);
+
+ /*
+ * We have an evil loop to do the handshake in a single
+ * thread, so we need these non-blocking to avoid deadlock
+ * of ourselves
+ */
+ qio_channel_set_blocking(QIO_CHANNEL(clientChanSock), false, NULL);
+ qio_channel_set_blocking(QIO_CHANNEL(serverChanSock), false, NULL);
+
+ /* Now the real part of the test, setup the sessions */
+ clientChanTLS = qio_channel_tls_new_client(
+ QIO_CHANNEL(clientChanSock), clientCreds,
+ data->hostname, &err);
+ g_assert(clientChanTLS != NULL);
+
+ serverChanTLS = qio_channel_tls_new_server(
+ QIO_CHANNEL(serverChanSock), serverCreds,
+ "channeltlsacl", &err);
+ g_assert(serverChanTLS != NULL);
+
+ qio_channel_tls_handshake(clientChanTLS,
+ test_tls_handshake_done,
+ &clientHandshake,
+ NULL);
+ qio_channel_tls_handshake(serverChanTLS,
+ test_tls_handshake_done,
+ &serverHandshake,
+ NULL);
+
+ /*
+ * Finally we loop around & around doing handshake on each
+ * session until we get an error, or the handshake completes.
+ * This relies on the socketpair being nonblocking to avoid
+ * deadlocking ourselves upon handshake
+ */
+ mainloop = g_main_context_default();
+ do {
+ g_main_context_iteration(mainloop, TRUE);
+ } while (!clientHandshake.finished &&
+ !serverHandshake.finished);
+
+ g_assert(clientHandshake.failed == data->expectClientFail);
+ g_assert(serverHandshake.failed == data->expectServerFail);
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_threads(test, false,
+ QIO_CHANNEL(clientChanTLS),
+ QIO_CHANNEL(serverChanTLS));
+ qio_channel_test_validate(test);
+
+ test = qio_channel_test_new();
+ qio_channel_test_run_threads(test, true,
+ QIO_CHANNEL(clientChanTLS),
+ QIO_CHANNEL(serverChanTLS));
+ qio_channel_test_validate(test);
+
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT);
+ unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY);
+
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
+ unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
+
+ rmdir(CLIENT_CERT_DIR);
+ rmdir(SERVER_CERT_DIR);
+
+ object_unparent(OBJECT(serverCreds));
+ object_unparent(OBJECT(clientCreds));
+
+ object_unref(OBJECT(serverChanTLS));
+ object_unref(OBJECT(clientChanTLS));
+
+ object_unref(OBJECT(serverChanSock));
+ object_unref(OBJECT(clientChanSock));
+
+ close(channel[0]);
+ close(channel[1]);
+}
+
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ module_call_init(MODULE_INIT_QOM);
+ g_test_init(&argc, &argv, NULL);
+ setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1);
+
+ mkdir(WORKDIR, 0700);
+
+ test_tls_init(KEYFILE);
+
+# define TEST_CHANNEL(name, caCrt, \
+ serverCrt, clientCrt, \
+ expectServerFail, expectClientFail, \
+ hostname, wildcards) \
+ struct QIOChannelTLSTestData name = { \
+ caCrt, caCrt, serverCrt, clientCrt, \
+ expectServerFail, expectClientFail, \
+ hostname, wildcards \
+ }; \
+ g_test_add_data_func("/qio/channel/tls/" # name, \
+ &name, test_io_channel_tls);
+
+ /* A perfect CA, perfect client & perfect server */
+
+ /* Basic:CA:critical */
+ TLS_ROOT_REQ(cacertreq,
+ "UK", "qemu CA", NULL, NULL, NULL, NULL,
+ true, true, true,
+ true, true, GNUTLS_KEY_KEY_CERT_SIGN,
+ false, false, NULL, NULL,
+ 0, 0);
+ TLS_CERT_REQ(servercertreq, cacertreq,
+ "UK", "qemu.org", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
+ 0, 0);
+ TLS_CERT_REQ(clientcertreq, cacertreq,
+ "UK", "qemu", NULL, NULL, NULL, NULL,
+ true, true, false,
+ true, true,
+ GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
+ true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
+ 0, 0);
+
+ const char *const wildcards[] = {
+ "C=UK,CN=qemu*",
+ NULL,
+ };
+ TEST_CHANNEL(basic, cacertreq.filename, servercertreq.filename,
+ clientcertreq.filename, false, false,
+ "qemu.org", wildcards);
+
+ ret = g_test_run();
+
+ test_tls_discard_cert(&clientcertreq);
+ test_tls_discard_cert(&servercertreq);
+ test_tls_discard_cert(&cacertreq);
+
+ test_tls_cleanup(KEYFILE);
+ rmdir(WORKDIR);
+
+ return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+#else /* ! QCRYPTO_HAVE_TLS_TEST_SUPPORT */
+
+int
+main(void)
+{
+ return EXIT_SUCCESS;
+}
+
+#endif /* ! QCRYPTO_HAVE_TLS_TEST_SUPPORT */
diff --git a/qemu/tests/test-io-task.c b/qemu/tests/test-io-task.c
new file mode 100644
index 000000000..5a9775086
--- /dev/null
+++ b/qemu/tests/test-io-task.c
@@ -0,0 +1,270 @@
+/*
+ * QEMU I/O task tests
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+
+#include "io/task.h"
+#include "qapi/error.h"
+
+#define TYPE_DUMMY "qemu:dummy"
+
+typedef struct DummyObject DummyObject;
+typedef struct DummyObjectClass DummyObjectClass;
+
+struct DummyObject {
+ Object parent;
+};
+
+struct DummyObjectClass {
+ ObjectClass parent;
+};
+
+static const TypeInfo dummy_info = {
+ .parent = TYPE_OBJECT,
+ .name = TYPE_DUMMY,
+ .instance_size = sizeof(DummyObject),
+ .class_size = sizeof(DummyObjectClass),
+};
+
+struct TestTaskData {
+ Object *source;
+ Error *err;
+ bool freed;
+};
+
+
+static void task_callback(Object *source,
+ Error *err,
+ gpointer opaque)
+{
+ struct TestTaskData *data = opaque;
+
+ data->source = source;
+ data->err = err;
+}
+
+
+static void test_task_complete(void)
+{
+ QIOTask *task;
+ Object *obj = object_new(TYPE_DUMMY);
+ Object *src;
+ struct TestTaskData data = { NULL, NULL, false };
+
+ task = qio_task_new(obj, task_callback, &data, NULL);
+ src = qio_task_get_source(task);
+
+ qio_task_complete(task);
+
+ g_assert(obj == src);
+
+ object_unref(obj);
+ object_unref(src);
+
+ g_assert(data.source == obj);
+ g_assert(data.err == NULL);
+ g_assert(data.freed == false);
+}
+
+
+static void task_data_free(gpointer opaque)
+{
+ struct TestTaskData *data = opaque;
+
+ data->freed = true;
+}
+
+
+static void test_task_data_free(void)
+{
+ QIOTask *task;
+ Object *obj = object_new(TYPE_DUMMY);
+ struct TestTaskData data = { NULL, NULL, false };
+
+ task = qio_task_new(obj, task_callback, &data, task_data_free);
+
+ qio_task_complete(task);
+
+ object_unref(obj);
+
+ g_assert(data.source == obj);
+ g_assert(data.err == NULL);
+ g_assert(data.freed == true);
+}
+
+
+static void test_task_error(void)
+{
+ QIOTask *task;
+ Object *obj = object_new(TYPE_DUMMY);
+ struct TestTaskData data = { NULL, NULL, false };
+ Error *err = NULL;
+
+ task = qio_task_new(obj, task_callback, &data, NULL);
+
+ error_setg(&err, "Some error");
+
+ qio_task_abort(task, err);
+
+ error_free(err);
+ object_unref(obj);
+
+ g_assert(data.source == obj);
+ g_assert(data.err == err);
+ g_assert(data.freed == false);
+
+}
+
+
+struct TestThreadWorkerData {
+ Object *source;
+ Error *err;
+ bool fail;
+ GThread *worker;
+ GThread *complete;
+ GMainLoop *loop;
+};
+
+static int test_task_thread_worker(QIOTask *task,
+ Error **errp,
+ gpointer opaque)
+{
+ struct TestThreadWorkerData *data = opaque;
+
+ data->worker = g_thread_self();
+
+ if (data->fail) {
+ error_setg(errp, "Testing fail");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void test_task_thread_callback(Object *source,
+ Error *err,
+ gpointer opaque)
+{
+ struct TestThreadWorkerData *data = opaque;
+
+ data->source = source;
+ data->err = err;
+
+ data->complete = g_thread_self();
+
+ g_main_loop_quit(data->loop);
+}
+
+
+static void test_task_thread_complete(void)
+{
+ QIOTask *task;
+ Object *obj = object_new(TYPE_DUMMY);
+ struct TestThreadWorkerData data = { 0 };
+ GThread *self;
+
+ data.loop = g_main_loop_new(g_main_context_default(),
+ TRUE);
+
+ task = qio_task_new(obj,
+ test_task_thread_callback,
+ &data,
+ NULL);
+
+ qio_task_run_in_thread(task,
+ test_task_thread_worker,
+ &data,
+ NULL);
+
+ g_main_loop_run(data.loop);
+
+ g_main_loop_unref(data.loop);
+ object_unref(obj);
+
+ g_assert(data.source == obj);
+ g_assert(data.err == NULL);
+
+ self = g_thread_self();
+
+ /* Make sure the test_task_thread_worker actually got
+ * run in a different thread */
+ g_assert(data.worker != self);
+
+ /* And that the test_task_thread_callback got rnu in
+ * the main loop thread (ie this one) */
+ g_assert(data.complete == self);
+}
+
+
+static void test_task_thread_error(void)
+{
+ QIOTask *task;
+ Object *obj = object_new(TYPE_DUMMY);
+ struct TestThreadWorkerData data = { 0 };
+ GThread *self;
+
+ data.loop = g_main_loop_new(g_main_context_default(),
+ TRUE);
+ data.fail = true;
+
+ task = qio_task_new(obj,
+ test_task_thread_callback,
+ &data,
+ NULL);
+
+ qio_task_run_in_thread(task,
+ test_task_thread_worker,
+ &data,
+ NULL);
+
+ g_main_loop_run(data.loop);
+
+ g_main_loop_unref(data.loop);
+ object_unref(obj);
+
+ g_assert(data.source == obj);
+ g_assert(data.err != NULL);
+
+ self = g_thread_self();
+
+ /* Make sure the test_task_thread_worker actually got
+ * run in a different thread */
+ g_assert(data.worker != self);
+
+ /* And that the test_task_thread_callback got rnu in
+ * the main loop thread (ie this one) */
+ g_assert(data.complete == self);
+}
+
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ module_call_init(MODULE_INIT_QOM);
+ type_register_static(&dummy_info);
+ g_test_add_func("/crypto/task/complete", test_task_complete);
+ g_test_add_func("/crypto/task/datafree", test_task_data_free);
+ g_test_add_func("/crypto/task/error", test_task_error);
+ g_test_add_func("/crypto/task/thread_complete", test_task_thread_complete);
+ g_test_add_func("/crypto/task/thread_error", test_task_thread_error);
+ return g_test_run();
+}
diff --git a/qemu/tests/test-iov.c b/qemu/tests/test-iov.c
index 46e4dddc5..3f25268dd 100644
--- a/qemu/tests/test-iov.c
+++ b/qemu/tests/test-iov.c
@@ -1,3 +1,4 @@
+#include "qemu/osdep.h"
#include <glib.h>
#include "qemu-common.h"
#include "qemu/iov.h"
diff --git a/qemu/tests/test-logging.c b/qemu/tests/test-logging.c
new file mode 100644
index 000000000..ac8deedc9
--- /dev/null
+++ b/qemu/tests/test-logging.c
@@ -0,0 +1,141 @@
+/*
+ * logging unit-tests
+ *
+ * Copyright (C) 2016 Linaro Ltd.
+ *
+ * Author: Alex Bennée <alex.bennee@linaro.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+
+#include "qemu-common.h"
+#include "include/qemu/log.h"
+
+static void test_parse_range(void)
+{
+ qemu_set_dfilter_ranges("0x1000+0x100");
+
+ g_assert_false(qemu_log_in_addr_range(0xfff));
+ g_assert(qemu_log_in_addr_range(0x1000));
+ g_assert(qemu_log_in_addr_range(0x1001));
+ g_assert(qemu_log_in_addr_range(0x10ff));
+ g_assert_false(qemu_log_in_addr_range(0x1100));
+
+ qemu_set_dfilter_ranges("0x1000-0x100");
+
+ g_assert_false(qemu_log_in_addr_range(0x1001));
+ g_assert(qemu_log_in_addr_range(0x1000));
+ g_assert(qemu_log_in_addr_range(0x0f01));
+ g_assert_false(qemu_log_in_addr_range(0x0f00));
+
+ qemu_set_dfilter_ranges("0x1000..0x1100");
+
+ g_assert_false(qemu_log_in_addr_range(0xfff));
+ g_assert(qemu_log_in_addr_range(0x1000));
+ g_assert(qemu_log_in_addr_range(0x1100));
+ g_assert_false(qemu_log_in_addr_range(0x1101));
+
+ qemu_set_dfilter_ranges("0x1000..0x1000");
+
+ g_assert_false(qemu_log_in_addr_range(0xfff));
+ g_assert(qemu_log_in_addr_range(0x1000));
+ g_assert_false(qemu_log_in_addr_range(0x1001));
+
+ qemu_set_dfilter_ranges("0x1000+0x100,0x2100-0x100,0x3000..0x3100");
+ g_assert(qemu_log_in_addr_range(0x1050));
+ g_assert(qemu_log_in_addr_range(0x2050));
+ g_assert(qemu_log_in_addr_range(0x3050));
+}
+
+#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+static void test_parse_invalid_range_subprocess(void)
+{
+ qemu_set_dfilter_ranges("0x1000+onehundred");
+}
+static void test_parse_invalid_range(void)
+{
+ g_test_trap_subprocess("/logging/parse_invalid_range/subprocess", 0, 0);
+ g_test_trap_assert_failed();
+ g_test_trap_assert_stdout("");
+ g_test_trap_assert_stderr("*Failed to parse range in: 0x1000+onehundred\n");
+}
+static void test_parse_zero_range_subprocess(void)
+{
+ qemu_set_dfilter_ranges("0x1000+0");
+}
+static void test_parse_zero_range(void)
+{
+ g_test_trap_subprocess("/logging/parse_zero_range/subprocess", 0, 0);
+ g_test_trap_assert_failed();
+ g_test_trap_assert_stdout("");
+ g_test_trap_assert_stderr("*Failed to parse range in: 0x1000+0\n");
+}
+
+/* As the only real failure from a bad log filename path spec is
+ * reporting to the user we have to use the g_test_trap_subprocess
+ * mechanism and check no errors reported on stderr.
+ */
+static void test_parse_path_subprocess(void)
+{
+ /* All these should work without issue */
+ qemu_set_log_filename("/tmp/qemu.log");
+ qemu_set_log_filename("/tmp/qemu-%d.log");
+ qemu_set_log_filename("/tmp/qemu.log.%d");
+}
+static void test_parse_path(void)
+{
+ g_test_trap_subprocess ("/logging/parse_path/subprocess", 0, 0);
+ g_test_trap_assert_passed();
+ g_test_trap_assert_stdout("");
+ g_test_trap_assert_stderr("");
+}
+static void test_parse_invalid_path_subprocess(void)
+{
+ qemu_set_log_filename("/tmp/qemu-%d%d.log");
+}
+static void test_parse_invalid_path(void)
+{
+ g_test_trap_subprocess ("/logging/parse_invalid_path/subprocess", 0, 0);
+ g_test_trap_assert_passed();
+ g_test_trap_assert_stdout("");
+ g_test_trap_assert_stderr("Bad logfile format: /tmp/qemu-%d%d.log\n");
+}
+#endif /* CONFIG_HAS_GLIB_SUBPROCESS_TESTS */
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/logging/parse_range", test_parse_range);
+#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
+ g_test_add_func("/logging/parse_invalid_range/subprocess", test_parse_invalid_range_subprocess);
+ g_test_add_func("/logging/parse_invalid_range", test_parse_invalid_range);
+ g_test_add_func("/logging/parse_zero_range/subprocess", test_parse_zero_range_subprocess);
+ g_test_add_func("/logging/parse_zero_range", test_parse_zero_range);
+ g_test_add_func("/logging/parse_path", test_parse_path);
+ g_test_add_func("/logging/parse_path/subprocess", test_parse_path_subprocess);
+ g_test_add_func("/logging/parse_invalid_path", test_parse_invalid_path);
+ g_test_add_func("/logging/parse_invalid_path/subprocess", test_parse_invalid_path_subprocess);
+#endif
+
+ return g_test_run();
+}
diff --git a/qemu/tests/test-mul64.c b/qemu/tests/test-mul64.c
index a0a17f777..1282ec5a2 100644
--- a/qemu/tests/test-mul64.c
+++ b/qemu/tests/test-mul64.c
@@ -6,10 +6,9 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdint.h>
#include "qemu/host-utils.h"
-#include "qemu/osdep.h"
typedef struct {
diff --git a/qemu/tests/test-netfilter.c b/qemu/tests/test-netfilter.c
new file mode 100644
index 000000000..7d105c323
--- /dev/null
+++ b/qemu/tests/test-netfilter.c
@@ -0,0 +1,201 @@
+/*
+ * QTest testcase for netfilter
+ *
+ * Copyright (c) 2015 FUJITSU LIMITED
+ * Author: Yang Hongyang <yanghy@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+#include "libqtest.h"
+
+/* add a netfilter to a netdev and then remove it */
+static void add_one_netfilter(void)
+{
+ QDict *response;
+
+ response = qmp("{'execute': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f0',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'queue': 'rx',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-del',"
+ " 'arguments': {"
+ " 'id': 'qtest-f0'"
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+}
+
+/* add a netfilter to a netdev and then remove the netdev */
+static void remove_netdev_with_one_netfilter(void)
+{
+ QDict *response;
+
+ response = qmp("{'execute': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f0',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'queue': 'rx',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'netdev_del',"
+ " 'arguments': {"
+ " 'id': 'qtest-bn0'"
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ /* add back the netdev */
+ response = qmp("{'execute': 'netdev_add',"
+ " 'arguments': {"
+ " 'type': 'user',"
+ " 'id': 'qtest-bn0'"
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+}
+
+/* add multi(2) netfilters to a netdev and then remove them */
+static void add_multi_netfilter(void)
+{
+ QDict *response;
+
+ response = qmp("{'execute': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f0',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'queue': 'rx',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f1',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'queue': 'rx',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-del',"
+ " 'arguments': {"
+ " 'id': 'qtest-f0'"
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-del',"
+ " 'arguments': {"
+ " 'id': 'qtest-f1'"
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+}
+
+/* add multi(2) netfilters to a netdev and then remove the netdev */
+static void remove_netdev_with_multi_netfilter(void)
+{
+ QDict *response;
+
+ response = qmp("{'execute': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f0',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'queue': 'rx',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f1',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'queue': 'rx',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'netdev_del',"
+ " 'arguments': {"
+ " 'id': 'qtest-bn0'"
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ /* add back the netdev */
+ response = qmp("{'execute': 'netdev_add',"
+ " 'arguments': {"
+ " 'type': 'user',"
+ " 'id': 'qtest-bn0'"
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/netfilter/addremove_one", add_one_netfilter);
+ qtest_add_func("/netfilter/remove_netdev_one",
+ remove_netdev_with_one_netfilter);
+ qtest_add_func("/netfilter/addremove_multi", add_multi_netfilter);
+ qtest_add_func("/netfilter/remove_netdev_multi",
+ remove_netdev_with_multi_netfilter);
+
+ qtest_start("-netdev user,id=qtest-bn0 -device e1000,netdev=qtest-bn0");
+ ret = g_test_run();
+
+ qtest_end();
+
+ return ret;
+}
diff --git a/qemu/tests/test-opts-visitor.c b/qemu/tests/test-opts-visitor.c
index 1c753d982..008e67738 100644
--- a/qemu/tests/test-opts-visitor.c
+++ b/qemu/tests/test-opts-visitor.c
@@ -10,13 +10,14 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qemu/config-file.h" /* qemu_add_opts() */
#include "qemu/option.h" /* qemu_opts_parse() */
+#include "qapi/error.h"
#include "qapi/opts-visitor.h" /* opts_visitor_new() */
#include "test-qapi-visit.h" /* visit_type_UserDefOptions() */
-#include "qapi/dealloc-visitor.h" /* qapi_dealloc_visitor_new() */
static QemuOptsList userdef_opts = {
.name = "userdef",
@@ -44,7 +45,7 @@ setup_fixture(OptsVisitorFixture *f, gconstpointer test_data)
g_assert(opts != NULL);
ov = opts_visitor_new(opts);
- visit_type_UserDefOptions(opts_get_visitor(ov), &f->userdef, NULL,
+ visit_type_UserDefOptions(opts_get_visitor(ov), NULL, &f->userdef,
&f->err);
opts_visitor_cleanup(ov);
qemu_opts_del(opts);
@@ -54,14 +55,7 @@ setup_fixture(OptsVisitorFixture *f, gconstpointer test_data)
static void
teardown_fixture(OptsVisitorFixture *f, gconstpointer test_data)
{
- if (f->userdef != NULL) {
- QapiDeallocVisitor *dv;
-
- dv = qapi_dealloc_visitor_new();
- visit_type_UserDefOptions(qapi_dealloc_get_visitor(dv), &f->userdef,
- NULL, NULL);
- qapi_dealloc_visitor_cleanup(dv);
- }
+ qapi_free_UserDefOptions(f->userdef);
error_free(f->err);
}
diff --git a/qemu/tests/test-qdev-global-props.c b/qemu/tests/test-qdev-global-props.c
index 0be98355c..f0cc31e11 100644
--- a/qemu/tests/test-qdev-global-props.c
+++ b/qemu/tests/test-qdev-global-props.c
@@ -22,8 +22,8 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdint.h>
#include "hw/qdev.h"
#include "qom/object.h"
@@ -116,26 +116,20 @@ static void test_static_globalprop(void)
#define TYPE_UNUSED_HOTPLUG "hotplug-type"
#define TYPE_UNUSED_NOHOTPLUG "nohotplug-type"
-static void prop1_accessor(Object *obj,
- Visitor *v,
- void *opaque,
- const char *name,
- Error **errp)
+static void prop1_accessor(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
MyType *mt = DYNAMIC_TYPE(obj);
- visit_type_uint32(v, &mt->prop1, name, errp);
+ visit_type_uint32(v, name, &mt->prop1, errp);
}
-static void prop2_accessor(Object *obj,
- Visitor *v,
- void *opaque,
- const char *name,
- Error **errp)
+static void prop2_accessor(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
{
MyType *mt = DYNAMIC_TYPE(obj);
- visit_type_uint32(v, &mt->prop2, name, errp);
+ visit_type_uint32(v, name, &mt->prop2, errp);
}
static void dynamic_instance_init(Object *obj)
diff --git a/qemu/tests/test-qemu-opts.c b/qemu/tests/test-qemu-opts.c
index 0c1136d1b..32abed5ea 100644
--- a/qemu/tests/test-qemu-opts.c
+++ b/qemu/tests/test-qemu-opts.c
@@ -7,12 +7,12 @@
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qapi/qmp/qstring.h"
#include "qemu/config-file.h"
#include <glib.h>
-#include <string.h>
static QemuOptsList opts_list_01 = {
.name = "opts_list_01",
diff --git a/qemu/tests/test-qga.c b/qemu/tests/test-qga.c
new file mode 100644
index 000000000..72a89dec2
--- /dev/null
+++ b/qemu/tests/test-qga.c
@@ -0,0 +1,869 @@
+#include "qemu/osdep.h"
+#include <locale.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "libqtest.h"
+
+typedef struct {
+ char *test_dir;
+ GMainLoop *loop;
+ int fd;
+ GPid pid;
+} TestFixture;
+
+static int connect_qga(char *path)
+{
+ int s, ret, len, i = 0;
+ struct sockaddr_un remote;
+
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ g_assert(s != -1);
+
+ remote.sun_family = AF_UNIX;
+ do {
+ strcpy(remote.sun_path, path);
+ len = strlen(remote.sun_path) + sizeof(remote.sun_family);
+ ret = connect(s, (struct sockaddr *)&remote, len);
+ if (ret == -1) {
+ g_usleep(G_USEC_PER_SEC);
+ }
+ if (i++ == 10) {
+ return -1;
+ }
+ } while (ret == -1);
+
+ return s;
+}
+
+static void qga_watch(GPid pid, gint status, gpointer user_data)
+{
+ TestFixture *fixture = user_data;
+
+ g_assert_cmpint(status, ==, 0);
+ g_main_loop_quit(fixture->loop);
+}
+
+static void
+fixture_setup(TestFixture *fixture, gconstpointer data)
+{
+ const gchar *extra_arg = data;
+ GError *error = NULL;
+ gchar *cwd, *path, *cmd, **argv = NULL;
+
+ fixture->loop = g_main_loop_new(NULL, FALSE);
+
+ fixture->test_dir = g_strdup("/tmp/qgatest.XXXXXX");
+ g_assert_nonnull(mkdtemp(fixture->test_dir));
+
+ path = g_build_filename(fixture->test_dir, "sock", NULL);
+ cwd = g_get_current_dir();
+ cmd = g_strdup_printf("%s%cqemu-ga -m unix-listen -t %s -p %s %s %s",
+ cwd, G_DIR_SEPARATOR,
+ fixture->test_dir, path,
+ getenv("QTEST_LOG") ? "-v" : "",
+ extra_arg ?: "");
+ g_shell_parse_argv(cmd, NULL, &argv, &error);
+ g_assert_no_error(error);
+
+ g_spawn_async(fixture->test_dir, argv, NULL,
+ G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, &fixture->pid, &error);
+ g_assert_no_error(error);
+
+ g_child_watch_add(fixture->pid, qga_watch, fixture);
+
+ fixture->fd = connect_qga(path);
+ g_assert_cmpint(fixture->fd, !=, -1);
+
+ g_strfreev(argv);
+ g_free(cmd);
+ g_free(cwd);
+ g_free(path);
+}
+
+static void
+fixture_tear_down(TestFixture *fixture, gconstpointer data)
+{
+ gchar *tmp;
+
+ kill(fixture->pid, SIGTERM);
+
+ g_main_loop_run(fixture->loop);
+ g_main_loop_unref(fixture->loop);
+
+ g_spawn_close_pid(fixture->pid);
+
+ tmp = g_build_filename(fixture->test_dir, "foo", NULL);
+ g_unlink(tmp);
+ g_free(tmp);
+
+ tmp = g_build_filename(fixture->test_dir, "qga.state", NULL);
+ g_unlink(tmp);
+ g_free(tmp);
+
+ tmp = g_build_filename(fixture->test_dir, "sock", NULL);
+ g_unlink(tmp);
+ g_free(tmp);
+
+ g_rmdir(fixture->test_dir);
+ g_free(fixture->test_dir);
+}
+
+static void qmp_assertion_message_error(const char *domain,
+ const char *file,
+ int line,
+ const char *func,
+ const char *expr,
+ QDict *dict)
+{
+ const char *class, *desc;
+ char *s;
+ QDict *error;
+
+ error = qdict_get_qdict(dict, "error");
+ class = qdict_get_try_str(error, "class");
+ desc = qdict_get_try_str(error, "desc");
+
+ s = g_strdup_printf("assertion failed %s: %s %s", expr, class, desc);
+ g_assertion_message(domain, file, line, func, s);
+ g_free(s);
+}
+
+#define qmp_assert_no_error(err) do { \
+ if (qdict_haskey(err, "error")) { \
+ qmp_assertion_message_error(G_LOG_DOMAIN, __FILE__, __LINE__, \
+ G_STRFUNC, #err, err); \
+ } \
+} while (0)
+
+static void test_qga_sync_delimited(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ guint32 v, r = g_random_int();
+ unsigned char c;
+ QDict *ret;
+ gchar *cmd;
+
+ cmd = g_strdup_printf("%c{'execute': 'guest-sync-delimited',"
+ " 'arguments': {'id': %u } }", 0xff, r);
+ qmp_fd_send(fixture->fd, cmd);
+ g_free(cmd);
+
+ v = read(fixture->fd, &c, 1);
+ g_assert_cmpint(v, ==, 1);
+ g_assert_cmpint(c, ==, 0xff);
+
+ ret = qmp_fd_receive(fixture->fd);
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ v = qdict_get_int(ret, "return");
+ g_assert_cmpint(r, ==, v);
+
+ QDECREF(ret);
+}
+
+static void test_qga_sync(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ guint32 v, r = g_random_int();
+ QDict *ret;
+ gchar *cmd;
+
+ cmd = g_strdup_printf("%c{'execute': 'guest-sync',"
+ " 'arguments': {'id': %u } }", 0xff, r);
+ ret = qmp_fd(fixture->fd, cmd);
+ g_free(cmd);
+
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ v = qdict_get_int(ret, "return");
+ g_assert_cmpint(r, ==, v);
+
+ QDECREF(ret);
+}
+
+static void test_qga_ping(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ QDECREF(ret);
+}
+
+static void test_qga_invalid_cmd(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret, *error;
+ const gchar *class, *desc;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-invalid-cmd'}");
+ g_assert_nonnull(ret);
+
+ error = qdict_get_qdict(ret, "error");
+ class = qdict_get_try_str(error, "class");
+ desc = qdict_get_try_str(error, "desc");
+
+ g_assert_cmpstr(class, ==, "CommandNotFound");
+ g_assert_cmpint(strlen(desc), >, 0);
+
+ QDECREF(ret);
+}
+
+static void test_qga_info(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret, *val;
+ const gchar *version;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-info'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ val = qdict_get_qdict(ret, "return");
+ version = qdict_get_try_str(val, "version");
+ g_assert_cmpstr(version, ==, QEMU_VERSION);
+
+ QDECREF(ret);
+}
+
+static void test_qga_get_vcpus(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+ QList *list;
+ const QListEntry *entry;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-vcpus'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ /* check there is at least a cpu */
+ list = qdict_get_qlist(ret, "return");
+ entry = qlist_first(list);
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "logical-id"));
+
+ QDECREF(ret);
+}
+
+static void test_qga_get_fsinfo(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+ QList *list;
+ const QListEntry *entry;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-fsinfo'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ /* sanity-check the response if there are any filesystems */
+ list = qdict_get_qlist(ret, "return");
+ entry = qlist_first(list);
+ if (entry) {
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "mountpoint"));
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "type"));
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "disk"));
+ }
+
+ QDECREF(ret);
+}
+
+static void test_qga_get_memory_block_info(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret, *val;
+ int64_t size;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-block-info'}");
+ g_assert_nonnull(ret);
+
+ /* some systems might not expose memory block info in sysfs */
+ if (!qdict_haskey(ret, "error")) {
+ /* check there is at least some memory */
+ val = qdict_get_qdict(ret, "return");
+ size = qdict_get_int(val, "size");
+ g_assert_cmpint(size, >, 0);
+ }
+
+ QDECREF(ret);
+}
+
+static void test_qga_get_memory_blocks(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+ QList *list;
+ const QListEntry *entry;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-blocks'}");
+ g_assert_nonnull(ret);
+
+ /* some systems might not expose memory block info in sysfs */
+ if (!qdict_haskey(ret, "error")) {
+ list = qdict_get_qlist(ret, "return");
+ entry = qlist_first(list);
+ /* newer versions of qga may return empty list without error */
+ if (entry) {
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "phys-index"));
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
+ }
+ }
+
+ QDECREF(ret);
+}
+
+static void test_qga_network_get_interfaces(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+ QList *list;
+ const QListEntry *entry;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-network-get-interfaces'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ /* check there is at least an interface */
+ list = qdict_get_qlist(ret, "return");
+ entry = qlist_first(list);
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
+
+ QDECREF(ret);
+}
+
+static void test_qga_file_ops(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ const unsigned char helloworld[] = "Hello World!\n";
+ const char *b64;
+ gchar *cmd, *path, *enc;
+ unsigned char *dec;
+ QDict *ret, *val;
+ int64_t id, eof;
+ gsize count;
+ FILE *f;
+ char tmp[100];
+
+ /* open */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
+ " 'arguments': { 'path': 'foo', 'mode': 'w+' } }");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ id = qdict_get_int(ret, "return");
+ QDECREF(ret);
+
+ enc = g_base64_encode(helloworld, sizeof(helloworld));
+ /* write */
+ cmd = g_strdup_printf("{'execute': 'guest-file-write',"
+ " 'arguments': { 'handle': %" PRId64 ","
+ " 'buf-b64': '%s' } }", id, enc);
+ ret = qmp_fd(fixture->fd, cmd);
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ g_assert_cmpint(count, ==, sizeof(helloworld));
+ g_assert_cmpint(eof, ==, 0);
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* flush */
+ cmd = g_strdup_printf("{'execute': 'guest-file-flush',"
+ " 'arguments': {'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* close */
+ cmd = g_strdup_printf("{'execute': 'guest-file-close',"
+ " 'arguments': {'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* check content */
+ path = g_build_filename(fixture->test_dir, "foo", NULL);
+ f = fopen(path, "r");
+ g_assert_nonnull(f);
+ count = fread(tmp, 1, sizeof(tmp), f);
+ g_assert_cmpint(count, ==, sizeof(helloworld));
+ tmp[count] = 0;
+ g_assert_cmpstr(tmp, ==, (char *)helloworld);
+ fclose(f);
+
+ /* open */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
+ " 'arguments': { 'path': 'foo', 'mode': 'r' } }");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ id = qdict_get_int(ret, "return");
+ QDECREF(ret);
+
+ /* read */
+ cmd = g_strdup_printf("{'execute': 'guest-file-read',"
+ " 'arguments': { 'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ b64 = qdict_get_str(val, "buf-b64");
+ g_assert_cmpint(count, ==, sizeof(helloworld));
+ g_assert(eof);
+ g_assert_cmpstr(b64, ==, enc);
+
+ QDECREF(ret);
+ g_free(cmd);
+ g_free(enc);
+
+ /* read eof */
+ cmd = g_strdup_printf("{'execute': 'guest-file-read',"
+ " 'arguments': { 'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ b64 = qdict_get_str(val, "buf-b64");
+ g_assert_cmpint(count, ==, 0);
+ g_assert(eof);
+ g_assert_cmpstr(b64, ==, "");
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* seek */
+ cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
+ " 'arguments': { 'handle': %" PRId64 ", "
+ " 'offset': %d, 'whence': '%s' } }",
+ id, 6, "set");
+ ret = qmp_fd(fixture->fd, cmd);
+ qmp_assert_no_error(ret);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "position");
+ eof = qdict_get_bool(val, "eof");
+ g_assert_cmpint(count, ==, 6);
+ g_assert(!eof);
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* partial read */
+ cmd = g_strdup_printf("{'execute': 'guest-file-read',"
+ " 'arguments': { 'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ b64 = qdict_get_str(val, "buf-b64");
+ g_assert_cmpint(count, ==, sizeof(helloworld) - 6);
+ g_assert(eof);
+ dec = g_base64_decode(b64, &count);
+ g_assert_cmpint(count, ==, sizeof(helloworld) - 6);
+ g_assert_cmpmem(dec, count, helloworld + 6, sizeof(helloworld) - 6);
+ g_free(dec);
+
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* close */
+ cmd = g_strdup_printf("{'execute': 'guest-file-close',"
+ " 'arguments': {'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ QDECREF(ret);
+ g_free(cmd);
+}
+
+static void test_qga_file_write_read(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ const unsigned char helloworld[] = "Hello World!\n";
+ const char *b64;
+ gchar *cmd, *enc;
+ QDict *ret, *val;
+ int64_t id, eof;
+ gsize count;
+
+ /* open */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
+ " 'arguments': { 'path': 'foo', 'mode': 'w+' } }");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ id = qdict_get_int(ret, "return");
+ QDECREF(ret);
+
+ enc = g_base64_encode(helloworld, sizeof(helloworld));
+ /* write */
+ cmd = g_strdup_printf("{'execute': 'guest-file-write',"
+ " 'arguments': { 'handle': %" PRId64 ","
+ " 'buf-b64': '%s' } }", id, enc);
+ ret = qmp_fd(fixture->fd, cmd);
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ g_assert_cmpint(count, ==, sizeof(helloworld));
+ g_assert_cmpint(eof, ==, 0);
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* read (check implicit flush) */
+ cmd = g_strdup_printf("{'execute': 'guest-file-read',"
+ " 'arguments': { 'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ b64 = qdict_get_str(val, "buf-b64");
+ g_assert_cmpint(count, ==, 0);
+ g_assert(eof);
+ g_assert_cmpstr(b64, ==, "");
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* seek to 0 */
+ cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
+ " 'arguments': { 'handle': %" PRId64 ", "
+ " 'offset': %d, 'whence': '%s' } }",
+ id, 0, "set");
+ ret = qmp_fd(fixture->fd, cmd);
+ qmp_assert_no_error(ret);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "position");
+ eof = qdict_get_bool(val, "eof");
+ g_assert_cmpint(count, ==, 0);
+ g_assert(!eof);
+ QDECREF(ret);
+ g_free(cmd);
+
+ /* read */
+ cmd = g_strdup_printf("{'execute': 'guest-file-read',"
+ " 'arguments': { 'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ val = qdict_get_qdict(ret, "return");
+ count = qdict_get_int(val, "count");
+ eof = qdict_get_bool(val, "eof");
+ b64 = qdict_get_str(val, "buf-b64");
+ g_assert_cmpint(count, ==, sizeof(helloworld));
+ g_assert(eof);
+ g_assert_cmpstr(b64, ==, enc);
+ QDECREF(ret);
+ g_free(cmd);
+ g_free(enc);
+
+ /* close */
+ cmd = g_strdup_printf("{'execute': 'guest-file-close',"
+ " 'arguments': {'handle': %" PRId64 "} }",
+ id);
+ ret = qmp_fd(fixture->fd, cmd);
+ QDECREF(ret);
+ g_free(cmd);
+}
+
+static void test_qga_get_time(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+ int64_t time;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ time = qdict_get_int(ret, "return");
+ g_assert_cmpint(time, >, 0);
+
+ QDECREF(ret);
+}
+
+static void test_qga_set_time(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+ int64_t current, time;
+ gchar *cmd;
+
+ /* get current time */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ current = qdict_get_int(ret, "return");
+ g_assert_cmpint(current, >, 0);
+ QDECREF(ret);
+
+ /* set some old time */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-set-time',"
+ " 'arguments': { 'time': 1000 } }");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ QDECREF(ret);
+
+ /* check old time */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ time = qdict_get_int(ret, "return");
+ g_assert_cmpint(time / 1000, <, G_USEC_PER_SEC * 10);
+ QDECREF(ret);
+
+ /* set back current time */
+ cmd = g_strdup_printf("{'execute': 'guest-set-time',"
+ " 'arguments': { 'time': %" PRId64 " } }",
+ current + time * 1000);
+ ret = qmp_fd(fixture->fd, cmd);
+ g_free(cmd);
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ QDECREF(ret);
+}
+
+static void test_qga_fstrim(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+ QList *list;
+ const QListEntry *entry;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-fstrim',"
+ " arguments: { minimum: 4194304 } }");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ list = qdict_get_qlist(ret, "return");
+ entry = qlist_first(list);
+ g_assert(qdict_haskey(qobject_to_qdict(entry->value), "paths"));
+
+ QDECREF(ret);
+}
+
+static void test_qga_blacklist(gconstpointer data)
+{
+ TestFixture fix;
+ QDict *ret, *error;
+ const gchar *class, *desc;
+
+ fixture_setup(&fix, "-b guest-ping,guest-get-time");
+
+ /* check blacklist */
+ ret = qmp_fd(fix.fd, "{'execute': 'guest-ping'}");
+ g_assert_nonnull(ret);
+ error = qdict_get_qdict(ret, "error");
+ class = qdict_get_try_str(error, "class");
+ desc = qdict_get_try_str(error, "desc");
+ g_assert_cmpstr(class, ==, "GenericError");
+ g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
+ QDECREF(ret);
+
+ ret = qmp_fd(fix.fd, "{'execute': 'guest-get-time'}");
+ g_assert_nonnull(ret);
+ error = qdict_get_qdict(ret, "error");
+ class = qdict_get_try_str(error, "class");
+ desc = qdict_get_try_str(error, "desc");
+ g_assert_cmpstr(class, ==, "GenericError");
+ g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
+ QDECREF(ret);
+
+ /* check something work */
+ ret = qmp_fd(fix.fd, "{'execute': 'guest-get-fsinfo'}");
+ qmp_assert_no_error(ret);
+ QDECREF(ret);
+
+ fixture_tear_down(&fix, NULL);
+}
+
+static void test_qga_config(gconstpointer data)
+{
+ GError *error = NULL;
+ char *cwd, *cmd, *out, *err, *str, **strv, *conf, **argv = NULL;
+ char *env[2];
+ int status, tmp;
+ gsize n;
+ GKeyFile *kf;
+ const char *qga_config =
+ "[general]\n"
+ "daemon=false\n"
+ "method=virtio-serial\n"
+ "path=/path/to/org.qemu.guest_agent.0\n"
+ "pidfile=/var/foo/qemu-ga.pid\n"
+ "statedir=/var/state\n"
+ "verbose=true\n"
+ "blacklist=guest-ping;guest-get-time\n";
+
+ tmp = g_file_open_tmp(NULL, &conf, &error);
+ g_assert_no_error(error);
+ g_assert_cmpint(tmp, >=, 0);
+ g_assert_cmpstr(conf, !=, "");
+
+ g_file_set_contents(conf, qga_config, -1, &error);
+ g_assert_no_error(error);
+
+ cwd = g_get_current_dir();
+ cmd = g_strdup_printf("%s%cqemu-ga -D",
+ cwd, G_DIR_SEPARATOR);
+ g_shell_parse_argv(cmd, NULL, &argv, &error);
+ g_assert_no_error(error);
+
+ env[0] = g_strdup_printf("QGA_CONF=%s", conf);
+ env[1] = NULL;
+ g_spawn_sync(NULL, argv, env, 0,
+ NULL, NULL, &out, &err, &status, &error);
+ g_assert_no_error(error);
+ g_assert_cmpstr(err, ==, "");
+ g_assert_cmpint(status, ==, 0);
+
+ kf = g_key_file_new();
+ g_key_file_load_from_data(kf, out, -1, G_KEY_FILE_NONE, &error);
+ g_assert_no_error(error);
+
+ str = g_key_file_get_start_group(kf);
+ g_assert_cmpstr(str, ==, "general");
+ g_free(str);
+
+ g_assert_false(g_key_file_get_boolean(kf, "general", "daemon", &error));
+ g_assert_no_error(error);
+
+ str = g_key_file_get_string(kf, "general", "method", &error);
+ g_assert_no_error(error);
+ g_assert_cmpstr(str, ==, "virtio-serial");
+ g_free(str);
+
+ str = g_key_file_get_string(kf, "general", "path", &error);
+ g_assert_no_error(error);
+ g_assert_cmpstr(str, ==, "/path/to/org.qemu.guest_agent.0");
+ g_free(str);
+
+ str = g_key_file_get_string(kf, "general", "pidfile", &error);
+ g_assert_no_error(error);
+ g_assert_cmpstr(str, ==, "/var/foo/qemu-ga.pid");
+ g_free(str);
+
+ str = g_key_file_get_string(kf, "general", "statedir", &error);
+ g_assert_no_error(error);
+ g_assert_cmpstr(str, ==, "/var/state");
+ g_free(str);
+
+ g_assert_true(g_key_file_get_boolean(kf, "general", "verbose", &error));
+ g_assert_no_error(error);
+
+ strv = g_key_file_get_string_list(kf, "general", "blacklist", &n, &error);
+ g_assert_cmpint(n, ==, 2);
+#if GLIB_CHECK_VERSION(2, 44, 0)
+ g_assert_true(g_strv_contains((const char * const *)strv,
+ "guest-ping"));
+ g_assert_true(g_strv_contains((const char * const *)strv,
+ "guest-get-time"));
+#endif
+ g_assert_no_error(error);
+ g_strfreev(strv);
+
+ g_free(out);
+ g_free(err);
+ g_free(conf);
+ g_free(env[0]);
+ g_key_file_free(kf);
+
+ close(tmp);
+}
+
+static void test_qga_fsfreeze_status(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+ const gchar *status;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+
+ status = qdict_get_try_str(ret, "return");
+ g_assert_cmpstr(status, ==, "thawed");
+
+ QDECREF(ret);
+}
+
+static void test_qga_fsfreeze_and_thaw(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ QDict *ret;
+ const gchar *status;
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-freeze'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ QDECREF(ret);
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ status = qdict_get_try_str(ret, "return");
+ g_assert_cmpstr(status, ==, "frozen");
+ QDECREF(ret);
+
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-thaw'}");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ QDECREF(ret);
+}
+
+int main(int argc, char **argv)
+{
+ TestFixture fix;
+ int ret;
+
+ setlocale (LC_ALL, "");
+ g_test_init(&argc, &argv, NULL);
+ fixture_setup(&fix, NULL);
+
+ g_test_add_data_func("/qga/sync-delimited", &fix, test_qga_sync_delimited);
+ g_test_add_data_func("/qga/sync", &fix, test_qga_sync);
+ g_test_add_data_func("/qga/ping", &fix, test_qga_ping);
+ g_test_add_data_func("/qga/info", &fix, test_qga_info);
+ g_test_add_data_func("/qga/network-get-interfaces", &fix,
+ test_qga_network_get_interfaces);
+ g_test_add_data_func("/qga/get-vcpus", &fix, test_qga_get_vcpus);
+ g_test_add_data_func("/qga/get-fsinfo", &fix, test_qga_get_fsinfo);
+ g_test_add_data_func("/qga/get-memory-block-info", &fix,
+ test_qga_get_memory_block_info);
+ g_test_add_data_func("/qga/get-memory-blocks", &fix,
+ test_qga_get_memory_blocks);
+ g_test_add_data_func("/qga/file-ops", &fix, test_qga_file_ops);
+ g_test_add_data_func("/qga/file-write-read", &fix, test_qga_file_write_read);
+ g_test_add_data_func("/qga/get-time", &fix, test_qga_get_time);
+ g_test_add_data_func("/qga/invalid-cmd", &fix, test_qga_invalid_cmd);
+ g_test_add_data_func("/qga/fsfreeze-status", &fix,
+ test_qga_fsfreeze_status);
+
+ g_test_add_data_func("/qga/blacklist", NULL, test_qga_blacklist);
+ g_test_add_data_func("/qga/config", NULL, test_qga_config);
+
+ if (g_getenv("QGA_TEST_SIDE_EFFECTING")) {
+ g_test_add_data_func("/qga/fsfreeze-and-thaw", &fix,
+ test_qga_fsfreeze_and_thaw);
+ g_test_add_data_func("/qga/set-time", &fix, test_qga_set_time);
+ g_test_add_data_func("/qga/fstrim", &fix, test_qga_fstrim);
+ }
+
+ ret = g_test_run();
+
+ fixture_tear_down(&fix, NULL);
+
+ return ret;
+}
diff --git a/qemu/tests/test-qmp-commands.c b/qemu/tests/test-qmp-commands.c
index 9918f2306..14a9ebbd5 100644
--- a/qemu/tests/test-qmp-commands.c
+++ b/qemu/tests/test-qmp-commands.c
@@ -1,3 +1,4 @@
+#include "qemu/osdep.h"
#include <glib.h>
#include "qemu-common.h"
#include "qapi/qmp/types.h"
@@ -12,6 +13,11 @@ void qmp_user_def_cmd(Error **errp)
{
}
+Empty2 *qmp_user_def_cmd0(Error **errp)
+{
+ return g_new0(Empty2, 1);
+}
+
void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
{
}
@@ -25,11 +31,9 @@ UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
UserDefOne *ud1d = g_malloc0(sizeof(UserDefOne));
ud1c->string = strdup(ud1a->string);
- ud1c->base = g_new0(UserDefZero, 1);
- ud1c->base->integer = ud1a->base->integer;
+ ud1c->integer = ud1a->integer;
ud1d->string = strdup(has_udb1 ? ud1b->string : "blah0");
- ud1d->base = g_new0(UserDefZero, 1);
- ud1d->base->integer = has_udb1 ? ud1b->base->integer : 0;
+ ud1d->integer = has_udb1 ? ud1b->integer : 0;
ret = g_new0(UserDefTwo, 1);
ret->string0 = strdup("blah1");
@@ -46,11 +50,16 @@ UserDefTwo *qmp_user_def_cmd2(UserDefOne *ud1a,
return ret;
}
-int64_t qmp_user_def_cmd3(int64_t a, bool has_b, int64_t b, Error **errp)
+int64_t qmp_guest_get_time(int64_t a, bool has_b, int64_t b, Error **errp)
{
return a + (has_b ? b : 0);
}
+QObject *qmp_guest_sync(QObject *arg, Error **errp)
+{
+ return arg;
+}
+
__org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
__org_qemu_x_StructList *b,
__org_qemu_x_Union2 *c,
@@ -59,9 +68,13 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
{
__org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
- ret->kind = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
- ret->__org_qemu_x_branch = strdup("blah1");
+ ret->type = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
+ ret->u.__org_qemu_x_branch.data = strdup("blah1");
+ /* Also test that 'wchar-t' was munged to 'q_wchar_t' */
+ if (b && b->value && !b->value->has_q_wchar_t) {
+ b->value->q_wchar_t = 1;
+ }
return ret;
}
@@ -155,7 +168,7 @@ static void test_dispatch_cmd_io(void)
qdict_put(args3, "a", qint_from_int(66));
qdict_put(req, "arguments", args3);
- qdict_put(req, "execute", qstring_from_str("user_def_cmd3"));
+ qdict_put(req, "execute", qstring_from_str("guest-get-time"));
ret3 = qobject_to_qint(test_qmp_dispatch(req));
assert(qint_get_int(ret3) == 66);
@@ -171,20 +184,17 @@ static void test_dealloc_types(void)
UserDefOneList *ud1list;
ud1test = g_malloc0(sizeof(UserDefOne));
- ud1test->base = g_new0(UserDefZero, 1);
- ud1test->base->integer = 42;
+ ud1test->integer = 42;
ud1test->string = g_strdup("hi there 42");
qapi_free_UserDefOne(ud1test);
ud1a = g_malloc0(sizeof(UserDefOne));
- ud1a->base = g_new0(UserDefZero, 1);
- ud1a->base->integer = 43;
+ ud1a->integer = 43;
ud1a->string = g_strdup("hi there 43");
ud1b = g_malloc0(sizeof(UserDefOne));
- ud1b->base = g_new0(UserDefZero, 1);
- ud1b->base->integer = 44;
+ ud1b->integer = 44;
ud1b->string = g_strdup("hi there 44");
ud1list = g_malloc0(sizeof(UserDefOneList));
@@ -213,7 +223,7 @@ static void test_dealloc_partial(void)
qdict_put_obj(ud2_dict, "string0", QOBJECT(qstring_from_str(text)));
qiv = qmp_input_visitor_new(QOBJECT(ud2_dict));
- visit_type_UserDefTwo(qmp_input_get_visitor(qiv), &ud2, NULL, &err);
+ visit_type_UserDefTwo(qmp_input_get_visitor(qiv), NULL, &ud2, &err);
qmp_input_visitor_cleanup(qiv);
QDECREF(ud2_dict);
}
@@ -225,8 +235,7 @@ static void test_dealloc_partial(void)
assert(ud2->dict1 == NULL);
/* confirm & release construction error */
- assert(err != NULL);
- error_free(err);
+ error_free_or_abort(&err);
/* tear down partial object */
qapi_free_UserDefTwo(ud2);
diff --git a/qemu/tests/test-qmp-event.c b/qemu/tests/test-qmp-event.c
index 1ee40e148..a296fdbac 100644
--- a/qemu/tests/test-qmp-event.c
+++ b/qemu/tests/test-qmp-event.c
@@ -11,8 +11,8 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdarg.h>
#include "qemu-common.h"
#include "test-qapi-types.h"
@@ -94,7 +94,7 @@ static bool qdict_cmp_simple(QDict *a, QDict *b)
/* This function is hooked as final emit function, which can verify the
correctness. */
-static void event_test_emit(TEST_QAPIEvent event, QDict *d, Error **errp)
+static void event_test_emit(test_QAPIEvent event, QDict *d, Error **errp)
{
QObject *obj;
QDict *t;
@@ -179,9 +179,7 @@ static void test_event_c(TestEventData *data,
QDict *d, *d_data, *d_b;
UserDefOne b;
- UserDefZero z;
- z.integer = 2;
- b.base = &z;
+ b.integer = 2;
b.string = g_strdup("test1");
b.has_enum1 = false;
@@ -209,11 +207,9 @@ static void test_event_d(TestEventData *data,
{
UserDefOne struct1;
EventStructOne a;
- UserDefZero z;
QDict *d, *d_data, *d_a, *d_struct1;
- z.integer = 2;
- struct1.base = &z;
+ struct1.integer = 2;
struct1.string = g_strdup("test1");
struct1.has_enum1 = true;
struct1.enum1 = ENUM_ONE_VALUE1;
diff --git a/qemu/tests/test-qmp-input-strict.c b/qemu/tests/test-qmp-input-strict.c
index 68f855bdf..d71727e27 100644
--- a/qemu/tests/test-qmp-input-strict.c
+++ b/qemu/tests/test-qmp-input-strict.c
@@ -11,14 +11,18 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdarg.h>
#include "qemu-common.h"
+#include "qapi/error.h"
#include "qapi/qmp-input-visitor.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
#include "qapi/qmp/types.h"
+#include "test-qmp-introspect.h"
+#include "qmp-introspect.h"
+#include "qapi-visit.h"
typedef struct TestInputVisitorData {
QObject *obj;
@@ -37,78 +41,65 @@ static void validate_teardown(TestInputVisitorData *data,
}
}
-/* This is provided instead of a test setup function so that the JSON
- string used by the tests are kept in the test functions (and not
- int main()) */
-static GCC_FMT_ATTR(2, 3)
-Visitor *validate_test_init(TestInputVisitorData *data,
- const char *json_string, ...)
+/* The various test_init functions are provided instead of a test setup
+ function so that the JSON string used by the tests are kept in the test
+ functions (and not in main()). */
+static Visitor *validate_test_init_internal(TestInputVisitorData *data,
+ const char *json_string,
+ va_list *ap)
{
Visitor *v;
- va_list ap;
- va_start(ap, json_string);
- data->obj = qobject_from_jsonv(json_string, &ap);
- va_end(ap);
+ validate_teardown(data, NULL);
- g_assert(data->obj != NULL);
+ data->obj = qobject_from_jsonv(json_string, ap);
+ g_assert(data->obj);
data->qiv = qmp_input_visitor_new_strict(data->obj);
- g_assert(data->qiv != NULL);
+ g_assert(data->qiv);
v = qmp_input_get_visitor(data->qiv);
- g_assert(v != NULL);
+ g_assert(v);
return v;
}
-typedef struct TestStruct
-{
- int64_t integer;
- bool boolean;
- char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
- const char *name, Error **errp)
+static GCC_FMT_ATTR(2, 3)
+Visitor *validate_test_init(TestInputVisitorData *data,
+ const char *json_string, ...)
{
- Error *err = NULL;
+ Visitor *v;
+ va_list ap;
- visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
- &err);
- if (err) {
- goto out;
- }
+ va_start(ap, json_string);
+ v = validate_test_init_internal(data, json_string, &ap);
+ va_end(ap);
+ return v;
+}
- visit_type_int(v, &(*obj)->integer, "integer", &err);
- if (err) {
- goto out_end;
- }
- visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
- if (err) {
- goto out_end;
- }
- visit_type_str(v, &(*obj)->string, "string", &err);
-
-out_end:
- error_propagate(errp, err);
- err = NULL;
- visit_end_struct(v, &err);
-out:
- error_propagate(errp, err);
+/* similar to validate_test_init(), but does not expect a string
+ * literal/format json_string argument and so can be used for
+ * programatically generated strings (and we can't pass in programatically
+ * generated strings via %s format parameters since qobject_from_jsonv()
+ * will wrap those in double-quotes and treat the entire object as a
+ * string)
+ */
+static Visitor *validate_test_init_raw(TestInputVisitorData *data,
+ const char *json_string)
+{
+ return validate_test_init_internal(data, json_string, NULL);
}
+
static void test_validate_struct(TestInputVisitorData *data,
const void *unused)
{
TestStruct *p = NULL;
- Error *err = NULL;
Visitor *v;
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
- visit_type_TestStruct(v, &p, NULL, &err);
- g_assert(!err);
+ visit_type_TestStruct(v, NULL, &p, &error_abort);
g_free(p->string);
g_free(p);
}
@@ -117,7 +108,6 @@ static void test_validate_struct_nested(TestInputVisitorData *data,
const void *unused)
{
UserDefTwo *udp = NULL;
- Error *err = NULL;
Visitor *v;
v = validate_test_init(data, "{ 'string0': 'string0', "
@@ -125,8 +115,7 @@ static void test_validate_struct_nested(TestInputVisitorData *data,
"'dict2': { 'userdef': { 'integer': 42, "
"'string': 'string' }, 'string': 'string2'}}}");
- visit_type_UserDefTwo(v, &udp, NULL, &err);
- g_assert(!err);
+ visit_type_UserDefTwo(v, NULL, &udp, &error_abort);
qapi_free_UserDefTwo(udp);
}
@@ -134,13 +123,11 @@ static void test_validate_list(TestInputVisitorData *data,
const void *unused)
{
UserDefOneList *head = NULL;
- Error *err = NULL;
Visitor *v;
v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
- visit_type_UserDefOneList(v, &head, NULL, &err);
- g_assert(!err);
+ visit_type_UserDefOneList(v, NULL, &head, &error_abort);
qapi_free_UserDefOneList(head);
}
@@ -149,12 +136,10 @@ static void test_validate_union_native_list(TestInputVisitorData *data,
{
UserDefNativeListUnion *tmp = NULL;
Visitor *v;
- Error *err = NULL;
v = validate_test_init(data, "{ 'type': 'integer', 'data' : [ 1, 2 ] }");
- visit_type_UserDefNativeListUnion(v, &tmp, NULL, &err);
- g_assert(!err);
+ visit_type_UserDefNativeListUnion(v, NULL, &tmp, &error_abort);
qapi_free_UserDefNativeListUnion(tmp);
}
@@ -163,16 +148,14 @@ static void test_validate_union_flat(TestInputVisitorData *data,
{
UserDefFlatUnion *tmp = NULL;
Visitor *v;
- Error *err = NULL;
v = validate_test_init(data,
"{ 'enum1': 'value1', "
+ "'integer': 41, "
"'string': 'str', "
"'boolean': true }");
- /* TODO when generator bug is fixed, add 'integer': 41 */
- visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
- g_assert(!err);
+ visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
qapi_free_UserDefFlatUnion(tmp);
}
@@ -181,12 +164,10 @@ static void test_validate_alternate(TestInputVisitorData *data,
{
UserDefAlternate *tmp = NULL;
Visitor *v;
- Error *err = NULL;
v = validate_test_init(data, "42");
- visit_type_UserDefAlternate(v, &tmp, NULL, &err);
- g_assert(!err);
+ visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
qapi_free_UserDefAlternate(tmp);
}
@@ -199,8 +180,8 @@ static void test_validate_fail_struct(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
- visit_type_TestStruct(v, &p, NULL, &err);
- g_assert(err);
+ visit_type_TestStruct(v, NULL, &p, &err);
+ error_free_or_abort(&err);
if (p) {
g_free(p->string);
}
@@ -216,8 +197,8 @@ static void test_validate_fail_struct_nested(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string', 'extra': [42, 23, {'foo':'bar'}] }, 'string2': 'string2'}}}");
- visit_type_UserDefTwo(v, &udp, NULL, &err);
- g_assert(err);
+ visit_type_UserDefTwo(v, NULL, &udp, &err);
+ error_free_or_abort(&err);
qapi_free_UserDefTwo(udp);
}
@@ -230,8 +211,8 @@ static void test_validate_fail_list(TestInputVisitorData *data,
v = validate_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44, 'extra': 'ggg' } ]");
- visit_type_UserDefOneList(v, &head, NULL, &err);
- g_assert(err);
+ visit_type_UserDefOneList(v, NULL, &head, &err);
+ error_free_or_abort(&err);
qapi_free_UserDefOneList(head);
}
@@ -245,8 +226,8 @@ static void test_validate_fail_union_native_list(TestInputVisitorData *data,
v = validate_test_init(data,
"{ 'type': 'integer', 'data' : [ 'string' ] }");
- visit_type_UserDefNativeListUnion(v, &tmp, NULL, &err);
- g_assert(err);
+ visit_type_UserDefNativeListUnion(v, NULL, &tmp, &err);
+ error_free_or_abort(&err);
qapi_free_UserDefNativeListUnion(tmp);
}
@@ -259,8 +240,8 @@ static void test_validate_fail_union_flat(TestInputVisitorData *data,
v = validate_test_init(data, "{ 'string': 'c', 'integer': 41, 'boolean': true }");
- visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
- g_assert(err);
+ visit_type_UserDefFlatUnion(v, NULL, &tmp, &err);
+ error_free_or_abort(&err);
qapi_free_UserDefFlatUnion(tmp);
}
@@ -272,10 +253,10 @@ static void test_validate_fail_union_flat_no_discrim(TestInputVisitorData *data,
Visitor *v;
/* test situation where discriminator field ('enum1' here) is missing */
- v = validate_test_init(data, "{ 'string': 'c', 'string1': 'd', 'string2': 'e' }");
+ v = validate_test_init(data, "{ 'integer': 42, 'string': 'c', 'string1': 'd', 'string2': 'e' }");
- visit_type_UserDefFlatUnion2(v, &tmp, NULL, &err);
- g_assert(err);
+ visit_type_UserDefFlatUnion2(v, NULL, &tmp, &err);
+ error_free_or_abort(&err);
qapi_free_UserDefFlatUnion2(tmp);
}
@@ -288,11 +269,32 @@ static void test_validate_fail_alternate(TestInputVisitorData *data,
v = validate_test_init(data, "3.14");
- visit_type_UserDefAlternate(v, &tmp, NULL, &err);
- g_assert(err);
+ visit_type_UserDefAlternate(v, NULL, &tmp, &err);
+ error_free_or_abort(&err);
qapi_free_UserDefAlternate(tmp);
}
+static void do_test_validate_qmp_introspect(TestInputVisitorData *data,
+ const char *schema_json)
+{
+ SchemaInfoList *schema = NULL;
+ Visitor *v;
+
+ v = validate_test_init_raw(data, schema_json);
+
+ visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
+ g_assert(schema);
+
+ qapi_free_SchemaInfoList(schema);
+}
+
+static void test_validate_qmp_introspect(TestInputVisitorData *data,
+ const void *unused)
+{
+ do_test_validate_qmp_introspect(data, test_qmp_schema_json);
+ do_test_validate_qmp_introspect(data, qmp_schema_json);
+}
+
static void validate_test_add(const char *testpath,
TestInputVisitorData *data,
void (*test_func)(TestInputVisitorData *data, const void *user_data))
@@ -333,6 +335,8 @@ int main(int argc, char **argv)
&testdata, test_validate_fail_alternate);
validate_test_add("/visitor/input-strict/fail/union-native-list",
&testdata, test_validate_fail_union_native_list);
+ validate_test_add("/visitor/input-strict/pass/qmp-introspect",
+ &testdata, test_validate_qmp_introspect);
g_test_run();
diff --git a/qemu/tests/test-qmp-input-visitor.c b/qemu/tests/test-qmp-input-visitor.c
index b96195309..80527eb85 100644
--- a/qemu/tests/test-qmp-input-visitor.c
+++ b/qemu/tests/test-qmp-input-visitor.c
@@ -1,7 +1,7 @@
/*
* QMP Input Visitor unit-tests.
*
- * Copyright (C) 2011, 2015 Red Hat Inc.
+ * Copyright (C) 2011-2016 Red Hat Inc.
*
* Authors:
* Luiz Capitulino <lcapitulino@redhat.com>
@@ -10,10 +10,11 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdarg.h>
#include "qemu-common.h"
+#include "qapi/error.h"
#include "qapi/qmp-input-visitor.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
@@ -36,31 +37,42 @@ static void visitor_input_teardown(TestInputVisitorData *data,
}
}
-/* This is provided instead of a test setup function so that the JSON
- string used by the tests are kept in the test functions (and not
- int main()) */
-static GCC_FMT_ATTR(2, 3)
-Visitor *visitor_input_test_init(TestInputVisitorData *data,
- const char *json_string, ...)
+/* The various test_init functions are provided instead of a test setup
+ function so that the JSON string used by the tests are kept in the test
+ functions (and not in main()). */
+static Visitor *visitor_input_test_init_internal(TestInputVisitorData *data,
+ const char *json_string,
+ va_list *ap)
{
Visitor *v;
- va_list ap;
- va_start(ap, json_string);
- data->obj = qobject_from_jsonv(json_string, &ap);
- va_end(ap);
+ visitor_input_teardown(data, NULL);
- g_assert(data->obj != NULL);
+ data->obj = qobject_from_jsonv(json_string, ap);
+ g_assert(data->obj);
data->qiv = qmp_input_visitor_new(data->obj);
- g_assert(data->qiv != NULL);
+ g_assert(data->qiv);
v = qmp_input_get_visitor(data->qiv);
- g_assert(v != NULL);
+ g_assert(v);
return v;
}
+static GCC_FMT_ATTR(2, 3)
+Visitor *visitor_input_test_init(TestInputVisitorData *data,
+ const char *json_string, ...)
+{
+ Visitor *v;
+ va_list ap;
+
+ va_start(ap, json_string);
+ v = visitor_input_test_init_internal(data, json_string, &ap);
+ va_end(ap);
+ return v;
+}
+
/* similar to visitor_input_test_init(), but does not expect a string
* literal/format json_string argument and so can be used for
* programatically generated strings (and we can't pass in programatically
@@ -71,32 +83,18 @@ Visitor *visitor_input_test_init(TestInputVisitorData *data,
static Visitor *visitor_input_test_init_raw(TestInputVisitorData *data,
const char *json_string)
{
- Visitor *v;
-
- data->obj = qobject_from_json(json_string);
-
- g_assert(data->obj != NULL);
-
- data->qiv = qmp_input_visitor_new(data->obj);
- g_assert(data->qiv != NULL);
-
- v = qmp_input_get_visitor(data->qiv);
- g_assert(v != NULL);
-
- return v;
+ return visitor_input_test_init_internal(data, json_string, NULL);
}
static void test_visitor_in_int(TestInputVisitorData *data,
const void *unused)
{
int64_t res = 0, value = -42;
- Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "%" PRId64, value);
- visit_type_int(v, &res, NULL, &err);
- g_assert(!err);
+ visit_type_int(v, NULL, &res, &error_abort);
g_assert_cmpint(res, ==, value);
}
@@ -113,22 +111,19 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
*/
v = visitor_input_test_init(data, "%f", DBL_MAX);
- visit_type_int(v, &res, NULL, &err);
- g_assert(err);
- error_free(err);
+ visit_type_int(v, NULL, &res, &err);
+ error_free_or_abort(&err);
}
static void test_visitor_in_bool(TestInputVisitorData *data,
const void *unused)
{
- Error *err = NULL;
bool res = false;
Visitor *v;
v = visitor_input_test_init(data, "true");
- visit_type_bool(v, &res, NULL, &err);
- g_assert(!err);
+ visit_type_bool(v, NULL, &res, &error_abort);
g_assert_cmpint(res, ==, true);
}
@@ -136,13 +131,11 @@ static void test_visitor_in_number(TestInputVisitorData *data,
const void *unused)
{
double res = 0, value = 3.14;
- Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "%f", value);
- visit_type_number(v, &res, NULL, &err);
- g_assert(!err);
+ visit_type_number(v, NULL, &res, &error_abort);
g_assert_cmpfloat(res, ==, value);
}
@@ -150,13 +143,11 @@ static void test_visitor_in_string(TestInputVisitorData *data,
const void *unused)
{
char *res = NULL, *value = (char *) "Q E M U";
- Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "%s", value);
- visit_type_str(v, &res, NULL, &err);
- g_assert(!err);
+ visit_type_str(v, NULL, &res, &error_abort);
g_assert_cmpstr(res, ==, value);
g_free(res);
@@ -165,7 +156,6 @@ static void test_visitor_in_string(TestInputVisitorData *data,
static void test_visitor_in_enum(TestInputVisitorData *data,
const void *unused)
{
- Error *err = NULL;
Visitor *v;
EnumOne i;
@@ -174,63 +164,21 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
- visit_type_EnumOne(v, &res, NULL, &err);
- g_assert(!err);
+ visit_type_EnumOne(v, NULL, &res, &error_abort);
g_assert_cmpint(i, ==, res);
-
- visitor_input_teardown(data, NULL);
}
-
- data->obj = NULL;
- data->qiv = NULL;
}
-typedef struct TestStruct
-{
- int64_t integer;
- bool boolean;
- char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
- const char *name, Error **errp)
-{
- Error *err = NULL;
-
- visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
- &err);
- if (err) {
- goto out;
- }
- visit_type_int(v, &(*obj)->integer, "integer", &err);
- if (err) {
- goto out_end;
- }
- visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
- if (err) {
- goto out_end;
- }
- visit_type_str(v, &(*obj)->string, "string", &err);
-
-out_end:
- error_propagate(errp, err);
- err = NULL;
- visit_end_struct(v, &err);
-out:
- error_propagate(errp, err);
-}
static void test_visitor_in_struct(TestInputVisitorData *data,
const void *unused)
{
TestStruct *p = NULL;
- Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
- visit_type_TestStruct(v, &p, NULL, &err);
- g_assert(!err);
+ visit_type_TestStruct(v, NULL, &p, &error_abort);
g_assert_cmpint(p->integer, ==, -42);
g_assert(p->boolean == true);
g_assert_cmpstr(p->string, ==, "foo");
@@ -239,17 +187,10 @@ static void test_visitor_in_struct(TestInputVisitorData *data,
g_free(p);
}
-static void check_and_free_str(char *str, const char *cmp)
-{
- g_assert_cmpstr(str, ==, cmp);
- g_free(str);
-}
-
static void test_visitor_in_struct_nested(TestInputVisitorData *data,
const void *unused)
{
UserDefTwo *udp = NULL;
- Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "{ 'string0': 'string0', "
@@ -257,34 +198,28 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
"'dict2': { 'userdef': { 'integer': 42, "
"'string': 'string' }, 'string': 'string2'}}}");
- visit_type_UserDefTwo(v, &udp, NULL, &err);
- g_assert(!err);
+ visit_type_UserDefTwo(v, NULL, &udp, &error_abort);
- check_and_free_str(udp->string0, "string0");
- check_and_free_str(udp->dict1->string1, "string1");
- g_assert_cmpint(udp->dict1->dict2->userdef->base->integer, ==, 42);
- check_and_free_str(udp->dict1->dict2->userdef->string, "string");
- check_and_free_str(udp->dict1->dict2->string, "string2");
+ g_assert_cmpstr(udp->string0, ==, "string0");
+ g_assert_cmpstr(udp->dict1->string1, ==, "string1");
+ g_assert_cmpint(udp->dict1->dict2->userdef->integer, ==, 42);
+ g_assert_cmpstr(udp->dict1->dict2->userdef->string, ==, "string");
+ g_assert_cmpstr(udp->dict1->dict2->string, ==, "string2");
g_assert(udp->dict1->has_dict3 == false);
- g_free(udp->dict1->dict2->userdef);
- g_free(udp->dict1->dict2);
- g_free(udp->dict1);
- g_free(udp);
+ qapi_free_UserDefTwo(udp);
}
static void test_visitor_in_list(TestInputVisitorData *data,
const void *unused)
{
UserDefOneList *item, *head = NULL;
- Error *err = NULL;
Visitor *v;
int i;
v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]");
- visit_type_UserDefOneList(v, &head, NULL, &err);
- g_assert(!err);
+ visit_type_UserDefOneList(v, NULL, &head, &error_abort);
g_assert(head != NULL);
for (i = 0, item = head; item; item = item->next, i++) {
@@ -292,31 +227,80 @@ static void test_visitor_in_list(TestInputVisitorData *data,
snprintf(string, sizeof(string), "string%d", i);
g_assert_cmpstr(item->value->string, ==, string);
- g_assert_cmpint(item->value->base->integer, ==, 42 + i);
+ g_assert_cmpint(item->value->integer, ==, 42 + i);
}
qapi_free_UserDefOneList(head);
+ head = NULL;
+
+ /* An empty list is valid */
+ v = visitor_input_test_init(data, "[]");
+ visit_type_UserDefOneList(v, NULL, &head, &error_abort);
+ g_assert(!head);
+}
+
+static void test_visitor_in_any(TestInputVisitorData *data,
+ const void *unused)
+{
+ QObject *res = NULL;
+ Visitor *v;
+ QInt *qint;
+ QBool *qbool;
+ QString *qstring;
+ QDict *qdict;
+ QObject *qobj;
+
+ v = visitor_input_test_init(data, "-42");
+ visit_type_any(v, NULL, &res, &error_abort);
+ qint = qobject_to_qint(res);
+ g_assert(qint);
+ g_assert_cmpint(qint_get_int(qint), ==, -42);
+ qobject_decref(res);
+
+ v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
+ visit_type_any(v, NULL, &res, &error_abort);
+ qdict = qobject_to_qdict(res);
+ g_assert(qdict && qdict_size(qdict) == 3);
+ qobj = qdict_get(qdict, "integer");
+ g_assert(qobj);
+ qint = qobject_to_qint(qobj);
+ g_assert(qint);
+ g_assert_cmpint(qint_get_int(qint), ==, -42);
+ qobj = qdict_get(qdict, "boolean");
+ g_assert(qobj);
+ qbool = qobject_to_qbool(qobj);
+ g_assert(qbool);
+ g_assert(qbool_get_bool(qbool) == true);
+ qobj = qdict_get(qdict, "string");
+ g_assert(qobj);
+ qstring = qobject_to_qstring(qobj);
+ g_assert(qstring);
+ g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
+ qobject_decref(res);
}
static void test_visitor_in_union_flat(TestInputVisitorData *data,
const void *unused)
{
Visitor *v;
- Error *err = NULL;
UserDefFlatUnion *tmp;
+ UserDefUnionBase *base;
v = visitor_input_test_init(data,
"{ 'enum1': 'value1', "
+ "'integer': 41, "
"'string': 'str', "
"'boolean': true }");
- /* TODO when generator bug is fixed, add 'integer': 41 */
- visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
- g_assert(err == NULL);
- g_assert_cmpint(tmp->kind, ==, ENUM_ONE_VALUE1);
+ visit_type_UserDefFlatUnion(v, NULL, &tmp, &error_abort);
+ g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
g_assert_cmpstr(tmp->string, ==, "str");
- /* TODO g_assert_cmpint(tmp->integer, ==, 41); */
- g_assert_cmpint(tmp->value1->boolean, ==, true);
+ g_assert_cmpint(tmp->integer, ==, 41);
+ g_assert_cmpint(tmp->u.value1.boolean, ==, true);
+
+ base = qapi_UserDefFlatUnion_base(tmp);
+ g_assert(&base->enum1 == &tmp->enum1);
+
qapi_free_UserDefFlatUnion(tmp);
}
@@ -326,14 +310,144 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
Visitor *v;
Error *err = NULL;
UserDefAlternate *tmp;
+ WrapAlternate *wrap;
v = visitor_input_test_init(data, "42");
+ visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
+ g_assert_cmpint(tmp->type, ==, QTYPE_QINT);
+ g_assert_cmpint(tmp->u.i, ==, 42);
+ qapi_free_UserDefAlternate(tmp);
+
+ v = visitor_input_test_init(data, "'string'");
+ visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
+ g_assert_cmpint(tmp->type, ==, QTYPE_QSTRING);
+ g_assert_cmpstr(tmp->u.s, ==, "string");
+ qapi_free_UserDefAlternate(tmp);
+
+ v = visitor_input_test_init(data, "{'integer':1, 'string':'str', "
+ "'enum1':'value1', 'boolean':true}");
+ visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
+ g_assert_cmpint(tmp->type, ==, QTYPE_QDICT);
+ g_assert_cmpint(tmp->u.udfu.integer, ==, 1);
+ g_assert_cmpstr(tmp->u.udfu.string, ==, "str");
+ g_assert_cmpint(tmp->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
+ g_assert_cmpint(tmp->u.udfu.u.value1.boolean, ==, true);
+ g_assert_cmpint(tmp->u.udfu.u.value1.has_a_b, ==, false);
+ qapi_free_UserDefAlternate(tmp);
- visit_type_UserDefAlternate(v, &tmp, NULL, &err);
- g_assert(err == NULL);
- g_assert_cmpint(tmp->kind, ==, USER_DEF_ALTERNATE_KIND_I);
- g_assert_cmpint(tmp->i, ==, 42);
+ v = visitor_input_test_init(data, "false");
+ visit_type_UserDefAlternate(v, NULL, &tmp, &err);
+ error_free_or_abort(&err);
qapi_free_UserDefAlternate(tmp);
+
+ v = visitor_input_test_init(data, "{ 'alt': 42 }");
+ visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
+ g_assert_cmpint(wrap->alt->type, ==, QTYPE_QINT);
+ g_assert_cmpint(wrap->alt->u.i, ==, 42);
+ qapi_free_WrapAlternate(wrap);
+
+ v = visitor_input_test_init(data, "{ 'alt': 'string' }");
+ visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
+ g_assert_cmpint(wrap->alt->type, ==, QTYPE_QSTRING);
+ g_assert_cmpstr(wrap->alt->u.s, ==, "string");
+ qapi_free_WrapAlternate(wrap);
+
+ v = visitor_input_test_init(data, "{ 'alt': {'integer':1, 'string':'str', "
+ "'enum1':'value1', 'boolean':true} }");
+ visit_type_WrapAlternate(v, NULL, &wrap, &error_abort);
+ g_assert_cmpint(wrap->alt->type, ==, QTYPE_QDICT);
+ g_assert_cmpint(wrap->alt->u.udfu.integer, ==, 1);
+ g_assert_cmpstr(wrap->alt->u.udfu.string, ==, "str");
+ g_assert_cmpint(wrap->alt->u.udfu.enum1, ==, ENUM_ONE_VALUE1);
+ g_assert_cmpint(wrap->alt->u.udfu.u.value1.boolean, ==, true);
+ g_assert_cmpint(wrap->alt->u.udfu.u.value1.has_a_b, ==, false);
+ qapi_free_WrapAlternate(wrap);
+}
+
+static void test_visitor_in_alternate_number(TestInputVisitorData *data,
+ const void *unused)
+{
+ Visitor *v;
+ Error *err = NULL;
+ AltStrBool *asb;
+ AltStrNum *asn;
+ AltNumStr *ans;
+ AltStrInt *asi;
+ AltIntNum *ain;
+ AltNumInt *ani;
+
+ /* Parsing an int */
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltStrBool(v, NULL, &asb, &err);
+ error_free_or_abort(&err);
+ qapi_free_AltStrBool(asb);
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltStrNum(v, NULL, &asn, &error_abort);
+ g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
+ g_assert_cmpfloat(asn->u.n, ==, 42);
+ qapi_free_AltStrNum(asn);
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltNumStr(v, NULL, &ans, &error_abort);
+ g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
+ g_assert_cmpfloat(ans->u.n, ==, 42);
+ qapi_free_AltNumStr(ans);
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltStrInt(v, NULL, &asi, &error_abort);
+ g_assert_cmpint(asi->type, ==, QTYPE_QINT);
+ g_assert_cmpint(asi->u.i, ==, 42);
+ qapi_free_AltStrInt(asi);
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltIntNum(v, NULL, &ain, &error_abort);
+ g_assert_cmpint(ain->type, ==, QTYPE_QINT);
+ g_assert_cmpint(ain->u.i, ==, 42);
+ qapi_free_AltIntNum(ain);
+
+ v = visitor_input_test_init(data, "42");
+ visit_type_AltNumInt(v, NULL, &ani, &error_abort);
+ g_assert_cmpint(ani->type, ==, QTYPE_QINT);
+ g_assert_cmpint(ani->u.i, ==, 42);
+ qapi_free_AltNumInt(ani);
+
+ /* Parsing a double */
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltStrBool(v, NULL, &asb, &err);
+ error_free_or_abort(&err);
+ qapi_free_AltStrBool(asb);
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltStrNum(v, NULL, &asn, &error_abort);
+ g_assert_cmpint(asn->type, ==, QTYPE_QFLOAT);
+ g_assert_cmpfloat(asn->u.n, ==, 42.5);
+ qapi_free_AltStrNum(asn);
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltNumStr(v, NULL, &ans, &error_abort);
+ g_assert_cmpint(ans->type, ==, QTYPE_QFLOAT);
+ g_assert_cmpfloat(ans->u.n, ==, 42.5);
+ qapi_free_AltNumStr(ans);
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltStrInt(v, NULL, &asi, &err);
+ error_free_or_abort(&err);
+ qapi_free_AltStrInt(asi);
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltIntNum(v, NULL, &ain, &error_abort);
+ g_assert_cmpint(ain->type, ==, QTYPE_QFLOAT);
+ g_assert_cmpfloat(ain->u.n, ==, 42.5);
+ qapi_free_AltIntNum(ain);
+
+ v = visitor_input_test_init(data, "42.5");
+ visit_type_AltNumInt(v, NULL, &ani, &error_abort);
+ g_assert_cmpint(ani->type, ==, QTYPE_QFLOAT);
+ g_assert_cmpfloat(ani->u.n, ==, 42.5);
+ qapi_free_AltNumInt(ani);
}
static void test_native_list_integer_helper(TestInputVisitorData *data,
@@ -341,7 +455,6 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
UserDefNativeListUnionKind kind)
{
UserDefNativeListUnion *cvalue = NULL;
- Error *err = NULL;
Visitor *v;
GString *gstr_list = g_string_new("");
GString *gstr_union = g_string_new("");
@@ -358,71 +471,71 @@ static void test_native_list_integer_helper(TestInputVisitorData *data,
gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str);
- visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
- g_assert(err == NULL);
+ visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->kind, ==, kind);
+ g_assert_cmpint(cvalue->type, ==, kind);
switch (kind) {
case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
intList *elem = NULL;
- for (i = 0, elem = cvalue->integer; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.integer.data;
+ elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
int8List *elem = NULL;
- for (i = 0, elem = cvalue->s8; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.s8.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
int16List *elem = NULL;
- for (i = 0, elem = cvalue->s16; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.s16.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
int32List *elem = NULL;
- for (i = 0, elem = cvalue->s32; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.s32.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
int64List *elem = NULL;
- for (i = 0, elem = cvalue->s64; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.s64.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
uint8List *elem = NULL;
- for (i = 0, elem = cvalue->u8; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.u8.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
uint16List *elem = NULL;
- for (i = 0, elem = cvalue->u16; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.u16.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
uint32List *elem = NULL;
- for (i = 0, elem = cvalue->u32; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.u32.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
uint64List *elem = NULL;
- for (i = 0, elem = cvalue->u64; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.u64.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, i);
}
break;
@@ -504,7 +617,6 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
{
UserDefNativeListUnion *cvalue = NULL;
boolList *elem = NULL;
- Error *err = NULL;
Visitor *v;
GString *gstr_list = g_string_new("");
GString *gstr_union = g_string_new("");
@@ -521,12 +633,11 @@ static void test_visitor_in_native_list_bool(TestInputVisitorData *data,
gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str);
- visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
- g_assert(err == NULL);
+ visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
+ g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN);
- for (i = 0, elem = cvalue->boolean; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.boolean.data; elem; elem = elem->next, i++) {
g_assert_cmpint(elem->value, ==, (i % 3 == 0) ? 1 : 0);
}
@@ -540,7 +651,6 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data,
{
UserDefNativeListUnion *cvalue = NULL;
strList *elem = NULL;
- Error *err = NULL;
Visitor *v;
GString *gstr_list = g_string_new("");
GString *gstr_union = g_string_new("");
@@ -556,12 +666,11 @@ static void test_visitor_in_native_list_string(TestInputVisitorData *data,
gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str);
- visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
- g_assert(err == NULL);
+ visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
+ g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_STRING);
- for (i = 0, elem = cvalue->string; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.string.data; elem; elem = elem->next, i++) {
gchar str[8];
sprintf(str, "%d", i);
g_assert_cmpstr(elem->value, ==, str);
@@ -579,7 +688,6 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data,
{
UserDefNativeListUnion *cvalue = NULL;
numberList *elem = NULL;
- Error *err = NULL;
Visitor *v;
GString *gstr_list = g_string_new("");
GString *gstr_union = g_string_new("");
@@ -595,12 +703,11 @@ static void test_visitor_in_native_list_number(TestInputVisitorData *data,
gstr_list->str);
v = visitor_input_test_init_raw(data, gstr_union->str);
- visit_type_UserDefNativeListUnion(v, &cvalue, NULL, &err);
- g_assert(err == NULL);
+ visit_type_UserDefNativeListUnion(v, NULL, &cvalue, &error_abort);
g_assert(cvalue != NULL);
- g_assert_cmpint(cvalue->kind, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
+ g_assert_cmpint(cvalue->type, ==, USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER);
- for (i = 0, elem = cvalue->number; elem; elem = elem->next, i++) {
+ for (i = 0, elem = cvalue->u.number.data; elem; elem = elem->next, i++) {
GString *double_expected = g_string_new("");
GString *double_actual = g_string_new("");
@@ -631,16 +738,69 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
TestStruct *p = NULL;
Error *err = NULL;
Visitor *v;
+ strList *q = NULL;
- v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
+ v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', "
+ "'string': -42 }");
- visit_type_TestStruct(v, &p, NULL, &err);
- g_assert(err);
+ visit_type_TestStruct(v, NULL, &p, &err);
+ error_free_or_abort(&err);
+ /* FIXME - a failed parse should not leave a partially-allocated p
+ * for us to clean up; this could cause callers to leak memory. */
g_assert(p->string == NULL);
- error_free(err);
g_free(p->string);
g_free(p);
+
+ v = visitor_input_test_init(data, "[ '1', '2', false, '3' ]");
+ visit_type_strList(v, NULL, &q, &err);
+ error_free_or_abort(&err);
+ assert(q);
+ qapi_free_strList(q);
+}
+
+static void test_visitor_in_wrong_type(TestInputVisitorData *data,
+ const void *unused)
+{
+ TestStruct *p = NULL;
+ Visitor *v;
+ strList *q = NULL;
+ int64_t i;
+ Error *err = NULL;
+
+ /* Make sure arrays and structs cannot be confused */
+
+ v = visitor_input_test_init(data, "[]");
+ visit_type_TestStruct(v, NULL, &p, &err);
+ error_free_or_abort(&err);
+ g_assert(!p);
+
+ v = visitor_input_test_init(data, "{}");
+ visit_type_strList(v, NULL, &q, &err);
+ error_free_or_abort(&err);
+ assert(!q);
+
+ /* Make sure primitives and struct cannot be confused */
+
+ v = visitor_input_test_init(data, "1");
+ visit_type_TestStruct(v, NULL, &p, &err);
+ error_free_or_abort(&err);
+ g_assert(!p);
+
+ v = visitor_input_test_init(data, "{}");
+ visit_type_int(v, NULL, &i, &err);
+ error_free_or_abort(&err);
+
+ /* Make sure primitives and arrays cannot be confused */
+
+ v = visitor_input_test_init(data, "1");
+ visit_type_strList(v, NULL, &q, &err);
+ error_free_or_abort(&err);
+ assert(!q);
+
+ v = visitor_input_test_init(data, "[]");
+ visit_type_int(v, NULL, &i, &err);
+ error_free_or_abort(&err);
}
int main(int argc, char **argv)
@@ -667,12 +827,18 @@ int main(int argc, char **argv)
&in_visitor_data, test_visitor_in_struct_nested);
input_visitor_test_add("/visitor/input/list",
&in_visitor_data, test_visitor_in_list);
+ input_visitor_test_add("/visitor/input/any",
+ &in_visitor_data, test_visitor_in_any);
input_visitor_test_add("/visitor/input/union-flat",
&in_visitor_data, test_visitor_in_union_flat);
input_visitor_test_add("/visitor/input/alternate",
&in_visitor_data, test_visitor_in_alternate);
input_visitor_test_add("/visitor/input/errors",
&in_visitor_data, test_visitor_in_errors);
+ input_visitor_test_add("/visitor/input/wrong-type",
+ &in_visitor_data, test_visitor_in_wrong_type);
+ input_visitor_test_add("/visitor/input/alternate-number",
+ &in_visitor_data, test_visitor_in_alternate_number);
input_visitor_test_add("/visitor/input/native_list/int",
&in_visitor_data,
test_visitor_in_native_list_int);
diff --git a/qemu/tests/test-qmp-output-visitor.c b/qemu/tests/test-qmp-output-visitor.c
index 87ba350b4..c70926793 100644
--- a/qemu/tests/test-qmp-output-visitor.c
+++ b/qemu/tests/test-qmp-output-visitor.c
@@ -1,7 +1,7 @@
/*
* QMP Output Visitor unit-tests.
*
- * Copyright (C) 2011, 2015 Red Hat Inc.
+ * Copyright (C) 2011-2016 Red Hat Inc.
*
* Authors:
* Luiz Capitulino <lcapitulino@redhat.com>
@@ -10,9 +10,11 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qemu-common.h"
+#include "qapi/error.h"
#include "qapi/qmp-output-visitor.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
@@ -45,11 +47,9 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
const void *unused)
{
int64_t value = -42;
- Error *err = NULL;
QObject *obj;
- visit_type_int(data->ov, &value, NULL, &err);
- g_assert(!err);
+ visit_type_int(data->ov, NULL, &value, &error_abort);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -62,12 +62,10 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
static void test_visitor_out_bool(TestOutputVisitorData *data,
const void *unused)
{
- Error *err = NULL;
bool value = true;
QObject *obj;
- visit_type_bool(data->ov, &value, NULL, &err);
- g_assert(!err);
+ visit_type_bool(data->ov, NULL, &value, &error_abort);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -81,11 +79,9 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
const void *unused)
{
double value = 3.14;
- Error *err = NULL;
QObject *obj;
- visit_type_number(data->ov, &value, NULL, &err);
- g_assert(!err);
+ visit_type_number(data->ov, NULL, &value, &error_abort);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -99,11 +95,9 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
const void *unused)
{
char *string = (char *) "Q E M U";
- Error *err = NULL;
QObject *obj;
- visit_type_str(data->ov, &string, NULL, &err);
- g_assert(!err);
+ visit_type_str(data->ov, NULL, &string, &error_abort);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -117,12 +111,10 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
const void *unused)
{
char *string = NULL;
- Error *err = NULL;
QObject *obj;
/* A null string should return "" */
- visit_type_str(data->ov, &string, NULL, &err);
- g_assert(!err);
+ visit_type_str(data->ov, NULL, &string, &error_abort);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -135,13 +127,11 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
static void test_visitor_out_enum(TestOutputVisitorData *data,
const void *unused)
{
- Error *err = NULL;
QObject *obj;
EnumOne i;
- for (i = 0; i < ENUM_ONE_MAX; i++) {
- visit_type_EnumOne(data->ov, &i, "unused", &err);
- g_assert(!err);
+ for (i = 0; i < ENUM_ONE__MAX; i++) {
+ visit_type_EnumOne(data->ov, "unused", &i, &error_abort);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -155,52 +145,17 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
const void *unused)
{
- EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+ EnumOne i, bad_values[] = { ENUM_ONE__MAX, -1 };
Error *err;
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
err = NULL;
- visit_type_EnumOne(data->ov, &bad_values[i], "unused", &err);
+ visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err);
g_assert(err);
error_free(err);
}
}
-typedef struct TestStruct
-{
- int64_t integer;
- bool boolean;
- char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
- const char *name, Error **errp)
-{
- Error *err = NULL;
-
- visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
- &err);
- if (err) {
- goto out;
- }
-
- visit_type_int(v, &(*obj)->integer, "integer", &err);
- if (err) {
- goto out_end;
- }
- visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
- if (err) {
- goto out_end;
- }
- visit_type_str(v, &(*obj)->string, "string", &err);
-
-out_end:
- error_propagate(errp, err);
- err = NULL;
- visit_end_struct(v, &err);
-out:
- error_propagate(errp, err);
-}
static void test_visitor_out_struct(TestOutputVisitorData *data,
const void *unused)
@@ -209,12 +164,10 @@ static void test_visitor_out_struct(TestOutputVisitorData *data,
.boolean = false,
.string = (char *) "foo"};
TestStruct *p = &test_struct;
- Error *err = NULL;
QObject *obj;
QDict *qdict;
- visit_type_TestStruct(data->ov, &p, NULL, &err);
- g_assert(!err);
+ visit_type_TestStruct(data->ov, NULL, &p, &error_abort);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -233,7 +186,6 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
const void *unused)
{
int64_t value = 42;
- Error *err = NULL;
UserDefTwo *ud2;
QObject *obj;
QDict *qdict, *dict1, *dict2, *dict3, *userdef;
@@ -250,20 +202,17 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
ud2->dict1->dict2 = g_malloc0(sizeof(*ud2->dict1->dict2));
ud2->dict1->dict2->userdef = g_new0(UserDefOne, 1);
ud2->dict1->dict2->userdef->string = g_strdup(string);
- ud2->dict1->dict2->userdef->base = g_new0(UserDefZero, 1);
- ud2->dict1->dict2->userdef->base->integer = value;
+ ud2->dict1->dict2->userdef->integer = value;
ud2->dict1->dict2->string = g_strdup(strings[2]);
ud2->dict1->dict3 = g_malloc0(sizeof(*ud2->dict1->dict3));
ud2->dict1->has_dict3 = true;
ud2->dict1->dict3->userdef = g_new0(UserDefOne, 1);
ud2->dict1->dict3->userdef->string = g_strdup(string);
- ud2->dict1->dict3->userdef->base = g_new0(UserDefZero, 1);
- ud2->dict1->dict3->userdef->base->integer = value;
+ ud2->dict1->dict3->userdef->integer = value;
ud2->dict1->dict3->string = g_strdup(strings[3]);
- visit_type_UserDefTwo(data->ov, &ud2, "unused", &err);
- g_assert(!err);
+ visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -300,9 +249,9 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
const void *unused)
{
- EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
- UserDefZero b;
- UserDefOne u = { .base = &b }, *pu = &u;
+ EnumOne bad_values[] = { ENUM_ONE__MAX, -1 };
+ UserDefOne u = {0};
+ UserDefOne *pu = &u;
Error *err;
int i;
@@ -310,63 +259,39 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
err = NULL;
u.has_enum1 = true;
u.enum1 = bad_values[i];
- visit_type_UserDefOne(data->ov, &pu, "unused", &err);
+ visit_type_UserDefOne(data->ov, "unused", &pu, &err);
g_assert(err);
error_free(err);
}
}
-typedef struct TestStructList
-{
- union {
- TestStruct *value;
- uint64_t padding;
- };
- struct TestStructList *next;
-} TestStructList;
-
-static void visit_type_TestStructList(Visitor *v, TestStructList **obj,
- const char *name, Error **errp)
-{
- GenericList *i, **head = (GenericList **)obj;
-
- visit_start_list(v, name, errp);
-
- for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) {
- TestStructList *native_i = (TestStructList *)i;
- visit_type_TestStruct(v, &native_i->value, NULL, errp);
- }
-
- visit_end_list(v, errp);
-}
static void test_visitor_out_list(TestOutputVisitorData *data,
const void *unused)
{
- char *value_str = (char *) "list value";
+ const char *value_str = "list value";
TestStructList *p, *head = NULL;
const int max_items = 10;
bool value_bool = true;
int value_int = 10;
- Error *err = NULL;
QListEntry *entry;
QObject *obj;
QList *qlist;
int i;
+ /* Build the list in reverse order... */
for (i = 0; i < max_items; i++) {
p = g_malloc0(sizeof(*p));
p->value = g_malloc0(sizeof(*p->value));
- p->value->integer = value_int;
+ p->value->integer = value_int + (max_items - i - 1);
p->value->boolean = value_bool;
- p->value->string = value_str;
+ p->value->string = g_strdup(value_str);
p->next = head;
head = p;
}
- visit_type_TestStructList(data->ov, &head, NULL, &err);
- g_assert(!err);
+ visit_type_TestStructList(data->ov, NULL, &head, &error_abort);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -375,6 +300,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
qlist = qobject_to_qlist(obj);
g_assert(!qlist_empty(qlist));
+ /* ...and ensure that the visitor sees it in order */
i = 0;
QLIST_FOREACH_ENTRY(qlist, entry) {
QDict *qdict;
@@ -382,7 +308,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
g_assert(qobject_type(entry->value) == QTYPE_QDICT);
qdict = qobject_to_qdict(entry->value);
g_assert_cmpint(qdict_size(qdict), ==, 3);
- g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int);
+ g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int + i);
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool);
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str);
i++;
@@ -390,13 +316,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
g_assert_cmpint(i, ==, max_items);
QDECREF(qlist);
-
- for (p = head; p;) {
- TestStructList *tmp = p->next;
- g_free(p->value);
- g_free(p);
- p = tmp;
- }
+ qapi_free_TestStructList(head);
}
static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
@@ -416,8 +336,7 @@ static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
p->value->dict1->dict2 = g_new0(UserDefTwoDictDict, 1);
p->value->dict1->dict2->userdef = g_new0(UserDefOne, 1);
p->value->dict1->dict2->userdef->string = g_strdup(string);
- p->value->dict1->dict2->userdef->base = g_new0(UserDefZero, 1);
- p->value->dict1->dict2->userdef->base->integer = 42;
+ p->value->dict1->dict2->userdef->integer = 42;
p->value->dict1->dict2->string = g_strdup(string);
p->value->dict1->has_dict3 = false;
@@ -428,23 +347,67 @@ static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data,
qapi_free_UserDefTwoList(head);
}
+static void test_visitor_out_any(TestOutputVisitorData *data,
+ const void *unused)
+{
+ QObject *qobj;
+ QInt *qint;
+ QBool *qbool;
+ QString *qstring;
+ QDict *qdict;
+ QObject *obj;
+
+ qobj = QOBJECT(qint_from_int(-42));
+ visit_type_any(data->ov, NULL, &qobj, &error_abort);
+ obj = qmp_output_get_qobject(data->qov);
+ g_assert(obj != NULL);
+ g_assert(qobject_type(obj) == QTYPE_QINT);
+ g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, -42);
+ qobject_decref(obj);
+ qobject_decref(qobj);
+
+ qdict = qdict_new();
+ qdict_put(qdict, "integer", qint_from_int(-42));
+ qdict_put(qdict, "boolean", qbool_from_bool(true));
+ qdict_put(qdict, "string", qstring_from_str("foo"));
+ qobj = QOBJECT(qdict);
+ visit_type_any(data->ov, NULL, &qobj, &error_abort);
+ qobject_decref(qobj);
+ obj = qmp_output_get_qobject(data->qov);
+ g_assert(obj != NULL);
+ qdict = qobject_to_qdict(obj);
+ g_assert(qdict);
+ qobj = qdict_get(qdict, "integer");
+ g_assert(qobj);
+ qint = qobject_to_qint(qobj);
+ g_assert(qint);
+ g_assert_cmpint(qint_get_int(qint), ==, -42);
+ qobj = qdict_get(qdict, "boolean");
+ g_assert(qobj);
+ qbool = qobject_to_qbool(qobj);
+ g_assert(qbool);
+ g_assert(qbool_get_bool(qbool) == true);
+ qobj = qdict_get(qdict, "string");
+ g_assert(qobj);
+ qstring = qobject_to_qstring(qobj);
+ g_assert(qstring);
+ g_assert_cmpstr(qstring_get_str(qstring), ==, "foo");
+ qobject_decref(obj);
+}
+
static void test_visitor_out_union_flat(TestOutputVisitorData *data,
const void *unused)
{
QObject *arg;
QDict *qdict;
- Error *err = NULL;
-
UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion));
- tmp->kind = ENUM_ONE_VALUE1;
+ tmp->enum1 = ENUM_ONE_VALUE1;
tmp->string = g_strdup("str");
- tmp->value1 = g_malloc0(sizeof(UserDefA));
- /* TODO when generator bug is fixed: tmp->integer = 41; */
- tmp->value1->boolean = true;
+ tmp->integer = 41;
+ tmp->u.value1.boolean = true;
- visit_type_UserDefFlatUnion(data->ov, &tmp, NULL, &err);
- g_assert(err == NULL);
+ visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort);
arg = qmp_output_get_qobject(data->qov);
g_assert(qobject_type(arg) == QTYPE_QDICT);
@@ -452,7 +415,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
- /* TODO g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41); */
+ g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 41);
g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
qapi_free_UserDefFlatUnion(tmp);
@@ -463,20 +426,55 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,
const void *unused)
{
QObject *arg;
- Error *err = NULL;
+ UserDefAlternate *tmp;
+ QDict *qdict;
- UserDefAlternate *tmp = g_malloc0(sizeof(UserDefAlternate));
- tmp->kind = USER_DEF_ALTERNATE_KIND_I;
- tmp->i = 42;
+ tmp = g_new0(UserDefAlternate, 1);
+ tmp->type = QTYPE_QINT;
+ tmp->u.i = 42;
- visit_type_UserDefAlternate(data->ov, &tmp, NULL, &err);
- g_assert(err == NULL);
+ visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
arg = qmp_output_get_qobject(data->qov);
g_assert(qobject_type(arg) == QTYPE_QINT);
g_assert_cmpint(qint_get_int(qobject_to_qint(arg)), ==, 42);
qapi_free_UserDefAlternate(tmp);
+ qobject_decref(arg);
+
+ tmp = g_new0(UserDefAlternate, 1);
+ tmp->type = QTYPE_QSTRING;
+ tmp->u.s = g_strdup("hello");
+
+ visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
+ arg = qmp_output_get_qobject(data->qov);
+
+ g_assert(qobject_type(arg) == QTYPE_QSTRING);
+ g_assert_cmpstr(qstring_get_str(qobject_to_qstring(arg)), ==, "hello");
+
+ qapi_free_UserDefAlternate(tmp);
+ qobject_decref(arg);
+
+ tmp = g_new0(UserDefAlternate, 1);
+ tmp->type = QTYPE_QDICT;
+ tmp->u.udfu.integer = 1;
+ tmp->u.udfu.string = g_strdup("str");
+ tmp->u.udfu.enum1 = ENUM_ONE_VALUE1;
+ tmp->u.udfu.u.value1.boolean = true;
+
+ visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
+ arg = qmp_output_get_qobject(data->qov);
+
+ g_assert_cmpint(qobject_type(arg), ==, QTYPE_QDICT);
+ qdict = qobject_to_qdict(arg);
+ g_assert_cmpint(qdict_size(qdict), ==, 4);
+ g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 1);
+ g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "str");
+ g_assert_cmpstr(qdict_get_str(qdict, "enum1"), ==, "value1");
+ g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, true);
+
+ qapi_free_UserDefAlternate(tmp);
+ qobject_decref(arg);
}
static void test_visitor_out_empty(TestOutputVisitorData *data,
@@ -485,15 +483,18 @@ static void test_visitor_out_empty(TestOutputVisitorData *data,
QObject *arg;
arg = qmp_output_get_qobject(data->qov);
- g_assert(!arg);
+ g_assert(qobject_type(arg) == QTYPE_QNULL);
+ /* Check that qnull reference counting is sane */
+ g_assert(arg->refcnt == 2);
+ qobject_decref(arg);
}
static void init_native_list(UserDefNativeListUnion *cvalue)
{
int i;
- switch (cvalue->kind) {
+ switch (cvalue->type) {
case USER_DEF_NATIVE_LIST_UNION_KIND_INTEGER: {
- intList **list = &cvalue->integer;
+ intList **list = &cvalue->u.integer.data;
for (i = 0; i < 32; i++) {
*list = g_new0(intList, 1);
(*list)->value = i;
@@ -503,7 +504,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_S8: {
- int8List **list = &cvalue->s8;
+ int8List **list = &cvalue->u.s8.data;
for (i = 0; i < 32; i++) {
*list = g_new0(int8List, 1);
(*list)->value = i;
@@ -513,7 +514,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_S16: {
- int16List **list = &cvalue->s16;
+ int16List **list = &cvalue->u.s16.data;
for (i = 0; i < 32; i++) {
*list = g_new0(int16List, 1);
(*list)->value = i;
@@ -523,7 +524,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_S32: {
- int32List **list = &cvalue->s32;
+ int32List **list = &cvalue->u.s32.data;
for (i = 0; i < 32; i++) {
*list = g_new0(int32List, 1);
(*list)->value = i;
@@ -533,7 +534,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_S64: {
- int64List **list = &cvalue->s64;
+ int64List **list = &cvalue->u.s64.data;
for (i = 0; i < 32; i++) {
*list = g_new0(int64List, 1);
(*list)->value = i;
@@ -543,7 +544,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_U8: {
- uint8List **list = &cvalue->u8;
+ uint8List **list = &cvalue->u.u8.data;
for (i = 0; i < 32; i++) {
*list = g_new0(uint8List, 1);
(*list)->value = i;
@@ -553,7 +554,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_U16: {
- uint16List **list = &cvalue->u16;
+ uint16List **list = &cvalue->u.u16.data;
for (i = 0; i < 32; i++) {
*list = g_new0(uint16List, 1);
(*list)->value = i;
@@ -563,7 +564,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_U32: {
- uint32List **list = &cvalue->u32;
+ uint32List **list = &cvalue->u.u32.data;
for (i = 0; i < 32; i++) {
*list = g_new0(uint32List, 1);
(*list)->value = i;
@@ -573,7 +574,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_U64: {
- uint64List **list = &cvalue->u64;
+ uint64List **list = &cvalue->u.u64.data;
for (i = 0; i < 32; i++) {
*list = g_new0(uint64List, 1);
(*list)->value = i;
@@ -583,7 +584,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_BOOLEAN: {
- boolList **list = &cvalue->boolean;
+ boolList **list = &cvalue->u.boolean.data;
for (i = 0; i < 32; i++) {
*list = g_new0(boolList, 1);
(*list)->value = (i % 3 == 0);
@@ -593,7 +594,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_STRING: {
- strList **list = &cvalue->string;
+ strList **list = &cvalue->u.string.data;
for (i = 0; i < 32; i++) {
*list = g_new0(strList, 1);
(*list)->value = g_strdup_printf("%d", i);
@@ -603,7 +604,7 @@ static void init_native_list(UserDefNativeListUnion *cvalue)
break;
}
case USER_DEF_NATIVE_LIST_UNION_KIND_NUMBER: {
- numberList **list = &cvalue->number;
+ numberList **list = &cvalue->u.number.data;
for (i = 0; i < 32; i++) {
*list = g_new0(numberList, 1);
(*list)->value = (double)i / 3;
@@ -709,17 +710,15 @@ static void test_native_list(TestOutputVisitorData *data,
UserDefNativeListUnionKind kind)
{
UserDefNativeListUnion *cvalue = g_new0(UserDefNativeListUnion, 1);
- Error *err = NULL;
QObject *obj;
- cvalue->kind = kind;
+ cvalue->type = kind;
init_native_list(cvalue);
- visit_type_UserDefNativeListUnion(data->ov, &cvalue, NULL, &err);
- g_assert(err == NULL);
+ visit_type_UserDefNativeListUnion(data->ov, NULL, &cvalue, &error_abort);
obj = qmp_output_get_qobject(data->qov);
- check_native_list(obj, cvalue->kind);
+ check_native_list(obj, cvalue->type);
qapi_free_UserDefNativeListUnion(cvalue);
qobject_decref(obj);
}
@@ -832,6 +831,8 @@ int main(int argc, char **argv)
&out_visitor_data, test_visitor_out_struct_errors);
output_visitor_test_add("/visitor/output/list",
&out_visitor_data, test_visitor_out_list);
+ output_visitor_test_add("/visitor/output/any",
+ &out_visitor_data, test_visitor_out_any);
output_visitor_test_add("/visitor/output/list-qapi-free",
&out_visitor_data, test_visitor_out_list_qapi_free);
output_visitor_test_add("/visitor/output/union-flat",
diff --git a/qemu/tests/test-rcu-list.c b/qemu/tests/test-rcu-list.c
index daa8bf41d..79d375014 100644
--- a/qemu/tests/test-rcu-list.c
+++ b/qemu/tests/test-rcu-list.c
@@ -20,14 +20,10 @@
* Copyright (c) 2013 Mike D. Day, IBM Corporation.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
#include "qemu/atomic.h"
#include "qemu/rcu.h"
-#include "qemu/compiler.h"
-#include "qemu/osdep.h"
#include "qemu/thread.h"
#include "qemu/rcu_queue.h"
diff --git a/qemu/tests/test-rfifolock.c b/qemu/tests/test-rfifolock.c
index 0572ebb42..9a3cb243b 100644
--- a/qemu/tests/test-rfifolock.c
+++ b/qemu/tests/test-rfifolock.c
@@ -10,6 +10,7 @@
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qemu-common.h"
#include "qemu/rfifolock.h"
diff --git a/qemu/tests/test-string-input-visitor.c b/qemu/tests/test-string-input-visitor.c
index 8e3433e0c..9e6906a56 100644
--- a/qemu/tests/test-string-input-visitor.c
+++ b/qemu/tests/test-string-input-visitor.c
@@ -10,10 +10,11 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdarg.h>
#include "qemu-common.h"
+#include "qapi/error.h"
#include "qapi/string-input-visitor.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
@@ -59,7 +60,7 @@ static void test_visitor_in_int(TestInputVisitorData *data,
v = visitor_input_test_init(data, "-42");
- visit_type_int(v, &res, NULL, &err);
+ visit_type_int(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpint(res, ==, value);
}
@@ -74,7 +75,7 @@ static void test_visitor_in_intList(TestInputVisitorData *data,
v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
- visit_type_int16List(v, &res, NULL, &error_abort);
+ visit_type_int16List(v, NULL, &res, &error_abort);
tmp = res;
while (i < sizeof(value) / sizeof(value[0])) {
g_assert(tmp);
@@ -100,42 +101,42 @@ static void test_visitor_in_bool(TestInputVisitorData *data,
v = visitor_input_test_init(data, "true");
- visit_type_bool(v, &res, NULL, &err);
+ visit_type_bool(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpint(res, ==, true);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "yes");
- visit_type_bool(v, &res, NULL, &err);
+ visit_type_bool(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpint(res, ==, true);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "on");
- visit_type_bool(v, &res, NULL, &err);
+ visit_type_bool(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpint(res, ==, true);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "false");
- visit_type_bool(v, &res, NULL, &err);
+ visit_type_bool(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpint(res, ==, false);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "no");
- visit_type_bool(v, &res, NULL, &err);
+ visit_type_bool(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpint(res, ==, false);
visitor_input_teardown(data, unused);
v = visitor_input_test_init(data, "off");
- visit_type_bool(v, &res, NULL, &err);
+ visit_type_bool(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpint(res, ==, false);
}
@@ -149,7 +150,7 @@ static void test_visitor_in_number(TestInputVisitorData *data,
v = visitor_input_test_init(data, "3.14");
- visit_type_number(v, &res, NULL, &err);
+ visit_type_number(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpfloat(res, ==, value);
}
@@ -163,7 +164,7 @@ static void test_visitor_in_string(TestInputVisitorData *data,
v = visitor_input_test_init(data, value);
- visit_type_str(v, &res, NULL, &err);
+ visit_type_str(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpstr(res, ==, value);
@@ -182,7 +183,7 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
v = visitor_input_test_init(data, EnumOne_lookup[i]);
- visit_type_EnumOne(v, &res, NULL, &err);
+ visit_type_EnumOne(v, NULL, &res, &err);
g_assert(!err);
g_assert_cmpint(i, ==, res);
@@ -220,29 +221,29 @@ static void test_visitor_in_fuzz(TestInputVisitorData *data,
}
v = visitor_input_test_init(data, buf);
- visit_type_int(v, &ires, NULL, NULL);
+ visit_type_int(v, NULL, &ires, NULL);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, buf);
- visit_type_intList(v, &ilres, NULL, NULL);
+ visit_type_intList(v, NULL, &ilres, NULL);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, buf);
- visit_type_bool(v, &bres, NULL, NULL);
+ visit_type_bool(v, NULL, &bres, NULL);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, buf);
- visit_type_number(v, &nres, NULL, NULL);
+ visit_type_number(v, NULL, &nres, NULL);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, buf);
sres = NULL;
- visit_type_str(v, &sres, NULL, NULL);
+ visit_type_str(v, NULL, &sres, NULL);
g_free(sres);
visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, buf);
- visit_type_EnumOne(v, &eres, NULL, NULL);
+ visit_type_EnumOne(v, NULL, &eres, NULL);
visitor_input_teardown(data, NULL);
}
}
diff --git a/qemu/tests/test-string-output-visitor.c b/qemu/tests/test-string-output-visitor.c
index 101fb27dd..1ecd75b85 100644
--- a/qemu/tests/test-string-output-visitor.c
+++ b/qemu/tests/test-string-output-visitor.c
@@ -10,9 +10,11 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qemu-common.h"
+#include "qapi/error.h"
#include "qapi/string-output-visitor.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
@@ -61,7 +63,7 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
Error *err = NULL;
char *str;
- visit_type_int(data->ov, &value, NULL, &err);
+ visit_type_int(data->ov, NULL, &value, &err);
g_assert(!err);
str = string_output_get_string(data->sov);
@@ -81,7 +83,7 @@ static void test_visitor_out_intList(TestOutputVisitorData *data,
3, 4, 5, 6, 11, 12, 13, 21, 22, INT64_MAX - 1, INT64_MAX};
intList *list = NULL, **tmp = &list;
int i;
- Error *errp = NULL;
+ Error *err = NULL;
char *str;
for (i = 0; i < sizeof(value) / sizeof(value[0]); i++) {
@@ -90,8 +92,8 @@ static void test_visitor_out_intList(TestOutputVisitorData *data,
tmp = &(*tmp)->next;
}
- visit_type_intList(data->ov, &list, NULL, &errp);
- g_assert(errp == NULL);
+ visit_type_intList(data->ov, NULL, &list, &err);
+ g_assert(err == NULL);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
@@ -120,7 +122,7 @@ static void test_visitor_out_bool(TestOutputVisitorData *data,
bool value = true;
char *str;
- visit_type_bool(data->ov, &value, NULL, &err);
+ visit_type_bool(data->ov, NULL, &value, &err);
g_assert(!err);
str = string_output_get_string(data->sov);
@@ -136,7 +138,7 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
Error *err = NULL;
char *str;
- visit_type_number(data->ov, &value, NULL, &err);
+ visit_type_number(data->ov, NULL, &value, &err);
g_assert(!err);
str = string_output_get_string(data->sov);
@@ -153,7 +155,7 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
Error *err = NULL;
char *str;
- visit_type_str(data->ov, &string, NULL, &err);
+ visit_type_str(data->ov, NULL, &string, &err);
g_assert(!err);
str = string_output_get_string(data->sov);
@@ -174,7 +176,7 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
char *str;
/* A null string should return "" */
- visit_type_str(data->ov, &string, NULL, &err);
+ visit_type_str(data->ov, NULL, &string, &err);
g_assert(!err);
str = string_output_get_string(data->sov);
@@ -194,10 +196,10 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
char *str;
EnumOne i;
- for (i = 0; i < ENUM_ONE_MAX; i++) {
+ for (i = 0; i < ENUM_ONE__MAX; i++) {
char *str_human;
- visit_type_EnumOne(data->ov, &i, "unused", &err);
+ visit_type_EnumOne(data->ov, "unused", &i, &err);
g_assert(!err);
str_human = g_strdup_printf("\"%s\"", EnumOne_lookup[i]);
@@ -217,12 +219,12 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
const void *unused)
{
- EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+ EnumOne i, bad_values[] = { ENUM_ONE__MAX, -1 };
Error *err;
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
err = NULL;
- visit_type_EnumOne(data->ov, &bad_values[i], "unused", &err);
+ visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err);
g_assert(err);
error_free(err);
}
@@ -248,39 +250,39 @@ int main(int argc, char **argv)
output_visitor_test_add("/string-visitor/output/int",
&out_visitor_data, test_visitor_out_int, false);
- output_visitor_test_add("/string-visitor/output/int",
+ output_visitor_test_add("/string-visitor/output/int-human",
&out_visitor_data, test_visitor_out_int, true);
output_visitor_test_add("/string-visitor/output/bool",
&out_visitor_data, test_visitor_out_bool, false);
- output_visitor_test_add("/string-visitor/output/bool",
+ output_visitor_test_add("/string-visitor/output/bool-human",
&out_visitor_data, test_visitor_out_bool, true);
output_visitor_test_add("/string-visitor/output/number",
&out_visitor_data, test_visitor_out_number, false);
- output_visitor_test_add("/string-visitor/output/number",
+ output_visitor_test_add("/string-visitor/output/number-human",
&out_visitor_data, test_visitor_out_number, true);
output_visitor_test_add("/string-visitor/output/string",
&out_visitor_data, test_visitor_out_string, false);
- output_visitor_test_add("/string-visitor/output/string",
+ output_visitor_test_add("/string-visitor/output/string-human",
&out_visitor_data, test_visitor_out_string, true);
output_visitor_test_add("/string-visitor/output/no-string",
&out_visitor_data, test_visitor_out_no_string,
false);
- output_visitor_test_add("/string-visitor/output/no-string",
+ output_visitor_test_add("/string-visitor/output/no-string-human",
&out_visitor_data, test_visitor_out_no_string,
true);
output_visitor_test_add("/string-visitor/output/enum",
&out_visitor_data, test_visitor_out_enum, false);
- output_visitor_test_add("/string-visitor/output/enum",
+ output_visitor_test_add("/string-visitor/output/enum-human",
&out_visitor_data, test_visitor_out_enum, true);
output_visitor_test_add("/string-visitor/output/enum-errors",
&out_visitor_data, test_visitor_out_enum_errors,
false);
- output_visitor_test_add("/string-visitor/output/enum-errors",
+ output_visitor_test_add("/string-visitor/output/enum-errors-human",
&out_visitor_data, test_visitor_out_enum_errors,
true);
output_visitor_test_add("/string-visitor/output/intList",
&out_visitor_data, test_visitor_out_intList, false);
- output_visitor_test_add("/string-visitor/output/intList",
+ output_visitor_test_add("/string-visitor/output/intList-human",
&out_visitor_data, test_visitor_out_intList, true);
g_test_run();
diff --git a/qemu/tests/test-thread-pool.c b/qemu/tests/test-thread-pool.c
index 6a0b9813f..88dc7316b 100644
--- a/qemu/tests/test-thread-pool.c
+++ b/qemu/tests/test-thread-pool.c
@@ -1,8 +1,10 @@
+#include "qemu/osdep.h"
#include <glib.h>
#include "qemu-common.h"
#include "block/aio.h"
#include "block/thread-pool.h"
#include "block/block.h"
+#include "qapi/error.h"
#include "qemu/timer.h"
#include "qemu/error-report.h"
@@ -229,9 +231,7 @@ int main(int argc, char **argv)
ctx = aio_context_new(&local_error);
if (!ctx) {
- error_report("Failed to create AIO Context: '%s'",
- error_get_pretty(local_error));
- error_free(local_error);
+ error_reportf_err(local_error, "Failed to create AIO Context: ");
exit(1);
}
pool = aio_get_thread_pool(ctx);
diff --git a/qemu/tests/test-throttle.c b/qemu/tests/test-throttle.c
index 016844546..744a52436 100644
--- a/qemu/tests/test-throttle.c
+++ b/qemu/tests/test-throttle.c
@@ -12,9 +12,11 @@
* See the COPYING.LIB file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include <math.h>
#include "block/aio.h"
+#include "qapi/error.h"
#include "qemu/throttle.h"
#include "qemu/error-report.h"
#include "block/throttle-groups.h"
@@ -34,6 +36,9 @@ static bool double_cmp(double x, double y)
/* tests for single bucket operations */
static void test_leak_bucket(void)
{
+ throttle_config_init(&cfg);
+ bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
+
/* set initial value */
bkt.avg = 150;
bkt.max = 15;
@@ -56,13 +61,33 @@ static void test_leak_bucket(void)
g_assert(bkt.avg == 150);
g_assert(bkt.max == 15);
g_assert(double_cmp(bkt.level, 0));
+
+ /* check that burst_level leaks correctly */
+ bkt.burst_level = 6;
+ bkt.max = 250;
+ bkt.burst_length = 2; /* otherwise burst_level will not leak */
+ throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
+ g_assert(double_cmp(bkt.burst_level, 3.5));
+
+ throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
+ g_assert(double_cmp(bkt.burst_level, 1));
+
+ throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
+ g_assert(double_cmp(bkt.burst_level, 0));
+
+ throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 100);
+ g_assert(double_cmp(bkt.burst_level, 0));
}
static void test_compute_wait(void)
{
+ unsigned i;
int64_t wait;
int64_t result;
+ throttle_config_init(&cfg);
+ bkt = cfg.buckets[THROTTLE_BPS_TOTAL];
+
/* no operation limit set */
bkt.avg = 0;
bkt.max = 15;
@@ -92,6 +117,27 @@ static void test_compute_wait(void)
/* time required to do half an operation */
result = (int64_t) NANOSECONDS_PER_SECOND / 150 / 2;
g_assert(wait == result);
+
+ /* Perform I/O for 2.2 seconds at a rate of bkt.max */
+ bkt.burst_length = 2;
+ bkt.level = 0;
+ bkt.avg = 10;
+ bkt.max = 200;
+ for (i = 0; i < 22; i++) {
+ double units = bkt.max / 10;
+ bkt.level += units;
+ bkt.burst_level += units;
+ throttle_leak_bucket(&bkt, NANOSECONDS_PER_SECOND / 10);
+ wait = throttle_compute_wait(&bkt);
+ g_assert(double_cmp(bkt.burst_level, 0));
+ g_assert(double_cmp(bkt.level, (i + 1) * (bkt.max - bkt.avg) / 10));
+ /* We can do bursts for the 2 seconds we have configured in
+ * burst_length. We have 100 extra miliseconds of burst
+ * because bkt.level has been leaking during this time.
+ * After that, we have to wait. */
+ result = i < 21 ? 0 : 1.8 * NANOSECONDS_PER_SECOND;
+ g_assert(wait == result);
+ }
}
/* functions to test ThrottleState initialization/destroy methods */
@@ -221,6 +267,8 @@ static void set_cfg_value(bool is_max, int index, int value)
{
if (is_max) {
cfg.buckets[index].max = value;
+ /* If max is set, avg should never be 0 */
+ cfg.buckets[index].avg = MAX(cfg.buckets[index].avg, 1);
} else {
cfg.buckets[index].avg = value;
}
@@ -230,17 +278,17 @@ static void test_enabled(void)
{
int i;
- memset(&cfg, 0, sizeof(cfg));
+ throttle_config_init(&cfg);
g_assert(!throttle_enabled(&cfg));
for (i = 0; i < BUCKETS_COUNT; i++) {
- memset(&cfg, 0, sizeof(cfg));
+ throttle_config_init(&cfg);
set_cfg_value(false, i, 150);
g_assert(throttle_enabled(&cfg));
}
for (i = 0; i < BUCKETS_COUNT; i++) {
- memset(&cfg, 0, sizeof(cfg));
+ throttle_config_init(&cfg);
set_cfg_value(false, i, -150);
g_assert(!throttle_enabled(&cfg));
}
@@ -253,32 +301,32 @@ static void test_conflicts_for_one_set(bool is_max,
int read,
int write)
{
- memset(&cfg, 0, sizeof(cfg));
- g_assert(!throttle_conflicting(&cfg));
+ throttle_config_init(&cfg);
+ g_assert(throttle_is_valid(&cfg, NULL));
set_cfg_value(is_max, total, 1);
set_cfg_value(is_max, read, 1);
- g_assert(throttle_conflicting(&cfg));
+ g_assert(!throttle_is_valid(&cfg, NULL));
- memset(&cfg, 0, sizeof(cfg));
+ throttle_config_init(&cfg);
set_cfg_value(is_max, total, 1);
set_cfg_value(is_max, write, 1);
- g_assert(throttle_conflicting(&cfg));
+ g_assert(!throttle_is_valid(&cfg, NULL));
- memset(&cfg, 0, sizeof(cfg));
+ throttle_config_init(&cfg);
set_cfg_value(is_max, total, 1);
set_cfg_value(is_max, read, 1);
set_cfg_value(is_max, write, 1);
- g_assert(throttle_conflicting(&cfg));
+ g_assert(!throttle_is_valid(&cfg, NULL));
- memset(&cfg, 0, sizeof(cfg));
+ throttle_config_init(&cfg);
set_cfg_value(is_max, total, 1);
- g_assert(!throttle_conflicting(&cfg));
+ g_assert(throttle_is_valid(&cfg, NULL));
- memset(&cfg, 0, sizeof(cfg));
+ throttle_config_init(&cfg);
set_cfg_value(is_max, read, 1);
set_cfg_value(is_max, write, 1);
- g_assert(!throttle_conflicting(&cfg));
+ g_assert(throttle_is_valid(&cfg, NULL));
}
static void test_conflicting_config(void)
@@ -312,9 +360,9 @@ static void test_is_valid_for_value(int value, bool should_be_valid)
int is_max, index;
for (is_max = 0; is_max < 2; is_max++) {
for (index = 0; index < BUCKETS_COUNT; index++) {
- memset(&cfg, 0, sizeof(cfg));
+ throttle_config_init(&cfg);
set_cfg_value(is_max, index, value);
- g_assert(throttle_is_valid(&cfg) == should_be_valid);
+ g_assert(throttle_is_valid(&cfg, NULL) == should_be_valid);
}
}
}
@@ -329,6 +377,26 @@ static void test_is_valid(void)
test_is_valid_for_value(1, true);
}
+static void test_max_is_missing_limit(void)
+{
+ int i;
+
+ for (i = 0; i < BUCKETS_COUNT; i++) {
+ throttle_config_init(&cfg);
+ cfg.buckets[i].max = 100;
+ cfg.buckets[i].avg = 0;
+ g_assert(!throttle_is_valid(&cfg, NULL));
+
+ cfg.buckets[i].max = 0;
+ cfg.buckets[i].avg = 0;
+ g_assert(throttle_is_valid(&cfg, NULL));
+
+ cfg.buckets[i].max = 0;
+ cfg.buckets[i].avg = 100;
+ g_assert(throttle_is_valid(&cfg, NULL));
+ }
+}
+
static void test_have_timer(void)
{
/* zero structures */
@@ -529,7 +597,7 @@ static void test_groups(void)
g_assert(bdrv1->throttle_state == bdrv3->throttle_state);
/* Setting the config of a group member affects the whole group */
- memset(&cfg1, 0, sizeof(cfg1));
+ throttle_config_init(&cfg1);
cfg1.buckets[THROTTLE_BPS_READ].avg = 500000;
cfg1.buckets[THROTTLE_BPS_WRITE].avg = 285000;
cfg1.buckets[THROTTLE_OPS_READ].avg = 20000;
@@ -561,21 +629,8 @@ static void test_groups(void)
int main(int argc, char **argv)
{
- Error *local_error = NULL;
-
- qemu_init_main_loop(&local_error);
+ qemu_init_main_loop(&error_fatal);
ctx = qemu_get_aio_context();
-
- if (!ctx) {
- error_report("Failed to create AIO Context: '%s'",
- local_error ? error_get_pretty(local_error) :
- "Failed to initialize the QEMU main loop");
- if (local_error) {
- error_free(local_error);
- }
- exit(1);
- }
-
bdrv_init();
do {} while (g_main_context_iteration(NULL, false));
@@ -591,6 +646,7 @@ int main(int argc, char **argv)
g_test_add_func("/throttle/config/enabled", test_enabled);
g_test_add_func("/throttle/config/conflicting", test_conflicting_config);
g_test_add_func("/throttle/config/is_valid", test_is_valid);
+ g_test_add_func("/throttle/config/max", test_max_is_missing_limit);
g_test_add_func("/throttle/config_functions", test_config_functions);
g_test_add_func("/throttle/accounting", test_accounting);
g_test_add_func("/throttle/groups", test_groups);
diff --git a/qemu/tests/test-timed-average.c b/qemu/tests/test-timed-average.c
new file mode 100644
index 000000000..1cc4ab302
--- /dev/null
+++ b/qemu/tests/test-timed-average.c
@@ -0,0 +1,90 @@
+/*
+ * Timed average computation tests
+ *
+ * Copyright Nodalink, EURL. 2014
+ *
+ * Authors:
+ * Benoît Canet <benoit.canet@nodalink.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include <glib.h>
+
+#include "qemu/timed-average.h"
+
+/* This is the clock for QEMU_CLOCK_VIRTUAL */
+static int64_t my_clock_value;
+
+int64_t cpu_get_clock(void)
+{
+ return my_clock_value;
+}
+
+static void account(TimedAverage *ta)
+{
+ timed_average_account(ta, 1);
+ timed_average_account(ta, 5);
+ timed_average_account(ta, 2);
+ timed_average_account(ta, 4);
+ timed_average_account(ta, 3);
+}
+
+static void test_average(void)
+{
+ TimedAverage ta;
+ uint64_t result;
+ int i;
+
+ /* we will compute some average on a period of 1 second */
+ timed_average_init(&ta, QEMU_CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND);
+
+ result = timed_average_min(&ta);
+ g_assert(result == 0);
+ result = timed_average_avg(&ta);
+ g_assert(result == 0);
+ result = timed_average_max(&ta);
+ g_assert(result == 0);
+
+ for (i = 0; i < 100; i++) {
+ account(&ta);
+ result = timed_average_min(&ta);
+ g_assert(result == 1);
+ result = timed_average_avg(&ta);
+ g_assert(result == 3);
+ result = timed_average_max(&ta);
+ g_assert(result == 5);
+ my_clock_value += NANOSECONDS_PER_SECOND / 10;
+ }
+
+ my_clock_value += NANOSECONDS_PER_SECOND * 100;
+
+ result = timed_average_min(&ta);
+ g_assert(result == 0);
+ result = timed_average_avg(&ta);
+ g_assert(result == 0);
+ result = timed_average_max(&ta);
+ g_assert(result == 0);
+
+ for (i = 0; i < 100; i++) {
+ account(&ta);
+ result = timed_average_min(&ta);
+ g_assert(result == 1);
+ result = timed_average_avg(&ta);
+ g_assert(result == 3);
+ result = timed_average_max(&ta);
+ g_assert(result == 5);
+ my_clock_value += NANOSECONDS_PER_SECOND / 10;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ /* tests in the same order as the header function declarations */
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/timed-average/average", test_average);
+ return g_test_run();
+}
+
diff --git a/qemu/tests/test-visitor-serialization.c b/qemu/tests/test-visitor-serialization.c
index fa86cae88..9adbc30a4 100644
--- a/qemu/tests/test-visitor-serialization.c
+++ b/qemu/tests/test-visitor-serialization.c
@@ -11,14 +11,14 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdlib.h>
-#include <stdint.h>
#include <float.h>
#include "qemu-common.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
+#include "qapi/error.h"
#include "qapi/qmp/types.h"
#include "qapi/qmp-input-visitor.h"
#include "qapi/qmp-output-visitor.h"
@@ -101,40 +101,40 @@ static void visit_primitive_type(Visitor *v, void **native, Error **errp)
PrimitiveType *pt = *native;
switch(pt->type) {
case PTYPE_STRING:
- visit_type_str(v, (char **)&pt->value.string, NULL, errp);
+ visit_type_str(v, NULL, (char **)&pt->value.string, errp);
break;
case PTYPE_BOOLEAN:
- visit_type_bool(v, &pt->value.boolean, NULL, errp);
+ visit_type_bool(v, NULL, &pt->value.boolean, errp);
break;
case PTYPE_NUMBER:
- visit_type_number(v, &pt->value.number, NULL, errp);
+ visit_type_number(v, NULL, &pt->value.number, errp);
break;
case PTYPE_INTEGER:
- visit_type_int(v, &pt->value.integer, NULL, errp);
+ visit_type_int(v, NULL, &pt->value.integer, errp);
break;
case PTYPE_U8:
- visit_type_uint8(v, &pt->value.u8, NULL, errp);
+ visit_type_uint8(v, NULL, &pt->value.u8, errp);
break;
case PTYPE_U16:
- visit_type_uint16(v, &pt->value.u16, NULL, errp);
+ visit_type_uint16(v, NULL, &pt->value.u16, errp);
break;
case PTYPE_U32:
- visit_type_uint32(v, &pt->value.u32, NULL, errp);
+ visit_type_uint32(v, NULL, &pt->value.u32, errp);
break;
case PTYPE_U64:
- visit_type_uint64(v, &pt->value.u64, NULL, errp);
+ visit_type_uint64(v, NULL, &pt->value.u64, errp);
break;
case PTYPE_S8:
- visit_type_int8(v, &pt->value.s8, NULL, errp);
+ visit_type_int8(v, NULL, &pt->value.s8, errp);
break;
case PTYPE_S16:
- visit_type_int16(v, &pt->value.s16, NULL, errp);
+ visit_type_int16(v, NULL, &pt->value.s16, errp);
break;
case PTYPE_S32:
- visit_type_int32(v, &pt->value.s32, NULL, errp);
+ visit_type_int32(v, NULL, &pt->value.s32, errp);
break;
case PTYPE_S64:
- visit_type_int64(v, &pt->value.s64, NULL, errp);
+ visit_type_int64(v, NULL, &pt->value.s64, errp);
break;
case PTYPE_EOL:
g_assert_not_reached();
@@ -146,80 +146,46 @@ static void visit_primitive_list(Visitor *v, void **native, Error **errp)
PrimitiveList *pl = *native;
switch (pl->type) {
case PTYPE_STRING:
- visit_type_strList(v, &pl->value.strings, NULL, errp);
+ visit_type_strList(v, NULL, &pl->value.strings, errp);
break;
case PTYPE_BOOLEAN:
- visit_type_boolList(v, &pl->value.booleans, NULL, errp);
+ visit_type_boolList(v, NULL, &pl->value.booleans, errp);
break;
case PTYPE_NUMBER:
- visit_type_numberList(v, &pl->value.numbers, NULL, errp);
+ visit_type_numberList(v, NULL, &pl->value.numbers, errp);
break;
case PTYPE_INTEGER:
- visit_type_intList(v, &pl->value.integers, NULL, errp);
+ visit_type_intList(v, NULL, &pl->value.integers, errp);
break;
case PTYPE_S8:
- visit_type_int8List(v, &pl->value.s8_integers, NULL, errp);
+ visit_type_int8List(v, NULL, &pl->value.s8_integers, errp);
break;
case PTYPE_S16:
- visit_type_int16List(v, &pl->value.s16_integers, NULL, errp);
+ visit_type_int16List(v, NULL, &pl->value.s16_integers, errp);
break;
case PTYPE_S32:
- visit_type_int32List(v, &pl->value.s32_integers, NULL, errp);
+ visit_type_int32List(v, NULL, &pl->value.s32_integers, errp);
break;
case PTYPE_S64:
- visit_type_int64List(v, &pl->value.s64_integers, NULL, errp);
+ visit_type_int64List(v, NULL, &pl->value.s64_integers, errp);
break;
case PTYPE_U8:
- visit_type_uint8List(v, &pl->value.u8_integers, NULL, errp);
+ visit_type_uint8List(v, NULL, &pl->value.u8_integers, errp);
break;
case PTYPE_U16:
- visit_type_uint16List(v, &pl->value.u16_integers, NULL, errp);
+ visit_type_uint16List(v, NULL, &pl->value.u16_integers, errp);
break;
case PTYPE_U32:
- visit_type_uint32List(v, &pl->value.u32_integers, NULL, errp);
+ visit_type_uint32List(v, NULL, &pl->value.u32_integers, errp);
break;
case PTYPE_U64:
- visit_type_uint64List(v, &pl->value.u64_integers, NULL, errp);
+ visit_type_uint64List(v, NULL, &pl->value.u64_integers, errp);
break;
default:
g_assert_not_reached();
}
}
-typedef struct TestStruct
-{
- int64_t integer;
- bool boolean;
- char *string;
-} TestStruct;
-
-static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
- const char *name, Error **errp)
-{
- Error *err = NULL;
-
- visit_start_struct(v, (void **)obj, NULL, name, sizeof(TestStruct), &err);
- if (err) {
- goto out;
- }
-
- visit_type_int(v, &(*obj)->integer, "integer", &err);
- if (err) {
- goto out_end;
- }
- visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
- if (err) {
- goto out_end;
- }
- visit_type_str(v, &(*obj)->string, "string", &err);
-
-out_end:
- error_propagate(errp, err);
- err = NULL;
- visit_end_struct(v, &err);
-out:
- error_propagate(errp, err);
-}
static TestStruct *struct_create(void)
{
@@ -247,7 +213,7 @@ static void struct_cleanup(TestStruct *ts)
static void visit_struct(Visitor *v, void **native, Error **errp)
{
- visit_type_TestStruct(v, (TestStruct **)native, NULL, errp);
+ visit_type_TestStruct(v, NULL, (TestStruct **)native, errp);
}
static UserDefTwo *nested_struct_create(void)
@@ -258,15 +224,13 @@ static UserDefTwo *nested_struct_create(void)
udnp->dict1->string1 = strdup("test_string1");
udnp->dict1->dict2 = g_malloc0(sizeof(*udnp->dict1->dict2));
udnp->dict1->dict2->userdef = g_new0(UserDefOne, 1);
- udnp->dict1->dict2->userdef->base = g_new0(UserDefZero, 1);
- udnp->dict1->dict2->userdef->base->integer = 42;
+ udnp->dict1->dict2->userdef->integer = 42;
udnp->dict1->dict2->userdef->string = strdup("test_string");
udnp->dict1->dict2->string = strdup("test_string2");
udnp->dict1->dict3 = g_malloc0(sizeof(*udnp->dict1->dict3));
udnp->dict1->has_dict3 = true;
udnp->dict1->dict3->userdef = g_new0(UserDefOne, 1);
- udnp->dict1->dict3->userdef->base = g_new0(UserDefZero, 1);
- udnp->dict1->dict3->userdef->base->integer = 43;
+ udnp->dict1->dict3->userdef->integer = 43;
udnp->dict1->dict3->userdef->string = strdup("test_string");
udnp->dict1->dict3->string = strdup("test_string3");
return udnp;
@@ -278,15 +242,15 @@ static void nested_struct_compare(UserDefTwo *udnp1, UserDefTwo *udnp2)
g_assert(udnp2);
g_assert_cmpstr(udnp1->string0, ==, udnp2->string0);
g_assert_cmpstr(udnp1->dict1->string1, ==, udnp2->dict1->string1);
- g_assert_cmpint(udnp1->dict1->dict2->userdef->base->integer, ==,
- udnp2->dict1->dict2->userdef->base->integer);
+ g_assert_cmpint(udnp1->dict1->dict2->userdef->integer, ==,
+ udnp2->dict1->dict2->userdef->integer);
g_assert_cmpstr(udnp1->dict1->dict2->userdef->string, ==,
udnp2->dict1->dict2->userdef->string);
g_assert_cmpstr(udnp1->dict1->dict2->string, ==,
udnp2->dict1->dict2->string);
g_assert(udnp1->dict1->has_dict3 == udnp2->dict1->has_dict3);
- g_assert_cmpint(udnp1->dict1->dict3->userdef->base->integer, ==,
- udnp2->dict1->dict3->userdef->base->integer);
+ g_assert_cmpint(udnp1->dict1->dict3->userdef->integer, ==,
+ udnp2->dict1->dict3->userdef->integer);
g_assert_cmpstr(udnp1->dict1->dict3->userdef->string, ==,
udnp2->dict1->dict3->userdef->string);
g_assert_cmpstr(udnp1->dict1->dict3->string, ==,
@@ -300,12 +264,12 @@ static void nested_struct_cleanup(UserDefTwo *udnp)
static void visit_nested_struct(Visitor *v, void **native, Error **errp)
{
- visit_type_UserDefTwo(v, (UserDefTwo **)native, NULL, errp);
+ visit_type_UserDefTwo(v, NULL, (UserDefTwo **)native, errp);
}
static void visit_nested_struct_list(Visitor *v, void **native, Error **errp)
{
- visit_type_UserDefTwoList(v, (UserDefTwoList **)native, NULL, errp);
+ visit_type_UserDefTwoList(v, NULL, (UserDefTwoList **)native, errp);
}
/* test cases */
@@ -338,14 +302,13 @@ static void test_primitives(gconstpointer opaque)
const SerializeOps *ops = args->ops;
PrimitiveType *pt = args->test_data;
PrimitiveType *pt_copy = g_malloc0(sizeof(*pt_copy));
- Error *err = NULL;
void *serialize_data;
pt_copy->type = pt->type;
- ops->serialize(pt, &serialize_data, visit_primitive_type, &err);
- ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type, &err);
+ ops->serialize(pt, &serialize_data, visit_primitive_type, &error_abort);
+ ops->deserialize((void **)&pt_copy, serialize_data, visit_primitive_type,
+ &error_abort);
- g_assert(err == NULL);
g_assert(pt_copy != NULL);
if (pt->type == PTYPE_STRING) {
g_assert_cmpstr(pt->value.string, ==, pt_copy->value.string);
@@ -381,7 +344,6 @@ static void test_primitive_lists(gconstpointer opaque)
PrimitiveList pl = { .value = { NULL } };
PrimitiveList pl_copy = { .value = { NULL } };
PrimitiveList *pl_copy_ptr = &pl_copy;
- Error *err = NULL;
void *serialize_data;
void *cur_head = NULL;
int i;
@@ -528,10 +490,11 @@ static void test_primitive_lists(gconstpointer opaque)
}
}
- ops->serialize((void **)&pl, &serialize_data, visit_primitive_list, &err);
- ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &err);
+ ops->serialize((void **)&pl, &serialize_data, visit_primitive_list,
+ &error_abort);
+ ops->deserialize((void **)&pl_copy_ptr, serialize_data,
+ visit_primitive_list, &error_abort);
- g_assert(err == NULL);
i = 0;
/* compare our deserialized list of primitives to the original */
@@ -688,10 +651,8 @@ static void test_primitive_lists(gconstpointer opaque)
g_assert_cmpint(i, ==, 33);
ops->cleanup(serialize_data);
- dealloc_helper(&pl, visit_primitive_list, &err);
- g_assert(!err);
- dealloc_helper(&pl_copy, visit_primitive_list, &err);
- g_assert(!err);
+ dealloc_helper(&pl, visit_primitive_list, &error_abort);
+ dealloc_helper(&pl_copy, visit_primitive_list, &error_abort);
g_free(args);
}
@@ -701,13 +662,12 @@ static void test_struct(gconstpointer opaque)
const SerializeOps *ops = args->ops;
TestStruct *ts = struct_create();
TestStruct *ts_copy = NULL;
- Error *err = NULL;
void *serialize_data;
- ops->serialize(ts, &serialize_data, visit_struct, &err);
- ops->deserialize((void **)&ts_copy, serialize_data, visit_struct, &err);
+ ops->serialize(ts, &serialize_data, visit_struct, &error_abort);
+ ops->deserialize((void **)&ts_copy, serialize_data, visit_struct,
+ &error_abort);
- g_assert(err == NULL);
struct_compare(ts, ts_copy);
struct_cleanup(ts);
@@ -723,14 +683,12 @@ static void test_nested_struct(gconstpointer opaque)
const SerializeOps *ops = args->ops;
UserDefTwo *udnp = nested_struct_create();
UserDefTwo *udnp_copy = NULL;
- Error *err = NULL;
void *serialize_data;
- ops->serialize(udnp, &serialize_data, visit_nested_struct, &err);
+ ops->serialize(udnp, &serialize_data, visit_nested_struct, &error_abort);
ops->deserialize((void **)&udnp_copy, serialize_data, visit_nested_struct,
- &err);
+ &error_abort);
- g_assert(err == NULL);
nested_struct_compare(udnp, udnp_copy);
nested_struct_cleanup(udnp);
@@ -745,7 +703,6 @@ static void test_nested_struct_list(gconstpointer opaque)
TestArgs *args = (TestArgs *) opaque;
const SerializeOps *ops = args->ops;
UserDefTwoList *listp = NULL, *tmp, *tmp_copy, *listp_copy = NULL;
- Error *err = NULL;
void *serialize_data;
int i = 0;
@@ -756,11 +713,10 @@ static void test_nested_struct_list(gconstpointer opaque)
listp = tmp;
}
- ops->serialize(listp, &serialize_data, visit_nested_struct_list, &err);
+ ops->serialize(listp, &serialize_data, visit_nested_struct_list,
+ &error_abort);
ops->deserialize((void **)&listp_copy, serialize_data,
- visit_nested_struct_list, &err);
-
- g_assert(err == NULL);
+ visit_nested_struct_list, &error_abort);
tmp = listp;
tmp_copy = listp_copy;
diff --git a/qemu/tests/test-vmstate.c b/qemu/tests/test-vmstate.c
index 1d620e04f..713d4443b 100644
--- a/qemu/tests/test-vmstate.c
+++ b/qemu/tests/test-vmstate.c
@@ -22,12 +22,13 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "qemu-common.h"
#include "migration/migration.h"
#include "migration/vmstate.h"
-#include "block/coroutine.h"
+#include "qemu/coroutine.h"
static char temp_file[] = "/tmp/vmst.test.XXXXXX";
static int temp_fd;
diff --git a/qemu/tests/test-write-threshold.c b/qemu/tests/test-write-threshold.c
index faffa7b85..fdbc8020f 100644
--- a/qemu/tests/test-write-threshold.c
+++ b/qemu/tests/test-write-threshold.c
@@ -6,8 +6,8 @@
*
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <stdint.h>
#include "block/block_int.h"
#include "block/write-threshold.h"
diff --git a/qemu/tests/test-x86-cpuid.c b/qemu/tests/test-x86-cpuid.c
index 6cd20d4a2..8eb0bc6ad 100644
--- a/qemu/tests/test-x86-cpuid.c
+++ b/qemu/tests/test-x86-cpuid.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "hw/i386/topology.h"
diff --git a/qemu/tests/test-xbzrle.c b/qemu/tests/test-xbzrle.c
index db93b0a3d..49f64195a 100644
--- a/qemu/tests/test-xbzrle.c
+++ b/qemu/tests/test-xbzrle.c
@@ -10,14 +10,9 @@
* See the COPYING file in the top-level directory.
*
*/
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <string.h>
-#include <sys/time.h>
-#include <assert.h>
+#include "qemu/osdep.h"
#include "qemu-common.h"
+#include "qemu/cutils.h"
#include "include/migration/migration.h"
#define PAGE_SIZE 4096
diff --git a/qemu/tests/tmp105-test.c b/qemu/tests/tmp105-test.c
index 99db53819..235cae013 100644
--- a/qemu/tests/tmp105-test.c
+++ b/qemu/tests/tmp105-test.c
@@ -7,6 +7,7 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqtest.h"
diff --git a/qemu/tests/tpci200-test.c b/qemu/tests/tpci200-test.c
index 9ae01277e..cb2b00ca8 100644
--- a/qemu/tests/tpci200-test.c
+++ b/qemu/tests/tpci200-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void nop(void)
diff --git a/qemu/tests/usb-hcd-ehci-test.c b/qemu/tests/usb-hcd-ehci-test.c
index 75073bf24..a0f13ef40 100644
--- a/qemu/tests/usb-hcd-ehci-test.c
+++ b/qemu/tests/usb-hcd-ehci-test.c
@@ -7,12 +7,10 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
-#include <stdio.h>
#include "libqtest.h"
#include "libqos/pci-pc.h"
-#include "qemu/osdep.h"
#include "hw/usb/uhci-regs.h"
#include "hw/usb/ehci-regs.h"
#include "libqos/usb.h"
diff --git a/qemu/tests/usb-hcd-ohci-test.c b/qemu/tests/usb-hcd-ohci-test.c
index fa592d487..efd6669c7 100644
--- a/qemu/tests/usb-hcd-ohci-test.c
+++ b/qemu/tests/usb-hcd-ohci-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
#include "libqos/usb.h"
diff --git a/qemu/tests/usb-hcd-uhci-test.c b/qemu/tests/usb-hcd-uhci-test.c
index a96b71683..71ff2ea18 100644
--- a/qemu/tests/usb-hcd-uhci-test.c
+++ b/qemu/tests/usb-hcd-uhci-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
#include "libqos/usb.h"
#include "hw/usb/uhci-regs.h"
diff --git a/qemu/tests/usb-hcd-xhci-test.c b/qemu/tests/usb-hcd-xhci-test.c
index 56ab36731..7e2e212df 100644
--- a/qemu/tests/usb-hcd-xhci-test.c
+++ b/qemu/tests/usb-hcd-xhci-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
#include "libqos/usb.h"
diff --git a/qemu/tests/vhost-user-bridge.c b/qemu/tests/vhost-user-bridge.c
new file mode 100644
index 000000000..0779ba260
--- /dev/null
+++ b/qemu/tests/vhost-user-bridge.c
@@ -0,0 +1,1418 @@
+/*
+ * Vhost User Bridge
+ *
+ * Copyright (c) 2015 Red Hat, Inc.
+ *
+ * Authors:
+ * Victor Kaplansky <victork@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+
+/*
+ * TODO:
+ * - main should get parameters from the command line.
+ * - implement all request handlers. Still not implemented:
+ * vubr_get_queue_num_exec()
+ * vubr_send_rarp_exec()
+ * - test for broken requests and virtqueue.
+ * - implement features defined by Virtio 1.0 spec.
+ * - support mergeable buffers and indirect descriptors.
+ * - implement clean shutdown.
+ * - implement non-blocking writes to UDP backend.
+ * - implement polling strategy.
+ * - implement clean starting/stopping of vq processing
+ * - implement clean starting/stopping of used and buffers
+ * dirty page logging.
+ */
+
+#define _FILE_OFFSET_BITS 64
+
+#include "qemu/osdep.h"
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/unistd.h>
+#include <sys/mman.h>
+#include <sys/eventfd.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <qemu/osdep.h>
+
+#include <linux/vhost.h>
+
+#include "qemu/atomic.h"
+#include "standard-headers/linux/virtio_net.h"
+#include "standard-headers/linux/virtio_ring.h"
+
+#define VHOST_USER_BRIDGE_DEBUG 1
+
+#define DPRINT(...) \
+ do { \
+ if (VHOST_USER_BRIDGE_DEBUG) { \
+ printf(__VA_ARGS__); \
+ } \
+ } while (0)
+
+typedef void (*CallbackFunc)(int sock, void *ctx);
+
+typedef struct Event {
+ void *ctx;
+ CallbackFunc callback;
+} Event;
+
+typedef struct Dispatcher {
+ int max_sock;
+ fd_set fdset;
+ Event events[FD_SETSIZE];
+} Dispatcher;
+
+static void
+vubr_die(const char *s)
+{
+ perror(s);
+ exit(1);
+}
+
+static int
+dispatcher_init(Dispatcher *dispr)
+{
+ FD_ZERO(&dispr->fdset);
+ dispr->max_sock = -1;
+ return 0;
+}
+
+static int
+dispatcher_add(Dispatcher *dispr, int sock, void *ctx, CallbackFunc cb)
+{
+ if (sock >= FD_SETSIZE) {
+ fprintf(stderr,
+ "Error: Failed to add new event. sock %d should be less than %d\n",
+ sock, FD_SETSIZE);
+ return -1;
+ }
+
+ dispr->events[sock].ctx = ctx;
+ dispr->events[sock].callback = cb;
+
+ FD_SET(sock, &dispr->fdset);
+ if (sock > dispr->max_sock) {
+ dispr->max_sock = sock;
+ }
+ DPRINT("Added sock %d for watching. max_sock: %d\n",
+ sock, dispr->max_sock);
+ return 0;
+}
+
+/* dispatcher_remove() is not currently in use but may be useful
+ * in the future. */
+static int
+dispatcher_remove(Dispatcher *dispr, int sock)
+{
+ if (sock >= FD_SETSIZE) {
+ fprintf(stderr,
+ "Error: Failed to remove event. sock %d should be less than %d\n",
+ sock, FD_SETSIZE);
+ return -1;
+ }
+
+ FD_CLR(sock, &dispr->fdset);
+ DPRINT("Sock %d removed from dispatcher watch.\n", sock);
+ return 0;
+}
+
+/* timeout in us */
+static int
+dispatcher_wait(Dispatcher *dispr, uint32_t timeout)
+{
+ struct timeval tv;
+ tv.tv_sec = timeout / 1000000;
+ tv.tv_usec = timeout % 1000000;
+
+ fd_set fdset = dispr->fdset;
+
+ /* wait until some of sockets become readable. */
+ int rc = select(dispr->max_sock + 1, &fdset, 0, 0, &tv);
+
+ if (rc == -1) {
+ vubr_die("select");
+ }
+
+ /* Timeout */
+ if (rc == 0) {
+ return 0;
+ }
+
+ /* Now call callback for every ready socket. */
+
+ int sock;
+ for (sock = 0; sock < dispr->max_sock + 1; sock++) {
+ /* The callback on a socket can remove other sockets from the
+ * dispatcher, thus we have to check that the socket is
+ * still not removed from dispatcher's list
+ */
+ if (FD_ISSET(sock, &fdset) && FD_ISSET(sock, &dispr->fdset)) {
+ Event *e = &dispr->events[sock];
+ e->callback(sock, e->ctx);
+ }
+ }
+
+ return 0;
+}
+
+typedef struct VubrVirtq {
+ int call_fd;
+ int kick_fd;
+ uint32_t size;
+ uint16_t last_avail_index;
+ uint16_t last_used_index;
+ struct vring_desc *desc;
+ struct vring_avail *avail;
+ struct vring_used *used;
+ uint64_t log_guest_addr;
+ int enable;
+} VubrVirtq;
+
+/* Based on qemu/hw/virtio/vhost-user.c */
+
+#define VHOST_MEMORY_MAX_NREGIONS 8
+#define VHOST_USER_F_PROTOCOL_FEATURES 30
+/* v1.0 compliant. */
+#define VIRTIO_F_VERSION_1 32
+
+#define VHOST_LOG_PAGE 4096
+
+enum VhostUserProtocolFeature {
+ VHOST_USER_PROTOCOL_F_MQ = 0,
+ VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
+ VHOST_USER_PROTOCOL_F_RARP = 2,
+
+ VHOST_USER_PROTOCOL_F_MAX
+};
+
+#define VHOST_USER_PROTOCOL_FEATURE_MASK ((1 << VHOST_USER_PROTOCOL_F_MAX) - 1)
+
+typedef enum VhostUserRequest {
+ VHOST_USER_NONE = 0,
+ VHOST_USER_GET_FEATURES = 1,
+ VHOST_USER_SET_FEATURES = 2,
+ VHOST_USER_SET_OWNER = 3,
+ VHOST_USER_RESET_OWNER = 4,
+ VHOST_USER_SET_MEM_TABLE = 5,
+ VHOST_USER_SET_LOG_BASE = 6,
+ VHOST_USER_SET_LOG_FD = 7,
+ VHOST_USER_SET_VRING_NUM = 8,
+ VHOST_USER_SET_VRING_ADDR = 9,
+ VHOST_USER_SET_VRING_BASE = 10,
+ VHOST_USER_GET_VRING_BASE = 11,
+ VHOST_USER_SET_VRING_KICK = 12,
+ VHOST_USER_SET_VRING_CALL = 13,
+ VHOST_USER_SET_VRING_ERR = 14,
+ VHOST_USER_GET_PROTOCOL_FEATURES = 15,
+ VHOST_USER_SET_PROTOCOL_FEATURES = 16,
+ VHOST_USER_GET_QUEUE_NUM = 17,
+ VHOST_USER_SET_VRING_ENABLE = 18,
+ VHOST_USER_SEND_RARP = 19,
+ VHOST_USER_MAX
+} VhostUserRequest;
+
+typedef struct VhostUserMemoryRegion {
+ uint64_t guest_phys_addr;
+ uint64_t memory_size;
+ uint64_t userspace_addr;
+ uint64_t mmap_offset;
+} VhostUserMemoryRegion;
+
+typedef struct VhostUserMemory {
+ uint32_t nregions;
+ uint32_t padding;
+ VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];
+} VhostUserMemory;
+
+typedef struct VhostUserLog {
+ uint64_t mmap_size;
+ uint64_t mmap_offset;
+} VhostUserLog;
+
+typedef struct VhostUserMsg {
+ VhostUserRequest request;
+
+#define VHOST_USER_VERSION_MASK (0x3)
+#define VHOST_USER_REPLY_MASK (0x1<<2)
+ uint32_t flags;
+ uint32_t size; /* the following payload size */
+ union {
+#define VHOST_USER_VRING_IDX_MASK (0xff)
+#define VHOST_USER_VRING_NOFD_MASK (0x1<<8)
+ uint64_t u64;
+ struct vhost_vring_state state;
+ struct vhost_vring_addr addr;
+ VhostUserMemory memory;
+ VhostUserLog log;
+ } payload;
+ int fds[VHOST_MEMORY_MAX_NREGIONS];
+ int fd_num;
+} QEMU_PACKED VhostUserMsg;
+
+#define VHOST_USER_HDR_SIZE offsetof(VhostUserMsg, payload.u64)
+
+/* The version of the protocol we support */
+#define VHOST_USER_VERSION (0x1)
+
+#define MAX_NR_VIRTQUEUE (8)
+
+typedef struct VubrDevRegion {
+ /* Guest Physical address. */
+ uint64_t gpa;
+ /* Memory region size. */
+ uint64_t size;
+ /* QEMU virtual address (userspace). */
+ uint64_t qva;
+ /* Starting offset in our mmaped space. */
+ uint64_t mmap_offset;
+ /* Start address of mmaped space. */
+ uint64_t mmap_addr;
+} VubrDevRegion;
+
+typedef struct VubrDev {
+ int sock;
+ Dispatcher dispatcher;
+ uint32_t nregions;
+ VubrDevRegion regions[VHOST_MEMORY_MAX_NREGIONS];
+ VubrVirtq vq[MAX_NR_VIRTQUEUE];
+ int log_call_fd;
+ uint64_t log_size;
+ uint8_t *log_table;
+ int backend_udp_sock;
+ struct sockaddr_in backend_udp_dest;
+ int ready;
+ uint64_t features;
+ int hdrlen;
+} VubrDev;
+
+static const char *vubr_request_str[] = {
+ [VHOST_USER_NONE] = "VHOST_USER_NONE",
+ [VHOST_USER_GET_FEATURES] = "VHOST_USER_GET_FEATURES",
+ [VHOST_USER_SET_FEATURES] = "VHOST_USER_SET_FEATURES",
+ [VHOST_USER_SET_OWNER] = "VHOST_USER_SET_OWNER",
+ [VHOST_USER_RESET_OWNER] = "VHOST_USER_RESET_OWNER",
+ [VHOST_USER_SET_MEM_TABLE] = "VHOST_USER_SET_MEM_TABLE",
+ [VHOST_USER_SET_LOG_BASE] = "VHOST_USER_SET_LOG_BASE",
+ [VHOST_USER_SET_LOG_FD] = "VHOST_USER_SET_LOG_FD",
+ [VHOST_USER_SET_VRING_NUM] = "VHOST_USER_SET_VRING_NUM",
+ [VHOST_USER_SET_VRING_ADDR] = "VHOST_USER_SET_VRING_ADDR",
+ [VHOST_USER_SET_VRING_BASE] = "VHOST_USER_SET_VRING_BASE",
+ [VHOST_USER_GET_VRING_BASE] = "VHOST_USER_GET_VRING_BASE",
+ [VHOST_USER_SET_VRING_KICK] = "VHOST_USER_SET_VRING_KICK",
+ [VHOST_USER_SET_VRING_CALL] = "VHOST_USER_SET_VRING_CALL",
+ [VHOST_USER_SET_VRING_ERR] = "VHOST_USER_SET_VRING_ERR",
+ [VHOST_USER_GET_PROTOCOL_FEATURES] = "VHOST_USER_GET_PROTOCOL_FEATURES",
+ [VHOST_USER_SET_PROTOCOL_FEATURES] = "VHOST_USER_SET_PROTOCOL_FEATURES",
+ [VHOST_USER_GET_QUEUE_NUM] = "VHOST_USER_GET_QUEUE_NUM",
+ [VHOST_USER_SET_VRING_ENABLE] = "VHOST_USER_SET_VRING_ENABLE",
+ [VHOST_USER_SEND_RARP] = "VHOST_USER_SEND_RARP",
+ [VHOST_USER_MAX] = "VHOST_USER_MAX",
+};
+
+static void
+print_buffer(uint8_t *buf, size_t len)
+{
+ int i;
+ printf("Raw buffer:\n");
+ for (i = 0; i < len; i++) {
+ if (i % 16 == 0) {
+ printf("\n");
+ }
+ if (i % 4 == 0) {
+ printf(" ");
+ }
+ printf("%02x ", buf[i]);
+ }
+ printf("\n............................................................\n");
+}
+
+/* Translate guest physical address to our virtual address. */
+static uint64_t
+gpa_to_va(VubrDev *dev, uint64_t guest_addr)
+{
+ int i;
+
+ /* Find matching memory region. */
+ for (i = 0; i < dev->nregions; i++) {
+ VubrDevRegion *r = &dev->regions[i];
+
+ if ((guest_addr >= r->gpa) && (guest_addr < (r->gpa + r->size))) {
+ return guest_addr - r->gpa + r->mmap_addr + r->mmap_offset;
+ }
+ }
+
+ assert(!"address not found in regions");
+ return 0;
+}
+
+/* Translate qemu virtual address to our virtual address. */
+static uint64_t
+qva_to_va(VubrDev *dev, uint64_t qemu_addr)
+{
+ int i;
+
+ /* Find matching memory region. */
+ for (i = 0; i < dev->nregions; i++) {
+ VubrDevRegion *r = &dev->regions[i];
+
+ if ((qemu_addr >= r->qva) && (qemu_addr < (r->qva + r->size))) {
+ return qemu_addr - r->qva + r->mmap_addr + r->mmap_offset;
+ }
+ }
+
+ assert(!"address not found in regions");
+ return 0;
+}
+
+static void
+vubr_message_read(int conn_fd, VhostUserMsg *vmsg)
+{
+ char control[CMSG_SPACE(VHOST_MEMORY_MAX_NREGIONS * sizeof(int))] = { };
+ struct iovec iov = {
+ .iov_base = (char *)vmsg,
+ .iov_len = VHOST_USER_HDR_SIZE,
+ };
+ struct msghdr msg = {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = control,
+ .msg_controllen = sizeof(control),
+ };
+ size_t fd_size;
+ struct cmsghdr *cmsg;
+ int rc;
+
+ rc = recvmsg(conn_fd, &msg, 0);
+
+ if (rc == 0) {
+ vubr_die("recvmsg");
+ fprintf(stderr, "Peer disconnected.\n");
+ exit(1);
+ }
+ if (rc < 0) {
+ vubr_die("recvmsg");
+ }
+
+ vmsg->fd_num = 0;
+ for (cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+ fd_size = cmsg->cmsg_len - CMSG_LEN(0);
+ vmsg->fd_num = fd_size / sizeof(int);
+ memcpy(vmsg->fds, CMSG_DATA(cmsg), fd_size);
+ break;
+ }
+ }
+
+ if (vmsg->size > sizeof(vmsg->payload)) {
+ fprintf(stderr,
+ "Error: too big message request: %d, size: vmsg->size: %u, "
+ "while sizeof(vmsg->payload) = %zu\n",
+ vmsg->request, vmsg->size, sizeof(vmsg->payload));
+ exit(1);
+ }
+
+ if (vmsg->size) {
+ rc = read(conn_fd, &vmsg->payload, vmsg->size);
+ if (rc == 0) {
+ vubr_die("recvmsg");
+ fprintf(stderr, "Peer disconnected.\n");
+ exit(1);
+ }
+ if (rc < 0) {
+ vubr_die("recvmsg");
+ }
+
+ assert(rc == vmsg->size);
+ }
+}
+
+static void
+vubr_message_write(int conn_fd, VhostUserMsg *vmsg)
+{
+ int rc;
+
+ do {
+ rc = write(conn_fd, vmsg, VHOST_USER_HDR_SIZE + vmsg->size);
+ } while (rc < 0 && errno == EINTR);
+
+ if (rc < 0) {
+ vubr_die("write");
+ }
+}
+
+static void
+vubr_backend_udp_sendbuf(VubrDev *dev, uint8_t *buf, size_t len)
+{
+ int slen = sizeof(struct sockaddr_in);
+
+ if (sendto(dev->backend_udp_sock, buf, len, 0,
+ (struct sockaddr *) &dev->backend_udp_dest, slen) == -1) {
+ vubr_die("sendto()");
+ }
+}
+
+static int
+vubr_backend_udp_recvbuf(VubrDev *dev, uint8_t *buf, size_t buflen)
+{
+ int slen = sizeof(struct sockaddr_in);
+ int rc;
+
+ rc = recvfrom(dev->backend_udp_sock, buf, buflen, 0,
+ (struct sockaddr *) &dev->backend_udp_dest,
+ (socklen_t *)&slen);
+ if (rc == -1) {
+ vubr_die("recvfrom()");
+ }
+
+ return rc;
+}
+
+static void
+vubr_consume_raw_packet(VubrDev *dev, uint8_t *buf, uint32_t len)
+{
+ int hdrlen = dev->hdrlen;
+ DPRINT(" hdrlen = %d\n", dev->hdrlen);
+
+ if (VHOST_USER_BRIDGE_DEBUG) {
+ print_buffer(buf, len);
+ }
+ vubr_backend_udp_sendbuf(dev, buf + hdrlen, len - hdrlen);
+}
+
+/* Kick the log_call_fd if required. */
+static void
+vubr_log_kick(VubrDev *dev)
+{
+ if (dev->log_call_fd != -1) {
+ DPRINT("Kicking the QEMU's log...\n");
+ eventfd_write(dev->log_call_fd, 1);
+ }
+}
+
+/* Kick the guest if necessary. */
+static void
+vubr_virtqueue_kick(VubrVirtq *vq)
+{
+ if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) {
+ DPRINT("Kicking the guest...\n");
+ eventfd_write(vq->call_fd, 1);
+ }
+}
+
+static void
+vubr_log_page(uint8_t *log_table, uint64_t page)
+{
+ DPRINT("Logged dirty guest page: %"PRId64"\n", page);
+ atomic_or(&log_table[page / 8], 1 << (page % 8));
+}
+
+static void
+vubr_log_write(VubrDev *dev, uint64_t address, uint64_t length)
+{
+ uint64_t page;
+
+ if (!(dev->features & (1ULL << VHOST_F_LOG_ALL)) ||
+ !dev->log_table || !length) {
+ return;
+ }
+
+ assert(dev->log_size > ((address + length - 1) / VHOST_LOG_PAGE / 8));
+
+ page = address / VHOST_LOG_PAGE;
+ while (page * VHOST_LOG_PAGE < address + length) {
+ vubr_log_page(dev->log_table, page);
+ page += VHOST_LOG_PAGE;
+ }
+ vubr_log_kick(dev);
+}
+
+static void
+vubr_post_buffer(VubrDev *dev, VubrVirtq *vq, uint8_t *buf, int32_t len)
+{
+ struct vring_desc *desc = vq->desc;
+ struct vring_avail *avail = vq->avail;
+ struct vring_used *used = vq->used;
+ uint64_t log_guest_addr = vq->log_guest_addr;
+ int32_t remaining_len = len;
+
+ unsigned int size = vq->size;
+
+ uint16_t avail_index = atomic_mb_read(&avail->idx);
+
+ /* We check the available descriptors before posting the
+ * buffer, so here we assume that enough available
+ * descriptors. */
+ assert(vq->last_avail_index != avail_index);
+ uint16_t a_index = vq->last_avail_index % size;
+ uint16_t u_index = vq->last_used_index % size;
+ uint16_t d_index = avail->ring[a_index];
+
+ int i = d_index;
+ uint32_t written_len = 0;
+
+ do {
+ DPRINT("Post packet to guest on vq:\n");
+ DPRINT(" size = %d\n", vq->size);
+ DPRINT(" last_avail_index = %d\n", vq->last_avail_index);
+ DPRINT(" last_used_index = %d\n", vq->last_used_index);
+ DPRINT(" a_index = %d\n", a_index);
+ DPRINT(" u_index = %d\n", u_index);
+ DPRINT(" d_index = %d\n", d_index);
+ DPRINT(" desc[%d].addr = 0x%016"PRIx64"\n", i, desc[i].addr);
+ DPRINT(" desc[%d].len = %d\n", i, desc[i].len);
+ DPRINT(" desc[%d].flags = %d\n", i, desc[i].flags);
+ DPRINT(" avail->idx = %d\n", avail_index);
+ DPRINT(" used->idx = %d\n", used->idx);
+
+ if (!(desc[i].flags & VRING_DESC_F_WRITE)) {
+ /* FIXME: we should find writable descriptor. */
+ fprintf(stderr, "Error: descriptor is not writable. Exiting.\n");
+ exit(1);
+ }
+
+ void *chunk_start = (void *)(uintptr_t)gpa_to_va(dev, desc[i].addr);
+ uint32_t chunk_len = desc[i].len;
+ uint32_t chunk_write_len = MIN(remaining_len, chunk_len);
+
+ memcpy(chunk_start, buf + written_len, chunk_write_len);
+ vubr_log_write(dev, desc[i].addr, chunk_write_len);
+ remaining_len -= chunk_write_len;
+ written_len += chunk_write_len;
+
+ if ((remaining_len == 0) || !(desc[i].flags & VRING_DESC_F_NEXT)) {
+ break;
+ }
+
+ i = desc[i].next;
+ } while (1);
+
+ if (remaining_len > 0) {
+ fprintf(stderr,
+ "Too long packet for RX, remaining_len = %d, Dropping...\n",
+ remaining_len);
+ return;
+ }
+
+ /* Add descriptor to the used ring. */
+ used->ring[u_index].id = d_index;
+ used->ring[u_index].len = len;
+ vubr_log_write(dev,
+ log_guest_addr + offsetof(struct vring_used, ring[u_index]),
+ sizeof(used->ring[u_index]));
+
+ vq->last_avail_index++;
+ vq->last_used_index++;
+
+ atomic_mb_set(&used->idx, vq->last_used_index);
+ vubr_log_write(dev,
+ log_guest_addr + offsetof(struct vring_used, idx),
+ sizeof(used->idx));
+
+ /* Kick the guest if necessary. */
+ vubr_virtqueue_kick(vq);
+}
+
+static int
+vubr_process_desc(VubrDev *dev, VubrVirtq *vq)
+{
+ struct vring_desc *desc = vq->desc;
+ struct vring_avail *avail = vq->avail;
+ struct vring_used *used = vq->used;
+ uint64_t log_guest_addr = vq->log_guest_addr;
+
+ unsigned int size = vq->size;
+
+ uint16_t a_index = vq->last_avail_index % size;
+ uint16_t u_index = vq->last_used_index % size;
+ uint16_t d_index = avail->ring[a_index];
+
+ uint32_t i, len = 0;
+ size_t buf_size = 4096;
+ uint8_t buf[4096];
+
+ DPRINT("Chunks: ");
+ i = d_index;
+ do {
+ void *chunk_start = (void *)(uintptr_t)gpa_to_va(dev, desc[i].addr);
+ uint32_t chunk_len = desc[i].len;
+
+ assert(!(desc[i].flags & VRING_DESC_F_WRITE));
+
+ if (len + chunk_len < buf_size) {
+ memcpy(buf + len, chunk_start, chunk_len);
+ DPRINT("%d ", chunk_len);
+ } else {
+ fprintf(stderr, "Error: too long packet. Dropping...\n");
+ break;
+ }
+
+ len += chunk_len;
+
+ if (!(desc[i].flags & VRING_DESC_F_NEXT)) {
+ break;
+ }
+
+ i = desc[i].next;
+ } while (1);
+ DPRINT("\n");
+
+ if (!len) {
+ return -1;
+ }
+
+ /* Add descriptor to the used ring. */
+ used->ring[u_index].id = d_index;
+ used->ring[u_index].len = len;
+ vubr_log_write(dev,
+ log_guest_addr + offsetof(struct vring_used, ring[u_index]),
+ sizeof(used->ring[u_index]));
+
+ vubr_consume_raw_packet(dev, buf, len);
+
+ return 0;
+}
+
+static void
+vubr_process_avail(VubrDev *dev, VubrVirtq *vq)
+{
+ struct vring_avail *avail = vq->avail;
+ struct vring_used *used = vq->used;
+ uint64_t log_guest_addr = vq->log_guest_addr;
+
+ while (vq->last_avail_index != atomic_mb_read(&avail->idx)) {
+ vubr_process_desc(dev, vq);
+ vq->last_avail_index++;
+ vq->last_used_index++;
+ }
+
+ atomic_mb_set(&used->idx, vq->last_used_index);
+ vubr_log_write(dev,
+ log_guest_addr + offsetof(struct vring_used, idx),
+ sizeof(used->idx));
+}
+
+static void
+vubr_backend_recv_cb(int sock, void *ctx)
+{
+ VubrDev *dev = (VubrDev *) ctx;
+ VubrVirtq *rx_vq = &dev->vq[0];
+ uint8_t buf[4096];
+ struct virtio_net_hdr_v1 *hdr = (struct virtio_net_hdr_v1 *)buf;
+ int hdrlen = dev->hdrlen;
+ int buflen = sizeof(buf);
+ int len;
+
+ if (!dev->ready) {
+ return;
+ }
+
+ DPRINT("\n\n *** IN UDP RECEIVE CALLBACK ***\n\n");
+ DPRINT(" hdrlen = %d\n", hdrlen);
+
+ uint16_t avail_index = atomic_mb_read(&rx_vq->avail->idx);
+
+ /* If there is no available descriptors, just do nothing.
+ * The buffer will be handled by next arrived UDP packet,
+ * or next kick on receive virtq. */
+ if (rx_vq->last_avail_index == avail_index) {
+ DPRINT("Got UDP packet, but no available descriptors on RX virtq.\n");
+ return;
+ }
+
+ memset(buf, 0, hdrlen);
+ /* TODO: support mergeable buffers. */
+ if (hdrlen == 12)
+ hdr->num_buffers = 1;
+ len = vubr_backend_udp_recvbuf(dev, buf + hdrlen, buflen - hdrlen);
+
+ vubr_post_buffer(dev, rx_vq, buf, len + hdrlen);
+}
+
+static void
+vubr_kick_cb(int sock, void *ctx)
+{
+ VubrDev *dev = (VubrDev *) ctx;
+ eventfd_t kick_data;
+ ssize_t rc;
+
+ rc = eventfd_read(sock, &kick_data);
+ if (rc == -1) {
+ vubr_die("eventfd_read()");
+ } else {
+ DPRINT("Got kick_data: %016"PRIx64"\n", kick_data);
+ vubr_process_avail(dev, &dev->vq[1]);
+ }
+}
+
+static int
+vubr_none_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ DPRINT("Function %s() not implemented yet.\n", __func__);
+ return 0;
+}
+
+static int
+vubr_get_features_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ vmsg->payload.u64 =
+ ((1ULL << VIRTIO_NET_F_MRG_RXBUF) |
+ (1ULL << VHOST_F_LOG_ALL) |
+ (1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) |
+ (1ULL << VHOST_USER_F_PROTOCOL_FEATURES));
+
+ vmsg->size = sizeof(vmsg->payload.u64);
+
+ DPRINT("Sending back to guest u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
+
+ /* Reply */
+ return 1;
+}
+
+static int
+vubr_set_features_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
+
+ dev->features = vmsg->payload.u64;
+ if ((dev->features & (1ULL << VIRTIO_F_VERSION_1)) ||
+ (dev->features & (1ULL << VIRTIO_NET_F_MRG_RXBUF))) {
+ dev->hdrlen = 12;
+ } else {
+ dev->hdrlen = 10;
+ }
+
+ return 0;
+}
+
+static int
+vubr_set_owner_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ return 0;
+}
+
+static void
+vubr_close_log(VubrDev *dev)
+{
+ if (dev->log_table) {
+ if (munmap(dev->log_table, dev->log_size) != 0) {
+ vubr_die("munmap()");
+ }
+
+ dev->log_table = 0;
+ }
+ if (dev->log_call_fd != -1) {
+ close(dev->log_call_fd);
+ dev->log_call_fd = -1;
+ }
+}
+
+static int
+vubr_reset_device_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ vubr_close_log(dev);
+ dev->ready = 0;
+ dev->features = 0;
+ return 0;
+}
+
+static int
+vubr_set_mem_table_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ int i;
+ VhostUserMemory *memory = &vmsg->payload.memory;
+ dev->nregions = memory->nregions;
+
+ DPRINT("Nregions: %d\n", memory->nregions);
+ for (i = 0; i < dev->nregions; i++) {
+ void *mmap_addr;
+ VhostUserMemoryRegion *msg_region = &memory->regions[i];
+ VubrDevRegion *dev_region = &dev->regions[i];
+
+ DPRINT("Region %d\n", i);
+ DPRINT(" guest_phys_addr: 0x%016"PRIx64"\n",
+ msg_region->guest_phys_addr);
+ DPRINT(" memory_size: 0x%016"PRIx64"\n",
+ msg_region->memory_size);
+ DPRINT(" userspace_addr 0x%016"PRIx64"\n",
+ msg_region->userspace_addr);
+ DPRINT(" mmap_offset 0x%016"PRIx64"\n",
+ msg_region->mmap_offset);
+
+ dev_region->gpa = msg_region->guest_phys_addr;
+ dev_region->size = msg_region->memory_size;
+ dev_region->qva = msg_region->userspace_addr;
+ dev_region->mmap_offset = msg_region->mmap_offset;
+
+ /* We don't use offset argument of mmap() since the
+ * mapped address has to be page aligned, and we use huge
+ * pages. */
+ mmap_addr = mmap(0, dev_region->size + dev_region->mmap_offset,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ vmsg->fds[i], 0);
+
+ if (mmap_addr == MAP_FAILED) {
+ vubr_die("mmap");
+ }
+ dev_region->mmap_addr = (uint64_t)(uintptr_t)mmap_addr;
+ DPRINT(" mmap_addr: 0x%016"PRIx64"\n", dev_region->mmap_addr);
+
+ close(vmsg->fds[i]);
+ }
+
+ return 0;
+}
+
+static int
+vubr_set_log_base_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ int fd;
+ uint64_t log_mmap_size, log_mmap_offset;
+ void *rc;
+
+ assert(vmsg->fd_num == 1);
+ fd = vmsg->fds[0];
+
+ assert(vmsg->size == sizeof(vmsg->payload.log));
+ log_mmap_offset = vmsg->payload.log.mmap_offset;
+ log_mmap_size = vmsg->payload.log.mmap_size;
+ DPRINT("Log mmap_offset: %"PRId64"\n", log_mmap_offset);
+ DPRINT("Log mmap_size: %"PRId64"\n", log_mmap_size);
+
+ rc = mmap(0, log_mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ log_mmap_offset);
+ if (rc == MAP_FAILED) {
+ vubr_die("mmap");
+ }
+ dev->log_table = rc;
+ dev->log_size = log_mmap_size;
+
+ vmsg->size = sizeof(vmsg->payload.u64);
+ /* Reply */
+ return 1;
+}
+
+static int
+vubr_set_log_fd_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ assert(vmsg->fd_num == 1);
+ dev->log_call_fd = vmsg->fds[0];
+ DPRINT("Got log_call_fd: %d\n", vmsg->fds[0]);
+ return 0;
+}
+
+static int
+vubr_set_vring_num_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ unsigned int index = vmsg->payload.state.index;
+ unsigned int num = vmsg->payload.state.num;
+
+ DPRINT("State.index: %d\n", index);
+ DPRINT("State.num: %d\n", num);
+ dev->vq[index].size = num;
+ return 0;
+}
+
+static int
+vubr_set_vring_addr_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ struct vhost_vring_addr *vra = &vmsg->payload.addr;
+ unsigned int index = vra->index;
+ VubrVirtq *vq = &dev->vq[index];
+
+ DPRINT("vhost_vring_addr:\n");
+ DPRINT(" index: %d\n", vra->index);
+ DPRINT(" flags: %d\n", vra->flags);
+ DPRINT(" desc_user_addr: 0x%016llx\n", vra->desc_user_addr);
+ DPRINT(" used_user_addr: 0x%016llx\n", vra->used_user_addr);
+ DPRINT(" avail_user_addr: 0x%016llx\n", vra->avail_user_addr);
+ DPRINT(" log_guest_addr: 0x%016llx\n", vra->log_guest_addr);
+
+ vq->desc = (struct vring_desc *)(uintptr_t)qva_to_va(dev, vra->desc_user_addr);
+ vq->used = (struct vring_used *)(uintptr_t)qva_to_va(dev, vra->used_user_addr);
+ vq->avail = (struct vring_avail *)(uintptr_t)qva_to_va(dev, vra->avail_user_addr);
+ vq->log_guest_addr = vra->log_guest_addr;
+
+ DPRINT("Setting virtq addresses:\n");
+ DPRINT(" vring_desc at %p\n", vq->desc);
+ DPRINT(" vring_used at %p\n", vq->used);
+ DPRINT(" vring_avail at %p\n", vq->avail);
+
+ vq->last_used_index = vq->used->idx;
+ return 0;
+}
+
+static int
+vubr_set_vring_base_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ unsigned int index = vmsg->payload.state.index;
+ unsigned int num = vmsg->payload.state.num;
+
+ DPRINT("State.index: %d\n", index);
+ DPRINT("State.num: %d\n", num);
+ dev->vq[index].last_avail_index = num;
+
+ return 0;
+}
+
+static int
+vubr_get_vring_base_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ unsigned int index = vmsg->payload.state.index;
+
+ DPRINT("State.index: %d\n", index);
+ vmsg->payload.state.num = dev->vq[index].last_avail_index;
+ vmsg->size = sizeof(vmsg->payload.state);
+ /* FIXME: this is a work-around for a bug in QEMU enabling
+ * too early vrings. When protocol features are enabled,
+ * we have to respect * VHOST_USER_SET_VRING_ENABLE request. */
+ dev->ready = 0;
+
+ if (dev->vq[index].call_fd != -1) {
+ close(dev->vq[index].call_fd);
+ dispatcher_remove(&dev->dispatcher, dev->vq[index].call_fd);
+ dev->vq[index].call_fd = -1;
+ }
+ if (dev->vq[index].kick_fd != -1) {
+ close(dev->vq[index].kick_fd);
+ dispatcher_remove(&dev->dispatcher, dev->vq[index].kick_fd);
+ dev->vq[index].kick_fd = -1;
+ }
+
+ /* Reply */
+ return 1;
+}
+
+static int
+vubr_set_vring_kick_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ uint64_t u64_arg = vmsg->payload.u64;
+ int index = u64_arg & VHOST_USER_VRING_IDX_MASK;
+
+ DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
+
+ assert((u64_arg & VHOST_USER_VRING_NOFD_MASK) == 0);
+ assert(vmsg->fd_num == 1);
+
+ if (dev->vq[index].kick_fd != -1) {
+ close(dev->vq[index].kick_fd);
+ dispatcher_remove(&dev->dispatcher, dev->vq[index].kick_fd);
+ }
+ dev->vq[index].kick_fd = vmsg->fds[0];
+ DPRINT("Got kick_fd: %d for vq: %d\n", vmsg->fds[0], index);
+
+ if (index % 2 == 1) {
+ /* TX queue. */
+ dispatcher_add(&dev->dispatcher, dev->vq[index].kick_fd,
+ dev, vubr_kick_cb);
+
+ DPRINT("Waiting for kicks on fd: %d for vq: %d\n",
+ dev->vq[index].kick_fd, index);
+ }
+ /* We temporarily use this hack to determine that both TX and RX
+ * queues are set up and ready for processing.
+ * FIXME: we need to rely in VHOST_USER_SET_VRING_ENABLE and
+ * actual kicks. */
+ if (dev->vq[0].kick_fd != -1 &&
+ dev->vq[1].kick_fd != -1) {
+ dev->ready = 1;
+ DPRINT("vhost-user-bridge is ready for processing queues.\n");
+ }
+ return 0;
+
+}
+
+static int
+vubr_set_vring_call_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ uint64_t u64_arg = vmsg->payload.u64;
+ int index = u64_arg & VHOST_USER_VRING_IDX_MASK;
+
+ DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
+ assert((u64_arg & VHOST_USER_VRING_NOFD_MASK) == 0);
+ assert(vmsg->fd_num == 1);
+
+ if (dev->vq[index].call_fd != -1) {
+ close(dev->vq[index].call_fd);
+ dispatcher_remove(&dev->dispatcher, dev->vq[index].call_fd);
+ }
+ dev->vq[index].call_fd = vmsg->fds[0];
+ DPRINT("Got call_fd: %d for vq: %d\n", vmsg->fds[0], index);
+
+ return 0;
+}
+
+static int
+vubr_set_vring_err_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
+ return 0;
+}
+
+static int
+vubr_get_protocol_features_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ vmsg->payload.u64 = 1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
+ DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
+ vmsg->size = sizeof(vmsg->payload.u64);
+
+ /* Reply */
+ return 1;
+}
+
+static int
+vubr_set_protocol_features_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ /* FIXME: unimplented */
+ DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
+ return 0;
+}
+
+static int
+vubr_get_queue_num_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ DPRINT("Function %s() not implemented yet.\n", __func__);
+ return 0;
+}
+
+static int
+vubr_set_vring_enable_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ unsigned int index = vmsg->payload.state.index;
+ unsigned int enable = vmsg->payload.state.num;
+
+ DPRINT("State.index: %d\n", index);
+ DPRINT("State.enable: %d\n", enable);
+ dev->vq[index].enable = enable;
+ return 0;
+}
+
+static int
+vubr_send_rarp_exec(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ DPRINT("Function %s() not implemented yet.\n", __func__);
+ return 0;
+}
+
+static int
+vubr_execute_request(VubrDev *dev, VhostUserMsg *vmsg)
+{
+ /* Print out generic part of the request. */
+ DPRINT(
+ "================== Vhost user message from QEMU ==================\n");
+ DPRINT("Request: %s (%d)\n", vubr_request_str[vmsg->request],
+ vmsg->request);
+ DPRINT("Flags: 0x%x\n", vmsg->flags);
+ DPRINT("Size: %d\n", vmsg->size);
+
+ if (vmsg->fd_num) {
+ int i;
+ DPRINT("Fds:");
+ for (i = 0; i < vmsg->fd_num; i++) {
+ DPRINT(" %d", vmsg->fds[i]);
+ }
+ DPRINT("\n");
+ }
+
+ switch (vmsg->request) {
+ case VHOST_USER_NONE:
+ return vubr_none_exec(dev, vmsg);
+ case VHOST_USER_GET_FEATURES:
+ return vubr_get_features_exec(dev, vmsg);
+ case VHOST_USER_SET_FEATURES:
+ return vubr_set_features_exec(dev, vmsg);
+ case VHOST_USER_SET_OWNER:
+ return vubr_set_owner_exec(dev, vmsg);
+ case VHOST_USER_RESET_OWNER:
+ return vubr_reset_device_exec(dev, vmsg);
+ case VHOST_USER_SET_MEM_TABLE:
+ return vubr_set_mem_table_exec(dev, vmsg);
+ case VHOST_USER_SET_LOG_BASE:
+ return vubr_set_log_base_exec(dev, vmsg);
+ case VHOST_USER_SET_LOG_FD:
+ return vubr_set_log_fd_exec(dev, vmsg);
+ case VHOST_USER_SET_VRING_NUM:
+ return vubr_set_vring_num_exec(dev, vmsg);
+ case VHOST_USER_SET_VRING_ADDR:
+ return vubr_set_vring_addr_exec(dev, vmsg);
+ case VHOST_USER_SET_VRING_BASE:
+ return vubr_set_vring_base_exec(dev, vmsg);
+ case VHOST_USER_GET_VRING_BASE:
+ return vubr_get_vring_base_exec(dev, vmsg);
+ case VHOST_USER_SET_VRING_KICK:
+ return vubr_set_vring_kick_exec(dev, vmsg);
+ case VHOST_USER_SET_VRING_CALL:
+ return vubr_set_vring_call_exec(dev, vmsg);
+ case VHOST_USER_SET_VRING_ERR:
+ return vubr_set_vring_err_exec(dev, vmsg);
+ case VHOST_USER_GET_PROTOCOL_FEATURES:
+ return vubr_get_protocol_features_exec(dev, vmsg);
+ case VHOST_USER_SET_PROTOCOL_FEATURES:
+ return vubr_set_protocol_features_exec(dev, vmsg);
+ case VHOST_USER_GET_QUEUE_NUM:
+ return vubr_get_queue_num_exec(dev, vmsg);
+ case VHOST_USER_SET_VRING_ENABLE:
+ return vubr_set_vring_enable_exec(dev, vmsg);
+ case VHOST_USER_SEND_RARP:
+ return vubr_send_rarp_exec(dev, vmsg);
+
+ case VHOST_USER_MAX:
+ assert(vmsg->request != VHOST_USER_MAX);
+ }
+ return 0;
+}
+
+static void
+vubr_receive_cb(int sock, void *ctx)
+{
+ VubrDev *dev = (VubrDev *) ctx;
+ VhostUserMsg vmsg;
+ int reply_requested;
+
+ vubr_message_read(sock, &vmsg);
+ reply_requested = vubr_execute_request(dev, &vmsg);
+ if (reply_requested) {
+ /* Set the version in the flags when sending the reply */
+ vmsg.flags &= ~VHOST_USER_VERSION_MASK;
+ vmsg.flags |= VHOST_USER_VERSION;
+ vmsg.flags |= VHOST_USER_REPLY_MASK;
+ vubr_message_write(sock, &vmsg);
+ }
+}
+
+static void
+vubr_accept_cb(int sock, void *ctx)
+{
+ VubrDev *dev = (VubrDev *)ctx;
+ int conn_fd;
+ struct sockaddr_un un;
+ socklen_t len = sizeof(un);
+
+ conn_fd = accept(sock, (struct sockaddr *) &un, &len);
+ if (conn_fd == -1) {
+ vubr_die("accept()");
+ }
+ DPRINT("Got connection from remote peer on sock %d\n", conn_fd);
+ dispatcher_add(&dev->dispatcher, conn_fd, ctx, vubr_receive_cb);
+}
+
+static VubrDev *
+vubr_new(const char *path)
+{
+ VubrDev *dev = (VubrDev *) calloc(1, sizeof(VubrDev));
+ dev->nregions = 0;
+ int i;
+ struct sockaddr_un un;
+ size_t len;
+
+ for (i = 0; i < MAX_NR_VIRTQUEUE; i++) {
+ dev->vq[i] = (VubrVirtq) {
+ .call_fd = -1, .kick_fd = -1,
+ .size = 0,
+ .last_avail_index = 0, .last_used_index = 0,
+ .desc = 0, .avail = 0, .used = 0,
+ .enable = 0,
+ };
+ }
+
+ /* Init log */
+ dev->log_call_fd = -1;
+ dev->log_size = 0;
+ dev->log_table = 0;
+ dev->ready = 0;
+ dev->features = 0;
+
+ /* Get a UNIX socket. */
+ dev->sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (dev->sock == -1) {
+ vubr_die("socket");
+ }
+
+ un.sun_family = AF_UNIX;
+ strcpy(un.sun_path, path);
+ len = sizeof(un.sun_family) + strlen(path);
+ unlink(path);
+
+ if (bind(dev->sock, (struct sockaddr *) &un, len) == -1) {
+ vubr_die("bind");
+ }
+
+ if (listen(dev->sock, 1) == -1) {
+ vubr_die("listen");
+ }
+
+ dispatcher_init(&dev->dispatcher);
+ dispatcher_add(&dev->dispatcher, dev->sock, (void *)dev,
+ vubr_accept_cb);
+
+ DPRINT("Waiting for connections on UNIX socket %s ...\n", path);
+ return dev;
+}
+
+static void
+vubr_set_host(struct sockaddr_in *saddr, const char *host)
+{
+ if (isdigit(host[0])) {
+ if (!inet_aton(host, &saddr->sin_addr)) {
+ fprintf(stderr, "inet_aton() failed.\n");
+ exit(1);
+ }
+ } else {
+ struct hostent *he = gethostbyname(host);
+
+ if (!he) {
+ fprintf(stderr, "gethostbyname() failed.\n");
+ exit(1);
+ }
+ saddr->sin_addr = *(struct in_addr *)he->h_addr;
+ }
+}
+
+static void
+vubr_backend_udp_setup(VubrDev *dev,
+ const char *local_host,
+ const char *local_port,
+ const char *remote_host,
+ const char *remote_port)
+{
+ int sock;
+ const char *r;
+
+ int lport, rport;
+
+ lport = strtol(local_port, (char **)&r, 0);
+ if (r == local_port) {
+ fprintf(stderr, "lport parsing failed.\n");
+ exit(1);
+ }
+
+ rport = strtol(remote_port, (char **)&r, 0);
+ if (r == remote_port) {
+ fprintf(stderr, "rport parsing failed.\n");
+ exit(1);
+ }
+
+ struct sockaddr_in si_local = {
+ .sin_family = AF_INET,
+ .sin_port = htons(lport),
+ };
+
+ vubr_set_host(&si_local, local_host);
+
+ /* setup destination for sends */
+ dev->backend_udp_dest = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ .sin_port = htons(rport),
+ };
+ vubr_set_host(&dev->backend_udp_dest, remote_host);
+
+ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock == -1) {
+ vubr_die("socket");
+ }
+
+ if (bind(sock, (struct sockaddr *)&si_local, sizeof(si_local)) == -1) {
+ vubr_die("bind");
+ }
+
+ dev->backend_udp_sock = sock;
+ dispatcher_add(&dev->dispatcher, sock, dev, vubr_backend_recv_cb);
+ DPRINT("Waiting for data from udp backend on %s:%d...\n",
+ local_host, lport);
+}
+
+static void
+vubr_run(VubrDev *dev)
+{
+ while (1) {
+ /* timeout 200ms */
+ dispatcher_wait(&dev->dispatcher, 200000);
+ /* Here one can try polling strategy. */
+ }
+}
+
+static int
+vubr_parse_host_port(const char **host, const char **port, const char *buf)
+{
+ char *p = strchr(buf, ':');
+
+ if (!p) {
+ return -1;
+ }
+ *p = '\0';
+ *host = strdup(buf);
+ *port = strdup(p + 1);
+ return 0;
+}
+
+#define DEFAULT_UD_SOCKET "/tmp/vubr.sock"
+#define DEFAULT_LHOST "127.0.0.1"
+#define DEFAULT_LPORT "4444"
+#define DEFAULT_RHOST "127.0.0.1"
+#define DEFAULT_RPORT "5555"
+
+static const char *ud_socket_path = DEFAULT_UD_SOCKET;
+static const char *lhost = DEFAULT_LHOST;
+static const char *lport = DEFAULT_LPORT;
+static const char *rhost = DEFAULT_RHOST;
+static const char *rport = DEFAULT_RPORT;
+
+int
+main(int argc, char *argv[])
+{
+ VubrDev *dev;
+ int opt;
+
+ while ((opt = getopt(argc, argv, "l:r:u:")) != -1) {
+
+ switch (opt) {
+ case 'l':
+ if (vubr_parse_host_port(&lhost, &lport, optarg) < 0) {
+ goto out;
+ }
+ break;
+ case 'r':
+ if (vubr_parse_host_port(&rhost, &rport, optarg) < 0) {
+ goto out;
+ }
+ break;
+ case 'u':
+ ud_socket_path = strdup(optarg);
+ break;
+ default:
+ goto out;
+ }
+ }
+
+ DPRINT("ud socket: %s\n", ud_socket_path);
+ DPRINT("local: %s:%s\n", lhost, lport);
+ DPRINT("remote: %s:%s\n", rhost, rport);
+
+ dev = vubr_new(ud_socket_path);
+ if (!dev) {
+ return 1;
+ }
+
+ vubr_backend_udp_setup(dev, lhost, lport, rhost, rport);
+ vubr_run(dev);
+ return 0;
+
+out:
+ fprintf(stderr, "Usage: %s ", argv[0]);
+ fprintf(stderr, "[-u ud_socket_path] [-l lhost:lport] [-r rhost:rport]\n");
+ fprintf(stderr, "\t-u path to unix doman socket. default: %s\n",
+ DEFAULT_UD_SOCKET);
+ fprintf(stderr, "\t-l local host and port. default: %s:%s\n",
+ DEFAULT_LHOST, DEFAULT_LPORT);
+ fprintf(stderr, "\t-r remote host and port. default: %s:%s\n",
+ DEFAULT_RHOST, DEFAULT_RPORT);
+
+ return 1;
+}
diff --git a/qemu/tests/vhost-user-test.c b/qemu/tests/vhost-user-test.c
index 75fedf097..69615968c 100644
--- a/qemu/tests/vhost-user-test.c
+++ b/qemu/tests/vhost-user-test.c
@@ -8,11 +8,12 @@
*
*/
-#define QEMU_GLIB_COMPAT_H
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqtest.h"
#include "qemu/option.h"
+#include "qemu/range.h"
#include "sysemu/char.h"
#include "sysemu/sysemu.h"
@@ -30,22 +31,15 @@
#define HAVE_MONOTONIC_TIME
#endif
-#if GLIB_CHECK_VERSION(2, 32, 0)
-#define HAVE_MUTEX_INIT
-#define HAVE_COND_INIT
-#define HAVE_THREAD_NEW
-#endif
-
#define QEMU_CMD_ACCEL " -machine accel=tcg"
-#define QEMU_CMD_MEM " -m 512 -object memory-backend-file,id=mem,size=512M,"\
+#define QEMU_CMD_MEM " -m %d -object memory-backend-file,id=mem,size=%dM,"\
"mem-path=%s,share=on -numa node,memdev=mem"
-#define QEMU_CMD_CHR " -chardev socket,id=chr0,path=%s"
-#define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=chr0,vhostforce"
-#define QEMU_CMD_NET " -device virtio-net-pci,netdev=net0 "
-#define QEMU_CMD_ROM " -option-rom ../pc-bios/pxe-virtio.rom"
+#define QEMU_CMD_CHR " -chardev socket,id=%s,path=%s"
+#define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=%s,vhostforce"
+#define QEMU_CMD_NET " -device virtio-net-pci,netdev=net0,romfile=./pc-bios/pxe-virtio.rom"
#define QEMU_CMD QEMU_CMD_ACCEL QEMU_CMD_MEM QEMU_CMD_CHR \
- QEMU_CMD_NETDEV QEMU_CMD_NET QEMU_CMD_ROM
+ QEMU_CMD_NETDEV QEMU_CMD_NET
#define HUGETLBFS_MAGIC 0x958458f6
@@ -53,6 +47,11 @@
#define VHOST_MEMORY_MAX_NREGIONS 8
+#define VHOST_USER_F_PROTOCOL_FEATURES 30
+#define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1
+
+#define VHOST_LOG_PAGE 0x1000
+
typedef enum VhostUserRequest {
VHOST_USER_NONE = 0,
VHOST_USER_GET_FEATURES = 1,
@@ -69,6 +68,9 @@ typedef enum VhostUserRequest {
VHOST_USER_SET_VRING_KICK = 12,
VHOST_USER_SET_VRING_CALL = 13,
VHOST_USER_SET_VRING_ERR = 14,
+ VHOST_USER_GET_PROTOCOL_FEATURES = 15,
+ VHOST_USER_SET_PROTOCOL_FEATURES = 16,
+ VHOST_USER_SET_VRING_ENABLE = 18,
VHOST_USER_MAX
} VhostUserRequest;
@@ -85,6 +87,11 @@ typedef struct VhostUserMemory {
VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];
} VhostUserMemory;
+typedef struct VhostUserLog {
+ uint64_t mmap_size;
+ uint64_t mmap_offset;
+} VhostUserLog;
+
typedef struct VhostUserMsg {
VhostUserRequest request;
@@ -93,11 +100,14 @@ typedef struct VhostUserMsg {
uint32_t flags;
uint32_t size; /* the following payload size */
union {
+#define VHOST_USER_VRING_IDX_MASK (0xff)
+#define VHOST_USER_VRING_NOFD_MASK (0x1<<8)
uint64_t u64;
struct vhost_vring_state state;
struct vhost_vring_addr addr;
VhostUserMemory memory;
- };
+ VhostUserLog log;
+ } payload;
} QEMU_PACKED VhostUserMsg;
static VhostUserMsg m __attribute__ ((unused));
@@ -111,154 +121,104 @@ static VhostUserMsg m __attribute__ ((unused));
#define VHOST_USER_VERSION (0x1)
/*****************************************************************************/
-int fds_num = 0, fds[VHOST_MEMORY_MAX_NREGIONS];
-static VhostUserMemory memory;
-static GMutex *data_mutex;
-static GCond *data_cond;
-
-static gint64 _get_time(void)
-{
-#ifdef HAVE_MONOTONIC_TIME
- return g_get_monotonic_time();
-#else
- GTimeVal time;
- g_get_current_time(&time);
-
- return time.tv_sec * G_TIME_SPAN_SECOND + time.tv_usec;
-#endif
-}
-
-static GMutex *_mutex_new(void)
-{
- GMutex *mutex;
-
-#ifdef HAVE_MUTEX_INIT
- mutex = g_new(GMutex, 1);
- g_mutex_init(mutex);
-#else
- mutex = g_mutex_new();
-#endif
-
- return mutex;
-}
-
-static void _mutex_free(GMutex *mutex)
-{
-#ifdef HAVE_MUTEX_INIT
- g_mutex_clear(mutex);
- g_free(mutex);
-#else
- g_mutex_free(mutex);
-#endif
-}
-
-static GCond *_cond_new(void)
-{
- GCond *cond;
-
-#ifdef HAVE_COND_INIT
- cond = g_new(GCond, 1);
- g_cond_init(cond);
-#else
- cond = g_cond_new();
-#endif
-
- return cond;
-}
-
-static gboolean _cond_wait_until(GCond *cond, GMutex *mutex, gint64 end_time)
+typedef struct TestServer {
+ gchar *socket_path;
+ gchar *mig_path;
+ gchar *chr_name;
+ CharDriverState *chr;
+ int fds_num;
+ int fds[VHOST_MEMORY_MAX_NREGIONS];
+ VhostUserMemory memory;
+ GMutex data_mutex;
+ GCond data_cond;
+ int log_fd;
+ uint64_t rings;
+} TestServer;
+
+#if !GLIB_CHECK_VERSION(2, 32, 0)
+static gboolean g_cond_wait_until(CompatGCond cond, CompatGMutex mutex,
+ gint64 end_time)
{
gboolean ret = FALSE;
-#ifdef HAVE_COND_INIT
- ret = g_cond_wait_until(cond, mutex, end_time);
-#else
+ end_time -= g_get_monotonic_time();
GTimeVal time = { end_time / G_TIME_SPAN_SECOND,
end_time % G_TIME_SPAN_SECOND };
ret = g_cond_timed_wait(cond, mutex, &time);
-#endif
return ret;
}
-
-static void _cond_free(GCond *cond)
-{
-#ifdef HAVE_COND_INIT
- g_cond_clear(cond);
- g_free(cond);
-#else
- g_cond_free(cond);
#endif
-}
-static GThread *_thread_new(const gchar *name, GThreadFunc func, gpointer data)
-{
- GThread *thread = NULL;
- GError *error = NULL;
-#ifdef HAVE_THREAD_NEW
- thread = g_thread_try_new(name, func, data, &error);
-#else
- thread = g_thread_create(func, data, TRUE, &error);
-#endif
- return thread;
-}
+static const char *tmpfs;
+static const char *root;
-static void read_guest_mem(void)
+static void wait_for_fds(TestServer *s)
{
- uint32_t *guest_mem;
gint64 end_time;
- int i, j;
- size_t size;
- g_mutex_lock(data_mutex);
+ g_mutex_lock(&s->data_mutex);
- end_time = _get_time() + 5 * G_TIME_SPAN_SECOND;
- while (!fds_num) {
- if (!_cond_wait_until(data_cond, data_mutex, end_time)) {
+ end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+ while (!s->fds_num) {
+ if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
/* timeout has passed */
- g_assert(fds_num);
+ g_assert(s->fds_num);
break;
}
}
/* check for sanity */
- g_assert_cmpint(fds_num, >, 0);
- g_assert_cmpint(fds_num, ==, memory.nregions);
+ g_assert_cmpint(s->fds_num, >, 0);
+ g_assert_cmpint(s->fds_num, ==, s->memory.nregions);
+
+ g_mutex_unlock(&s->data_mutex);
+}
+
+static void read_guest_mem(const void *data)
+{
+ TestServer *s = (void *)data;
+ uint32_t *guest_mem;
+ int i, j;
+ size_t size;
+
+ wait_for_fds(s);
+
+ g_mutex_lock(&s->data_mutex);
/* iterate all regions */
- for (i = 0; i < fds_num; i++) {
+ for (i = 0; i < s->fds_num; i++) {
/* We'll check only the region statring at 0x0*/
- if (memory.regions[i].guest_phys_addr != 0x0) {
+ if (s->memory.regions[i].guest_phys_addr != 0x0) {
continue;
}
- g_assert_cmpint(memory.regions[i].memory_size, >, 1024);
+ g_assert_cmpint(s->memory.regions[i].memory_size, >, 1024);
- size = memory.regions[i].memory_size + memory.regions[i].mmap_offset;
+ size = s->memory.regions[i].memory_size +
+ s->memory.regions[i].mmap_offset;
guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
- MAP_SHARED, fds[i], 0);
+ MAP_SHARED, s->fds[i], 0);
g_assert(guest_mem != MAP_FAILED);
- guest_mem += (memory.regions[i].mmap_offset / sizeof(*guest_mem));
+ guest_mem += (s->memory.regions[i].mmap_offset / sizeof(*guest_mem));
for (j = 0; j < 256; j++) {
- uint32_t a = readl(memory.regions[i].guest_phys_addr + j*4);
+ uint32_t a = readl(s->memory.regions[i].guest_phys_addr + j*4);
uint32_t b = guest_mem[j];
g_assert_cmpint(a, ==, b);
}
- munmap(guest_mem, memory.regions[i].memory_size);
+ munmap(guest_mem, s->memory.regions[i].memory_size);
}
- g_assert_cmpint(1, ==, 1);
- g_mutex_unlock(data_mutex);
+ g_mutex_unlock(&s->data_mutex);
}
static void *thread_function(void *data)
{
- GMainLoop *loop;
- loop = g_main_loop_new(NULL, FALSE);
+ GMainLoop *loop = data;
g_main_loop_run(loop);
return NULL;
}
@@ -270,7 +230,8 @@ static int chr_can_read(void *opaque)
static void chr_read(void *opaque, const uint8_t *buf, int size)
{
- CharDriverState *chr = opaque;
+ TestServer *s = opaque;
+ CharDriverState *chr = s->chr;
VhostUserMsg msg;
uint8_t *p = (uint8_t *) &msg;
int fd;
@@ -280,20 +241,35 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
return;
}
- g_mutex_lock(data_mutex);
+ g_mutex_lock(&s->data_mutex);
memcpy(p, buf, VHOST_USER_HDR_SIZE);
if (msg.size) {
p += VHOST_USER_HDR_SIZE;
- qemu_chr_fe_read_all(chr, p, msg.size);
+ g_assert_cmpint(qemu_chr_fe_read_all(chr, p, msg.size), ==, msg.size);
}
switch (msg.request) {
case VHOST_USER_GET_FEATURES:
/* send back features to qemu */
msg.flags |= VHOST_USER_REPLY_MASK;
- msg.size = sizeof(m.u64);
- msg.u64 = 0;
+ msg.size = sizeof(m.payload.u64);
+ msg.payload.u64 = 0x1ULL << VHOST_F_LOG_ALL |
+ 0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
+ p = (uint8_t *) &msg;
+ qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
+ break;
+
+ case VHOST_USER_SET_FEATURES:
+ g_assert_cmpint(msg.payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES),
+ !=, 0ULL);
+ break;
+
+ case VHOST_USER_GET_PROTOCOL_FEATURES:
+ /* send back features to qemu */
+ msg.flags |= VHOST_USER_REPLY_MASK;
+ msg.size = sizeof(m.payload.u64);
+ msg.payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
p = (uint8_t *) &msg;
qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
break;
@@ -301,19 +277,22 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
case VHOST_USER_GET_VRING_BASE:
/* send back vring base to qemu */
msg.flags |= VHOST_USER_REPLY_MASK;
- msg.size = sizeof(m.state);
- msg.state.num = 0;
+ msg.size = sizeof(m.payload.state);
+ msg.payload.state.num = 0;
p = (uint8_t *) &msg;
qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
+
+ assert(msg.payload.state.index < 2);
+ s->rings &= ~(0x1ULL << msg.payload.state.index);
break;
case VHOST_USER_SET_MEM_TABLE:
/* received the mem table */
- memcpy(&memory, &msg.memory, sizeof(msg.memory));
- fds_num = qemu_chr_fe_get_msgfds(chr, fds, sizeof(fds) / sizeof(int));
+ memcpy(&s->memory, &msg.payload.memory, sizeof(msg.payload.memory));
+ s->fds_num = qemu_chr_fe_get_msgfds(chr, s->fds, G_N_ELEMENTS(s->fds));
/* signal the test that it can continue */
- g_cond_signal(data_cond);
+ g_cond_signal(&s->data_cond);
break;
case VHOST_USER_SET_VRING_KICK:
@@ -327,23 +306,38 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
*/
qemu_set_nonblock(fd);
break;
+
+ case VHOST_USER_SET_LOG_BASE:
+ if (s->log_fd != -1) {
+ close(s->log_fd);
+ s->log_fd = -1;
+ }
+ qemu_chr_fe_get_msgfds(chr, &s->log_fd, 1);
+ msg.flags |= VHOST_USER_REPLY_MASK;
+ msg.size = 0;
+ p = (uint8_t *) &msg;
+ qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE);
+
+ g_cond_signal(&s->data_cond);
+ break;
+
+ case VHOST_USER_SET_VRING_BASE:
+ assert(msg.payload.state.index < 2);
+ s->rings |= 0x1ULL << msg.payload.state.index;
+ break;
+
default:
break;
}
- g_mutex_unlock(data_mutex);
+
+ g_mutex_unlock(&s->data_mutex);
}
-static const char *init_hugepagefs(void)
+static const char *init_hugepagefs(const char *path)
{
- const char *path;
struct statfs fs;
int ret;
- path = getenv("QTEST_HUGETLBFS_PATH");
- if (!path) {
- path = "/hugetlbfs";
- }
-
if (access(path, R_OK | W_OK | X_OK)) {
g_test_message("access on path (%s): %s\n", path, strerror(errno));
return NULL;
@@ -366,44 +360,294 @@ static const char *init_hugepagefs(void)
return path;
}
+static TestServer *test_server_new(const gchar *name)
+{
+ TestServer *server = g_new0(TestServer, 1);
+ gchar *chr_path;
+
+ server->socket_path = g_strdup_printf("%s/%s.sock", tmpfs, name);
+ server->mig_path = g_strdup_printf("%s/%s.mig", tmpfs, name);
+
+ chr_path = g_strdup_printf("unix:%s,server,nowait", server->socket_path);
+ server->chr_name = g_strdup_printf("chr-%s", name);
+ server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
+ g_free(chr_path);
+
+ qemu_chr_add_handlers(server->chr, chr_can_read, chr_read, NULL, server);
+
+ g_mutex_init(&server->data_mutex);
+ g_cond_init(&server->data_cond);
+
+ server->log_fd = -1;
+
+ return server;
+}
+
+#define GET_QEMU_CMD(s) \
+ g_strdup_printf(QEMU_CMD, 512, 512, (root), (s)->chr_name, \
+ (s)->socket_path, (s)->chr_name)
+
+#define GET_QEMU_CMDE(s, mem, extra, ...) \
+ g_strdup_printf(QEMU_CMD extra, (mem), (mem), (root), (s)->chr_name, \
+ (s)->socket_path, (s)->chr_name, ##__VA_ARGS__)
+
+static gboolean _test_server_free(TestServer *server)
+{
+ int i;
+
+ qemu_chr_delete(server->chr);
+
+ for (i = 0; i < server->fds_num; i++) {
+ close(server->fds[i]);
+ }
+
+ if (server->log_fd != -1) {
+ close(server->log_fd);
+ }
+
+ unlink(server->socket_path);
+ g_free(server->socket_path);
+
+ unlink(server->mig_path);
+ g_free(server->mig_path);
+
+ g_free(server->chr_name);
+ g_free(server);
+
+ return FALSE;
+}
+
+static void test_server_free(TestServer *server)
+{
+ g_idle_add((GSourceFunc)_test_server_free, server);
+}
+
+static void wait_for_log_fd(TestServer *s)
+{
+ gint64 end_time;
+
+ g_mutex_lock(&s->data_mutex);
+ end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
+ while (s->log_fd == -1) {
+ if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
+ /* timeout has passed */
+ g_assert(s->log_fd != -1);
+ break;
+ }
+ }
+
+ g_mutex_unlock(&s->data_mutex);
+}
+
+static void write_guest_mem(TestServer *s, uint32_t seed)
+{
+ uint32_t *guest_mem;
+ int i, j;
+ size_t size;
+
+ wait_for_fds(s);
+
+ /* iterate all regions */
+ for (i = 0; i < s->fds_num; i++) {
+
+ /* We'll write only the region statring at 0x0 */
+ if (s->memory.regions[i].guest_phys_addr != 0x0) {
+ continue;
+ }
+
+ g_assert_cmpint(s->memory.regions[i].memory_size, >, 1024);
+
+ size = s->memory.regions[i].memory_size +
+ s->memory.regions[i].mmap_offset;
+
+ guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, s->fds[i], 0);
+
+ g_assert(guest_mem != MAP_FAILED);
+ guest_mem += (s->memory.regions[i].mmap_offset / sizeof(*guest_mem));
+
+ for (j = 0; j < 256; j++) {
+ guest_mem[j] = seed + j;
+ }
+
+ munmap(guest_mem, s->memory.regions[i].memory_size);
+ break;
+ }
+}
+
+static guint64 get_log_size(TestServer *s)
+{
+ guint64 log_size = 0;
+ int i;
+
+ for (i = 0; i < s->memory.nregions; ++i) {
+ VhostUserMemoryRegion *reg = &s->memory.regions[i];
+ guint64 last = range_get_last(reg->guest_phys_addr,
+ reg->memory_size);
+ log_size = MAX(log_size, last / (8 * VHOST_LOG_PAGE) + 1);
+ }
+
+ return log_size;
+}
+
+typedef struct TestMigrateSource {
+ GSource source;
+ TestServer *src;
+ TestServer *dest;
+} TestMigrateSource;
+
+static gboolean
+test_migrate_source_check(GSource *source)
+{
+ TestMigrateSource *t = (TestMigrateSource *)source;
+ gboolean overlap = t->src->rings && t->dest->rings;
+
+ g_assert(!overlap);
+
+ return FALSE;
+}
+
+#if !GLIB_CHECK_VERSION(2,36,0)
+/* this callback is unnecessary with glib >2.36, the default
+ * prepare for the source does the same */
+static gboolean
+test_migrate_source_prepare(GSource *source, gint *timeout)
+{
+ *timeout = -1;
+ return FALSE;
+}
+#endif
+
+GSourceFuncs test_migrate_source_funcs = {
+#if !GLIB_CHECK_VERSION(2,36,0)
+ .prepare = test_migrate_source_prepare,
+#endif
+ .check = test_migrate_source_check,
+};
+
+static void test_migrate(void)
+{
+ TestServer *s = test_server_new("src");
+ TestServer *dest = test_server_new("dest");
+ char *uri = g_strdup_printf("%s%s", "unix:", dest->mig_path);
+ QTestState *global = global_qtest, *from, *to;
+ GSource *source;
+ gchar *cmd;
+ QDict *rsp;
+ guint8 *log;
+ guint64 size;
+
+ cmd = GET_QEMU_CMDE(s, 2, "");
+ from = qtest_start(cmd);
+ g_free(cmd);
+
+ wait_for_fds(s);
+ size = get_log_size(s);
+ g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
+
+ cmd = GET_QEMU_CMDE(dest, 2, " -incoming %s", uri);
+ to = qtest_init(cmd);
+ g_free(cmd);
+
+ source = g_source_new(&test_migrate_source_funcs,
+ sizeof(TestMigrateSource));
+ ((TestMigrateSource *)source)->src = s;
+ ((TestMigrateSource *)source)->dest = dest;
+ g_source_attach(source, NULL);
+
+ /* slow down migration to have time to fiddle with log */
+ /* TODO: qtest could learn to break on some places */
+ rsp = qmp("{ 'execute': 'migrate_set_speed',"
+ "'arguments': { 'value': 10 } }");
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+
+ cmd = g_strdup_printf("{ 'execute': 'migrate',"
+ "'arguments': { 'uri': '%s' } }",
+ uri);
+ rsp = qmp(cmd);
+ g_free(cmd);
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+
+ wait_for_log_fd(s);
+
+ log = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, s->log_fd, 0);
+ g_assert(log != MAP_FAILED);
+
+ /* modify first page */
+ write_guest_mem(s, 0x42);
+ log[0] = 1;
+ munmap(log, size);
+
+ /* speed things up */
+ rsp = qmp("{ 'execute': 'migrate_set_speed',"
+ "'arguments': { 'value': 0 } }");
+ g_assert(qdict_haskey(rsp, "return"));
+ QDECREF(rsp);
+
+ qmp_eventwait("STOP");
+
+ global_qtest = to;
+ qmp_eventwait("RESUME");
+
+ read_guest_mem(dest);
+
+ g_source_destroy(source);
+ g_source_unref(source);
+
+ qtest_quit(to);
+ test_server_free(dest);
+ qtest_quit(from);
+ test_server_free(s);
+ g_free(uri);
+
+ global_qtest = global;
+}
+
int main(int argc, char **argv)
{
QTestState *s = NULL;
- CharDriverState *chr = NULL;
- const char *hugefs = 0;
- char *socket_path = 0;
- char *qemu_cmd = 0;
- char *chr_path = 0;
+ TestServer *server = NULL;
+ const char *hugefs;
+ char *qemu_cmd = NULL;
int ret;
+ char template[] = "/tmp/vhost-test-XXXXXX";
+ GMainLoop *loop;
+ GThread *thread;
g_test_init(&argc, &argv, NULL);
module_call_init(MODULE_INIT_QOM);
+ qemu_add_opts(&qemu_chardev_opts);
- hugefs = init_hugepagefs();
- if (!hugefs) {
- return 0;
+ tmpfs = mkdtemp(template);
+ if (!tmpfs) {
+ g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
+ }
+ g_assert(tmpfs);
+
+ hugefs = getenv("QTEST_HUGETLBFS_PATH");
+ if (hugefs) {
+ root = init_hugepagefs(hugefs);
+ g_assert(root);
+ } else {
+ root = tmpfs;
}
- socket_path = g_strdup_printf("/tmp/vhost-%d.sock", getpid());
-
- /* create char dev and add read handlers */
- qemu_add_opts(&qemu_chardev_opts);
- chr_path = g_strdup_printf("unix:%s,server,nowait", socket_path);
- chr = qemu_chr_new("chr0", chr_path, NULL);
- g_free(chr_path);
- qemu_chr_add_handlers(chr, chr_can_read, chr_read, NULL, chr);
+ server = test_server_new("test");
+ loop = g_main_loop_new(NULL, FALSE);
/* run the main loop thread so the chardev may operate */
- data_mutex = _mutex_new();
- data_cond = _cond_new();
- _thread_new(NULL, thread_function, NULL);
+ thread = g_thread_new(NULL, thread_function, loop);
+
+ qemu_cmd = GET_QEMU_CMD(server);
- qemu_cmd = g_strdup_printf(QEMU_CMD, hugefs, socket_path);
s = qtest_start(qemu_cmd);
g_free(qemu_cmd);
- qtest_add_func("/vhost-user/read-guest-mem", read_guest_mem);
+ qtest_add_data_func("/vhost-user/read-guest-mem", server, read_guest_mem);
+ qtest_add_func("/vhost-user/migrate", test_migrate);
ret = g_test_run();
@@ -412,10 +656,22 @@ int main(int argc, char **argv)
}
/* cleanup */
- unlink(socket_path);
- g_free(socket_path);
- _cond_free(data_cond);
- _mutex_free(data_mutex);
+ test_server_free(server);
+
+ /* finish the helper thread and dispatch pending sources */
+ g_main_loop_quit(loop);
+ g_thread_join(thread);
+ while (g_main_context_pending(NULL)) {
+ g_main_context_iteration (NULL, TRUE);
+ }
+ g_main_loop_unref(loop);
+
+ ret = rmdir(tmpfs);
+ if (ret != 0) {
+ g_test_message("unable to rmdir: path (%s): %s\n",
+ tmpfs, strerror(errno));
+ }
+ g_assert_cmpint(ret, ==, 0);
return ret;
}
diff --git a/qemu/tests/virtio-9p-test.c b/qemu/tests/virtio-9p-test.c
index 1fae47797..59d0f1fa9 100644
--- a/qemu/tests/virtio-9p-test.c
+++ b/qemu/tests/virtio-9p-test.c
@@ -7,12 +7,10 @@
* See the COPYING file in the top-level directory.
*/
-#include <stdlib.h>
-#include <string.h>
+#include "qemu/osdep.h"
#include <glib.h>
#include "libqtest.h"
#include "qemu-common.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void pci_nop(void)
diff --git a/qemu/tests/virtio-balloon-test.c b/qemu/tests/virtio-balloon-test.c
index becebb51a..b010ce98e 100644
--- a/qemu/tests/virtio-balloon-test.c
+++ b/qemu/tests/virtio-balloon-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void pci_nop(void)
diff --git a/qemu/tests/virtio-blk-test.c b/qemu/tests/virtio-blk-test.c
index 4078321a2..3a66630d7 100644
--- a/qemu/tests/virtio-blk-test.c
+++ b/qemu/tests/virtio-blk-test.c
@@ -8,11 +8,8 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
#include "libqtest.h"
#include "libqos/virtio.h"
#include "libqos/virtio-pci.h"
diff --git a/qemu/tests/virtio-console-test.c b/qemu/tests/virtio-console-test.c
index 6be96e8c6..0b9c2a55e 100644
--- a/qemu/tests/virtio-console-test.c
+++ b/qemu/tests/virtio-console-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void console_pci_nop(void)
diff --git a/qemu/tests/virtio-net-test.c b/qemu/tests/virtio-net-test.c
index ea7478c27..04cfcd594 100644
--- a/qemu/tests/virtio-net-test.c
+++ b/qemu/tests/virtio-net-test.c
@@ -7,23 +7,244 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
-#include "libqos/pci.h"
+#include "qemu-common.h"
+#include "qemu/sockets.h"
+#include "qemu/iov.h"
+#include "libqos/pci-pc.h"
+#include "libqos/virtio.h"
+#include "libqos/virtio-pci.h"
+#include "libqos/malloc.h"
+#include "libqos/malloc-pc.h"
+#include "libqos/malloc-generic.h"
+#include "qemu/bswap.h"
+#include "hw/virtio/virtio-net.h"
#define PCI_SLOT_HP 0x06
+#define PCI_SLOT 0x04
+#define PCI_FN 0x00
+
+#define QVIRTIO_NET_TIMEOUT_US (30 * 1000 * 1000)
+#define VNET_HDR_SIZE sizeof(struct virtio_net_hdr_mrg_rxbuf)
+
+static void test_end(void)
+{
+ qtest_end();
+}
+
+#ifndef _WIN32
+
+static QVirtioPCIDevice *virtio_net_pci_init(QPCIBus *bus, int slot)
+{
+ QVirtioPCIDevice *dev;
+
+ dev = qvirtio_pci_device_find(bus, QVIRTIO_NET_DEVICE_ID);
+ g_assert(dev != NULL);
+ g_assert_cmphex(dev->vdev.device_type, ==, QVIRTIO_NET_DEVICE_ID);
+
+ qvirtio_pci_device_enable(dev);
+ qvirtio_reset(&qvirtio_pci, &dev->vdev);
+ qvirtio_set_acknowledge(&qvirtio_pci, &dev->vdev);
+ qvirtio_set_driver(&qvirtio_pci, &dev->vdev);
+
+ return dev;
+}
+
+static QPCIBus *pci_test_start(int socket)
+{
+ char *cmdline;
+
+ cmdline = g_strdup_printf("-netdev socket,fd=%d,id=hs0 -device "
+ "virtio-net-pci,netdev=hs0", socket);
+ qtest_start(cmdline);
+ g_free(cmdline);
+
+ return qpci_init_pc();
+}
+
+static void driver_init(const QVirtioBus *bus, QVirtioDevice *dev)
+{
+ uint32_t features;
+
+ features = qvirtio_get_features(bus, dev);
+ features = features & ~(QVIRTIO_F_BAD_FEATURE |
+ QVIRTIO_F_RING_INDIRECT_DESC |
+ QVIRTIO_F_RING_EVENT_IDX);
+ qvirtio_set_features(bus, dev, features);
+
+ qvirtio_set_driver_ok(bus, dev);
+}
+
+static void rx_test(const QVirtioBus *bus, QVirtioDevice *dev,
+ QGuestAllocator *alloc, QVirtQueue *vq,
+ int socket)
+{
+ uint64_t req_addr;
+ uint32_t free_head;
+ char test[] = "TEST";
+ char buffer[64];
+ int len = htonl(sizeof(test));
+ struct iovec iov[] = {
+ {
+ .iov_base = &len,
+ .iov_len = sizeof(len),
+ }, {
+ .iov_base = test,
+ .iov_len = sizeof(test),
+ },
+ };
+ int ret;
+
+ req_addr = guest_alloc(alloc, 64);
+
+ free_head = qvirtqueue_add(vq, req_addr, 64, true, false);
+ qvirtqueue_kick(bus, dev, vq, free_head);
+
+ ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test));
+ g_assert_cmpint(ret, ==, sizeof(test) + sizeof(len));
+
+ qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_NET_TIMEOUT_US);
+ memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
+ g_assert_cmpstr(buffer, ==, "TEST");
+
+ guest_free(alloc, req_addr);
+}
+
+static void tx_test(const QVirtioBus *bus, QVirtioDevice *dev,
+ QGuestAllocator *alloc, QVirtQueue *vq,
+ int socket)
+{
+ uint64_t req_addr;
+ uint32_t free_head;
+ uint32_t len;
+ char buffer[64];
+ int ret;
+
+ req_addr = guest_alloc(alloc, 64);
+ memwrite(req_addr + VNET_HDR_SIZE, "TEST", 4);
+
+ free_head = qvirtqueue_add(vq, req_addr, 64, false, false);
+ qvirtqueue_kick(bus, dev, vq, free_head);
+
+ qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_NET_TIMEOUT_US);
+ guest_free(alloc, req_addr);
+
+ ret = qemu_recv(socket, &len, sizeof(len), 0);
+ g_assert_cmpint(ret, ==, sizeof(len));
+ len = ntohl(len);
+
+ ret = qemu_recv(socket, buffer, len, 0);
+ g_assert_cmpstr(buffer, ==, "TEST");
+}
+
+static void rx_stop_cont_test(const QVirtioBus *bus, QVirtioDevice *dev,
+ QGuestAllocator *alloc, QVirtQueue *vq,
+ int socket)
+{
+ uint64_t req_addr;
+ uint32_t free_head;
+ char test[] = "TEST";
+ char buffer[64];
+ int len = htonl(sizeof(test));
+ struct iovec iov[] = {
+ {
+ .iov_base = &len,
+ .iov_len = sizeof(len),
+ }, {
+ .iov_base = test,
+ .iov_len = sizeof(test),
+ },
+ };
+ int ret;
+
+ req_addr = guest_alloc(alloc, 64);
+
+ free_head = qvirtqueue_add(vq, req_addr, 64, true, false);
+ qvirtqueue_kick(bus, dev, vq, free_head);
+
+ qmp("{ 'execute' : 'stop'}");
+
+ ret = iov_send(socket, iov, 2, 0, sizeof(len) + sizeof(test));
+ g_assert_cmpint(ret, ==, sizeof(test) + sizeof(len));
+
+ /* We could check the status, but this command is more importantly to
+ * ensure the packet data gets queued in QEMU, before we do 'cont'.
+ */
+ qmp("{ 'execute' : 'query-status'}");
+ qmp("{ 'execute' : 'cont'}");
+
+ qvirtio_wait_queue_isr(bus, dev, vq, QVIRTIO_NET_TIMEOUT_US);
+ memread(req_addr + VNET_HDR_SIZE, buffer, sizeof(test));
+ g_assert_cmpstr(buffer, ==, "TEST");
+
+ guest_free(alloc, req_addr);
+}
-/* Tests only initialization so far. TODO: Replace with functional tests */
-static void pci_nop(void)
+static void send_recv_test(const QVirtioBus *bus, QVirtioDevice *dev,
+ QGuestAllocator *alloc, QVirtQueue *rvq,
+ QVirtQueue *tvq, int socket)
{
+ rx_test(bus, dev, alloc, rvq, socket);
+ tx_test(bus, dev, alloc, tvq, socket);
}
+static void stop_cont_test(const QVirtioBus *bus, QVirtioDevice *dev,
+ QGuestAllocator *alloc, QVirtQueue *rvq,
+ QVirtQueue *tvq, int socket)
+{
+ rx_stop_cont_test(bus, dev, alloc, rvq, socket);
+}
+
+static void pci_basic(gconstpointer data)
+{
+ QVirtioPCIDevice *dev;
+ QPCIBus *bus;
+ QVirtQueuePCI *tx, *rx;
+ QGuestAllocator *alloc;
+ void (*func) (const QVirtioBus *bus,
+ QVirtioDevice *dev,
+ QGuestAllocator *alloc,
+ QVirtQueue *rvq,
+ QVirtQueue *tvq,
+ int socket) = data;
+ int sv[2], ret;
+
+ ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv);
+ g_assert_cmpint(ret, !=, -1);
+
+ bus = pci_test_start(sv[1]);
+ dev = virtio_net_pci_init(bus, PCI_SLOT);
+
+ alloc = pc_alloc_init();
+ rx = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
+ alloc, 0);
+ tx = (QVirtQueuePCI *)qvirtqueue_setup(&qvirtio_pci, &dev->vdev,
+ alloc, 1);
+
+ driver_init(&qvirtio_pci, &dev->vdev);
+ func(&qvirtio_pci, &dev->vdev, alloc, &rx->vq, &tx->vq, sv[0]);
+
+ /* End test */
+ close(sv[0]);
+ guest_free(alloc, tx->vq.desc);
+ pc_alloc_uninit(alloc);
+ qvirtio_pci_device_disable(dev);
+ g_free(dev);
+ qpci_free_pc(bus);
+ test_end();
+}
+#endif
+
static void hotplug(void)
{
+ qtest_start("-device virtio-net-pci");
+
qpci_plug_device_test("virtio-net-pci", "net1", PCI_SLOT_HP, NULL);
qpci_unplug_acpi_device_test("net1", PCI_SLOT_HP);
+
+ test_end();
}
int main(int argc, char **argv)
@@ -31,13 +252,14 @@ int main(int argc, char **argv)
int ret;
g_test_init(&argc, &argv, NULL);
- qtest_add_func("/virtio/net/pci/nop", pci_nop);
+#ifndef _WIN32
+ qtest_add_data_func("/virtio/net/pci/basic", send_recv_test, pci_basic);
+ qtest_add_data_func("/virtio/net/pci/rx_stop_cont",
+ stop_cont_test, pci_basic);
+#endif
qtest_add_func("/virtio/net/pci/hotplug", hotplug);
- qtest_start("-device virtio-net-pci");
ret = g_test_run();
- qtest_end();
-
return ret;
}
diff --git a/qemu/tests/virtio-rng-test.c b/qemu/tests/virtio-rng-test.c
index 41c1cdb1a..771dbd73a 100644
--- a/qemu/tests/virtio-rng-test.c
+++ b/qemu/tests/virtio-rng-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
#include "libqos/pci.h"
#define PCI_SLOT_HP 0x06
diff --git a/qemu/tests/virtio-scsi-test.c b/qemu/tests/virtio-scsi-test.c
index 11ccdd632..d78747a46 100644
--- a/qemu/tests/virtio-scsi-test.c
+++ b/qemu/tests/virtio-scsi-test.c
@@ -8,11 +8,10 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
-#include <stdio.h>
+#include "block/scsi.h"
#include "libqos/virtio.h"
#include "libqos/virtio-pci.h"
#include "libqos/pci-pc.h"
@@ -71,40 +70,6 @@ static void qvirtio_scsi_stop(void)
qtest_end();
}
-static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
-{
- QVirtIOSCSI *vs;
- QVirtioPCIDevice *dev;
- void *addr;
- int i;
-
- vs = g_new0(QVirtIOSCSI, 1);
- vs->alloc = pc_alloc_init();
- vs->bus = qpci_init_pc();
-
- dev = qvirtio_pci_device_find(vs->bus, QVIRTIO_SCSI_DEVICE_ID);
- vs->dev = (QVirtioDevice *)dev;
- g_assert(dev != NULL);
- g_assert_cmphex(vs->dev->device_type, ==, QVIRTIO_SCSI_DEVICE_ID);
-
- qvirtio_pci_device_enable(dev);
- qvirtio_reset(&qvirtio_pci, vs->dev);
- qvirtio_set_acknowledge(&qvirtio_pci, vs->dev);
- qvirtio_set_driver(&qvirtio_pci, vs->dev);
-
- addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
- vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev,
- (uint64_t)(uintptr_t)addr);
-
- g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES);
-
- for (i = 0; i < vs->num_queues + 2; i++) {
- vs->vq[i] = qvirtqueue_setup(&qvirtio_pci, vs->dev, vs->alloc, i);
- }
-
- return vs;
-}
-
static void qvirtio_scsi_pci_free(QVirtIOSCSI *vs)
{
int i;
@@ -134,7 +99,8 @@ static uint64_t qvirtio_scsi_alloc(QVirtIOSCSI *vs, size_t alloc_size,
static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
const uint8_t *data_in,
size_t data_in_len,
- uint8_t *data_out, size_t data_out_len)
+ uint8_t *data_out, size_t data_out_len,
+ QVirtIOSCSICmdResp *resp_out)
{
QVirtQueue *vq;
QVirtIOSCSICmdReq req = { { 0 } };
@@ -174,6 +140,10 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
response = readb(resp_addr + offsetof(QVirtIOSCSICmdResp, response));
+ if (resp_out) {
+ memread(resp_addr, resp_out, sizeof(*resp_out));
+ }
+
guest_free(vs->alloc, req_addr);
guest_free(vs->alloc, resp_addr);
guest_free(vs->alloc, data_in_addr);
@@ -181,6 +151,52 @@ static uint8_t virtio_scsi_do_command(QVirtIOSCSI *vs, const uint8_t *cdb,
return response;
}
+static QVirtIOSCSI *qvirtio_scsi_pci_init(int slot)
+{
+ const uint8_t test_unit_ready_cdb[CDB_SIZE] = {};
+ QVirtIOSCSI *vs;
+ QVirtioPCIDevice *dev;
+ QVirtIOSCSICmdResp resp;
+ void *addr;
+ int i;
+
+ vs = g_new0(QVirtIOSCSI, 1);
+ vs->alloc = pc_alloc_init();
+ vs->bus = qpci_init_pc();
+
+ dev = qvirtio_pci_device_find(vs->bus, QVIRTIO_SCSI_DEVICE_ID);
+ vs->dev = (QVirtioDevice *)dev;
+ g_assert(dev != NULL);
+ g_assert_cmphex(vs->dev->device_type, ==, QVIRTIO_SCSI_DEVICE_ID);
+
+ qvirtio_pci_device_enable(dev);
+ qvirtio_reset(&qvirtio_pci, vs->dev);
+ qvirtio_set_acknowledge(&qvirtio_pci, vs->dev);
+ qvirtio_set_driver(&qvirtio_pci, vs->dev);
+
+ addr = dev->addr + QVIRTIO_PCI_DEVICE_SPECIFIC_NO_MSIX;
+ vs->num_queues = qvirtio_config_readl(&qvirtio_pci, vs->dev,
+ (uint64_t)(uintptr_t)addr);
+
+ g_assert_cmpint(vs->num_queues, <, MAX_NUM_QUEUES);
+
+ for (i = 0; i < vs->num_queues + 2; i++) {
+ vs->vq[i] = qvirtqueue_setup(&qvirtio_pci, vs->dev, vs->alloc, i);
+ }
+
+ /* Clear the POWER ON OCCURRED unit attention */
+ g_assert_cmpint(virtio_scsi_do_command(vs, test_unit_ready_cdb,
+ NULL, 0, NULL, 0, &resp),
+ ==, 0);
+ g_assert_cmpint(resp.status, ==, CHECK_CONDITION);
+ g_assert_cmpint(resp.sense[0], ==, 0x70); /* Fixed format sense buffer */
+ g_assert_cmpint(resp.sense[2], ==, UNIT_ATTENTION);
+ g_assert_cmpint(resp.sense[12], ==, 0x29); /* POWER ON */
+ g_assert_cmpint(resp.sense[13], ==, 0x00);
+
+ return vs;
+}
+
/* Tests only initialization so far. TODO: Replace with functional tests */
static void pci_nop(void)
{
@@ -221,9 +237,12 @@ static void hotplug(void)
static void test_unaligned_write_same(void)
{
QVirtIOSCSI *vs;
- uint8_t buf[512] = { 0 };
- const uint8_t write_same_cdb[CDB_SIZE] = { 0x41, 0x00, 0x00, 0x00, 0x00,
+ uint8_t buf1[512] = { 0 };
+ uint8_t buf2[512] = { 1 };
+ const uint8_t write_same_cdb_1[CDB_SIZE] = { 0x41, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x02, 0x00 };
+ const uint8_t write_same_cdb_2[CDB_SIZE] = { 0x41, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x33, 0x00, 0x00 };
qvirtio_scsi_start("-drive file=blkdebug::null-co://,if=none,id=dr1"
",format=raw,file.align=4k "
@@ -231,7 +250,10 @@ static void test_unaligned_write_same(void)
vs = qvirtio_scsi_pci_init(PCI_SLOT);
g_assert_cmphex(0, ==,
- virtio_scsi_do_command(vs, write_same_cdb, NULL, 0, buf, 512));
+ virtio_scsi_do_command(vs, write_same_cdb_1, NULL, 0, buf1, 512, NULL));
+
+ g_assert_cmphex(0, ==,
+ virtio_scsi_do_command(vs, write_same_cdb_2, NULL, 0, buf2, 512, NULL));
qvirtio_scsi_pci_free(vs);
qvirtio_scsi_stop();
diff --git a/qemu/tests/virtio-serial-test.c b/qemu/tests/virtio-serial-test.c
index bf030a616..480d4abb2 100644
--- a/qemu/tests/virtio-serial-test.c
+++ b/qemu/tests/virtio-serial-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void pci_nop(void)
diff --git a/qemu/tests/vmxnet3-test.c b/qemu/tests/vmxnet3-test.c
index a2ebed39c..6ef0e2f04 100644
--- a/qemu/tests/vmxnet3-test.c
+++ b/qemu/tests/vmxnet3-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
static void nop(void)
diff --git a/qemu/tests/wdt_ib700-test.c b/qemu/tests/wdt_ib700-test.c
index 82ca59725..efe337045 100644
--- a/qemu/tests/wdt_ib700-test.c
+++ b/qemu/tests/wdt_ib700-test.c
@@ -7,10 +7,9 @@
* See the COPYING file in the top-level directory.
*/
+#include "qemu/osdep.h"
#include <glib.h>
-#include <string.h>
#include "libqtest.h"
-#include "qemu/osdep.h"
#include "qemu/timer.h"
static void qmp_check_no_event(void)