summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-09-05 20:35:53 +0900
committerChanho Park <chanho61.park@samsung.com>2014-09-05 20:35:53 +0900
commit16b1353a36171ae06d63fd309f4772dbfb1da113 (patch)
treecf6c297ee81aba0d9b47f23d78a889667e7bce48 /tests
parenta15119db2ff5c2fdfdeb913b297bf8aa3399132e (diff)
downloadqemu-16b1353a36171ae06d63fd309f4772dbfb1da113.tar.gz
qemu-16b1353a36171ae06d63fd309f4772dbfb1da113.tar.bz2
qemu-16b1353a36171ae06d63fd309f4772dbfb1da113.zip
Imported Upstream version 2.1.0upstream/2.1.0
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore12
-rw-r--r--tests/Makefile82
-rw-r--r--tests/ac97-test.c33
-rw-r--r--tests/acpi-test-data/pc/DSDTbin4480 -> 2807 bytes
-rw-r--r--tests/acpi-test-data/pc/SSDTbin2269 -> 3065 bytes
-rw-r--r--tests/acpi-test-data/q35/DSDTbin7378 -> 7397 bytes
-rw-r--r--tests/acpi-test-data/q35/SSDTbin550 -> 1346 bytes
-rw-r--r--tests/bios-tables-test.c (renamed from tests/acpi-test.c)132
-rw-r--r--tests/check-qdict.c87
-rw-r--r--tests/check-qjson.c7
-rw-r--r--tests/display-vga-test.c52
-rw-r--r--tests/e1000-test.c33
-rw-r--r--tests/es1370-test.c33
-rw-r--r--tests/fdc-test.c4
-rw-r--r--tests/intel-hda-test.c45
-rw-r--r--tests/ioh3420-test.c34
-rw-r--r--tests/libqos/pci-pc.c12
-rw-r--r--tests/libqos/pci.c2
-rw-r--r--tests/libqtest.c55
-rw-r--r--tests/qapi-schema/duplicate-key.err2
-rw-r--r--tests/qapi-schema/event-nest-struct.err1
-rw-r--r--tests/qapi-schema/event-nest-struct.exit1
-rw-r--r--tests/qapi-schema/event-nest-struct.json2
-rw-r--r--tests/qapi-schema/event-nest-struct.out0
-rw-r--r--tests/qapi-schema/flat-union-invalid-branch-key.err2
-rw-r--r--tests/qapi-schema/flat-union-invalid-discriminator.err2
-rw-r--r--tests/qapi-schema/flat-union-no-base.err2
-rw-r--r--tests/qapi-schema/flat-union-string-discriminator.err2
-rw-r--r--tests/qapi-schema/funny-char.err2
-rw-r--r--tests/qapi-schema/include-before-err.err1
-rw-r--r--tests/qapi-schema/include-before-err.exit1
-rw-r--r--tests/qapi-schema/include-before-err.json2
-rw-r--r--tests/qapi-schema/include-before-err.out0
-rw-r--r--tests/qapi-schema/include-cycle-b.json1
-rw-r--r--tests/qapi-schema/include-cycle-c.json1
-rw-r--r--tests/qapi-schema/include-cycle.err3
-rw-r--r--tests/qapi-schema/include-cycle.exit1
-rw-r--r--tests/qapi-schema/include-cycle.json1
-rw-r--r--tests/qapi-schema/include-cycle.out0
-rw-r--r--tests/qapi-schema/include-format-err.err1
-rw-r--r--tests/qapi-schema/include-format-err.exit1
-rw-r--r--tests/qapi-schema/include-format-err.json2
-rw-r--r--tests/qapi-schema/include-format-err.out0
-rw-r--r--tests/qapi-schema/include-nested-err.err2
-rw-r--r--tests/qapi-schema/include-nested-err.exit1
-rw-r--r--tests/qapi-schema/include-nested-err.json1
-rw-r--r--tests/qapi-schema/include-nested-err.out0
-rw-r--r--tests/qapi-schema/include-no-file.err1
-rw-r--r--tests/qapi-schema/include-no-file.exit1
-rw-r--r--tests/qapi-schema/include-no-file.json1
-rw-r--r--tests/qapi-schema/include-no-file.out0
-rw-r--r--tests/qapi-schema/include-non-file.err1
-rw-r--r--tests/qapi-schema/include-non-file.exit1
-rw-r--r--tests/qapi-schema/include-non-file.json1
-rw-r--r--tests/qapi-schema/include-non-file.out0
-rw-r--r--tests/qapi-schema/include-relpath-sub.json2
-rw-r--r--tests/qapi-schema/include-relpath.err0
-rw-r--r--tests/qapi-schema/include-relpath.exit1
-rw-r--r--tests/qapi-schema/include-relpath.json1
-rw-r--r--tests/qapi-schema/include-relpath.out3
-rw-r--r--tests/qapi-schema/include-repetition-sub.json2
-rw-r--r--tests/qapi-schema/include-repetition.err0
-rw-r--r--tests/qapi-schema/include-repetition.exit1
-rw-r--r--tests/qapi-schema/include-repetition.json3
-rw-r--r--tests/qapi-schema/include-repetition.out3
-rw-r--r--tests/qapi-schema/include-self-cycle.err1
-rw-r--r--tests/qapi-schema/include-self-cycle.exit1
-rw-r--r--tests/qapi-schema/include-self-cycle.json1
-rw-r--r--tests/qapi-schema/include-self-cycle.out0
-rw-r--r--tests/qapi-schema/include-simple-sub.json2
-rw-r--r--tests/qapi-schema/include-simple.err0
-rw-r--r--tests/qapi-schema/include-simple.exit1
-rw-r--r--tests/qapi-schema/include-simple.json1
-rw-r--r--tests/qapi-schema/include-simple.out3
-rw-r--r--tests/qapi-schema/include/relpath.json1
-rw-r--r--tests/qapi-schema/missing-colon.err2
-rw-r--r--tests/qapi-schema/missing-comma-list.err2
-rw-r--r--tests/qapi-schema/missing-comma-object.err2
-rw-r--r--tests/qapi-schema/non-objects.err2
-rw-r--r--tests/qapi-schema/qapi-schema-test.json12
-rw-r--r--tests/qapi-schema/qapi-schema-test.out10
-rw-r--r--tests/qapi-schema/quoted-structural-chars.err2
-rw-r--r--tests/qapi-schema/test-qapi.py6
-rw-r--r--tests/qapi-schema/trailing-comma-list.err2
-rw-r--r--tests/qapi-schema/trailing-comma-object.err2
-rw-r--r--tests/qapi-schema/unclosed-list.err2
-rw-r--r--tests/qapi-schema/unclosed-object.err2
-rw-r--r--tests/qapi-schema/unclosed-string.err2
-rw-r--r--tests/qapi-schema/union-invalid-base.err2
-rwxr-xr-xtests/qemu-iotests-quick.sh12
-rwxr-xr-xtests/qemu-iotests/0192
-rwxr-xr-xtests/qemu-iotests/02829
-rw-r--r--tests/qemu-iotests/028.out267
-rwxr-xr-xtests/qemu-iotests/03052
-rwxr-xr-xtests/qemu-iotests/0318
-rwxr-xr-xtests/qemu-iotests/03658
-rw-r--r--tests/qemu-iotests/036.out35
-rwxr-xr-xtests/qemu-iotests/03938
-rw-r--r--tests/qemu-iotests/039.out3
-rwxr-xr-xtests/qemu-iotests/04038
-rw-r--r--tests/qemu-iotests/040.out4
-rwxr-xr-xtests/qemu-iotests/041249
-rw-r--r--tests/qemu-iotests/041.out4
-rw-r--r--tests/qemu-iotests/049.out2
-rwxr-xr-xtests/qemu-iotests/05110
-rw-r--r--tests/qemu-iotests/051.out24
-rwxr-xr-xtests/qemu-iotests/0542
-rwxr-xr-xtests/qemu-iotests/0569
-rwxr-xr-xtests/qemu-iotests/0597
-rw-r--r--tests/qemu-iotests/059.out8
-rwxr-xr-xtests/qemu-iotests/06020
-rwxr-xr-xtests/qemu-iotests/06124
-rw-r--r--tests/qemu-iotests/061.out2
-rwxr-xr-xtests/qemu-iotests/0652
-rw-r--r--tests/qemu-iotests/067.out10
-rwxr-xr-xtests/qemu-iotests/0707
-rw-r--r--tests/qemu-iotests/070.out7
-rwxr-xr-xtests/qemu-iotests/08115
-rw-r--r--tests/qemu-iotests/081.out12
-rw-r--r--tests/qemu-iotests/082.out24
-rwxr-xr-xtests/qemu-iotests/08310
-rw-r--r--tests/qemu-iotests/084.out5
-rwxr-xr-xtests/qemu-iotests/08573
-rwxr-xr-xtests/qemu-iotests/0868
-rwxr-xr-xtests/qemu-iotests/08785
-rw-r--r--tests/qemu-iotests/087.out18
-rwxr-xr-xtests/qemu-iotests/089129
-rw-r--r--tests/qemu-iotests/089.out50
-rwxr-xr-xtests/qemu-iotests/09061
-rw-r--r--tests/qemu-iotests/090.out12
-rwxr-xr-xtests/qemu-iotests/091107
-rw-r--r--tests/qemu-iotests/091.out28
-rwxr-xr-xtests/qemu-iotests/09298
-rw-r--r--tests/qemu-iotests/092.out38
-rwxr-xr-xtests/qemu-iotests/09586
-rw-r--r--tests/qemu-iotests/095.out31
-rwxr-xr-xtests/qemu-iotests/check110
-rw-r--r--tests/qemu-iotests/common11
-rw-r--r--tests/qemu-iotests/common.config2
-rw-r--r--tests/qemu-iotests/common.filter1
-rw-r--r--tests/qemu-iotests/common.qemu200
-rw-r--r--tests/qemu-iotests/common.rc12
-rw-r--r--tests/qemu-iotests/group57
-rw-r--r--tests/qemu-iotests/iotests.py8
-rwxr-xr-xtests/qemu-iotests/qcow2.py15
-rw-r--r--tests/qemu-iotests/sample_images/test-disk2vhd.vhdx.bz2bin0 -> 1424 bytes
-rw-r--r--tests/qom-test.c21
-rw-r--r--tests/tcg/Makefile2
-rw-r--r--tests/tcg/lm32/Makefile15
-rw-r--r--tests/tcg/lm32/crt.S4
-rw-r--r--tests/tcg/lm32/helper.S65
-rw-r--r--tests/tcg/lm32/macros.inc37
-rw-r--r--tests/tcg/lm32/test_lb.S4
-rw-r--r--tests/tcg/lm32/test_lbu.S4
-rw-r--r--tests/tcg/lm32/test_lh.S4
-rw-r--r--tests/tcg/lm32/test_lhu.S4
-rw-r--r--tests/tcg/lm32/test_lw.S2
-rw-r--r--tests/tcg/lm32/test_sb.S2
-rw-r--r--tests/tcg/lm32/test_scall.S4
-rw-r--r--tests/tcg/lm32/test_sh.S2
-rw-r--r--tests/tcg/lm32/test_sw.S3
-rw-r--r--tests/tcg/test_path.c7
-rw-r--r--tests/tcg/xtensa/test_mmu.S246
-rw-r--r--tests/test-aio.c40
-rw-r--r--tests/test-qdev-global-props.c4
-rw-r--r--tests/test-qemu-opts.c441
-rw-r--r--tests/test-qmp-event.c271
-rw-r--r--tests/test-qmp-input-strict.c100
-rw-r--r--tests/test-qmp-input-visitor.c99
-rw-r--r--tests/test-qmp-output-visitor.c111
-rw-r--r--tests/test-string-input-visitor.c87
-rw-r--r--tests/test-string-output-visitor.c178
-rw-r--r--tests/test-thread-pool.c6
-rw-r--r--tests/test-throttle.c55
-rw-r--r--tests/test-visitor-serialization.c32
-rw-r--r--tests/test-vmstate.c314
-rw-r--r--tests/tmp105-test.c4
-rw-r--r--tests/usb-hcd-ehci-test.c185
-rw-r--r--tests/vhost-user-test.c421
-rw-r--r--tests/vmstate-static-checker-data/dump1.json1163
-rw-r--r--tests/vmstate-static-checker-data/dump2.json968
-rw-r--r--tests/wdt_ib700-test.c134
182 files changed, 7302 insertions, 717 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index 9ba9d96b6..c71c11020 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -7,20 +7,28 @@ check-qstring
check-qom-interface
test-aio
test-bitops
-test-throttle
+test-coroutine
test-cutils
test-hbitmap
test-int128
test-iov
test-mul64
+test-opts-visitor
test-qapi-types.[ch]
test-qapi-visit.[ch]
test-qdev-global-props
-test-qmp-commands.h
test-qmp-commands
+test-qmp-commands.h
test-qmp-input-strict
+test-qmp-input-visitor
test-qmp-marshal.c
+test-qmp-output-visitor
+test-rfifolock
+test-string-input-visitor
+test-string-output-visitor
test-thread-pool
+test-throttle
+test-visitor-serialization
test-vmstate
test-x86-cpuid
test-xbzrle
diff --git a/tests/Makefile b/tests/Makefile
index 88f7105d0..4b2e1bbea 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -27,6 +27,8 @@ check-unit-y += tests/test-string-input-visitor$(EXESUF)
gcov-files-test-string-input-visitor-y = qapi/string-input-visitor.c
check-unit-y += tests/test-string-output-visitor$(EXESUF)
gcov-files-test-string-output-visitor-y = qapi/string-output-visitor.c
+check-unit-y += tests/test-qmp-event$(EXESUF)
+gcov-files-test-qmp-event-y += qapi/qmp-event.c
check-unit-y += tests/test-opts-visitor$(EXESUF)
gcov-files-test-opts-visitor-y = qapi/opts-visitor.c
check-unit-y += tests/test-coroutine$(EXESUF)
@@ -60,6 +62,8 @@ check-unit-y += tests/test-qdev-global-props$(EXESUF)
check-unit-y += tests/check-qom-interface$(EXESUF)
gcov-files-check-qom-interface-y = qom/object.c
check-unit-$(CONFIG_POSIX) += tests/test-vmstate$(EXESUF)
+check-unit-y += tests/test-qemu-opts$(EXESUF)
+gcov-files-test-qemu-opts-y = qom/test-qemu-opts.c
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -107,12 +111,22 @@ check-qtest-pci-y += tests/ne2000-test$(EXESUF)
gcov-files-pci-y += hw/net/ne2000.c
check-qtest-pci-y += tests/nvme-test$(EXESUF)
gcov-files-pci-y += hw/block/nvme.c
+check-qtest-pci-y += tests/ac97-test$(EXESUF)
+gcov-files-pci-y += hw/audio/ac97.c
+check-qtest-pci-y += tests/es1370-test$(EXESUF)
+gcov-files-pci-y += hw/audio/es1370.c
check-qtest-pci-y += $(check-qtest-virtio-y)
gcov-files-pci-y += $(gcov-files-virtio-y) hw/virtio/virtio-pci.c
check-qtest-pci-y += tests/tpci200-test$(EXESUF)
gcov-files-pci-y += hw/ipack/tpci200.c
check-qtest-pci-y += $(check-qtest-ipack-y)
gcov-files-pci-y += $(gcov-files-ipack-y)
+check-qtest-pci-y += tests/display-vga-test$(EXESUF)
+gcov-files-pci-y += hw/display/vga.c
+gcov-files-pci-y += hw/display/cirrus_vga.c
+gcov-files-pci-y += hw/display/vga-pci.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-i386-y = tests/endianness-test$(EXESUF)
check-qtest-i386-y += tests/fdc-test$(EXESUF)
@@ -121,12 +135,14 @@ check-qtest-i386-y += tests/ide-test$(EXESUF)
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/acpi-test$(EXESUF)
+check-qtest-i386-y += tests/bios-tables-test$(EXESUF)
check-qtest-i386-y += tests/rtc-test$(EXESUF)
check-qtest-i386-y += tests/i440fx-test$(EXESUF)
check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
check-qtest-i386-y += tests/blockdev-test$(EXESUF)
check-qtest-i386-y += tests/qdev-monitor-test$(EXESUF)
+check-qtest-i386-y += tests/wdt_ib700-test$(EXESUF)
+gcov-files-i386-y += hw/watchdog/watchdog.c hw/watchdog/wdt_ib700.c
check-qtest-i386-y += $(check-qtest-pci-y)
gcov-files-i386-y += $(gcov-files-pci-y)
check-qtest-i386-y += tests/vmxnet3-test$(EXESUF)
@@ -137,6 +153,14 @@ check-qtest-i386-y += tests/pvpanic-test$(EXESUF)
gcov-files-i386-y += i386-softmmu/hw/misc/pvpanic.c
check-qtest-i386-y += tests/i82801b11-test$(EXESUF)
gcov-files-i386-y += hw/pci-bridge/i82801b11.c
+check-qtest-i386-y += tests/ioh3420-test$(EXESUF)
+gcov-files-i386-y += hw/pci-bridge/ioh3420.c
+check-qtest-i386-y += tests/usb-hcd-ehci-test$(EXESUF)
+gcov-files-i386-y += hw/usb/hcd-ehci.c
+gcov-files-i386-y += hw/usb/hcd-uhci.c
+gcov-files-i386-y += hw/usb/dev-hid.c
+gcov-files-i386-y += hw/usb/dev-storage.c
+check-qtest-i386-$(CONFIG_LINUX) += tests/vhost-user-test$(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))
@@ -175,9 +199,14 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
duplicate-key.json union-invalid-base.json flat-union-no-base.json \
flat-union-invalid-discriminator.json \
flat-union-invalid-branch-key.json flat-union-reverse-define.json \
- flat-union-string-discriminator.json)
+ flat-union-string-discriminator.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)
-GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h tests/test-qmp-commands.h
+GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h \
+ tests/test-qmp-commands.h tests/test-qapi-event.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 \
@@ -186,9 +215,10 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
tests/test-qmp-commands.o tests/test-visitor-serialization.o \
tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
- tests/test-opts-visitor.o
+ tests/test-opts-visitor.o tests/test-qmp-event.o
-test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.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
@@ -227,16 +257,28 @@ tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
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
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
+ $(gen-out-type) -o tests -p "test-" -i $<, \
+ " GEN $@")
tests/test-qapi-visit.c tests/test-qapi-visit.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
+ $(gen-out-type) -o tests -p "test-" -i $<, \
+ " GEN $@")
tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
- $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@")
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
+ $(gen-out-type) -o tests -p "test-" -i $<, \
+ " GEN $@")
+tests/test-qapi-event.c tests/test-qapi-event.h :\
+$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-event.py
+ $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
+ $(gen-out-type) -o tests -p "test-" -i $<, \
+ " 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
@@ -261,7 +303,7 @@ tests/fdc-test$(EXESUF): tests/fdc-test.o
tests/ide-test$(EXESUF): tests/ide-test.o $(libqos-pc-obj-y)
tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
-tests/acpi-test$(EXESUF): tests/acpi-test.o $(libqos-obj-y)
+tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o $(libqos-obj-y)
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
@@ -271,6 +313,7 @@ tests/pcnet-test$(EXESUF): tests/pcnet-test.o
tests/eepro100-test$(EXESUF): tests/eepro100-test.o
tests/vmxnet3-test$(EXESUF): tests/vmxnet3-test.o
tests/ne2000-test$(EXESUF): tests/ne2000-test.o
+tests/wdt_ib700-test$(EXESUF): tests/wdt_ib700-test.o
tests/virtio-balloon-test$(EXESUF): tests/virtio-balloon-test.o
tests/virtio-blk-test$(EXESUF): tests/virtio-blk-test.o
tests/virtio-net-test$(EXESUF): tests/virtio-net-test.o
@@ -280,6 +323,7 @@ tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o
tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o
tests/virtio-console-test$(EXESUF): tests/virtio-console-test.o
tests/tpci200-test$(EXESUF): tests/tpci200-test.o
+tests/display-vga-test$(EXESUF): tests/display-vga-test.o
tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o
tests/qom-test$(EXESUF): tests/qom-test.o
tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y)
@@ -287,7 +331,18 @@ tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y)
tests/nvme-test$(EXESUF): tests/nvme-test.o
tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o
tests/i82801b11-test$(EXESUF): tests/i82801b11-test.o
+tests/ac97-test$(EXESUF): tests/ac97-test.o
+tests/es1370-test$(EXESUF): tests/es1370-test.o
+tests/intel-hda-test$(EXESUF): tests/intel-hda-test.o
+tests/ioh3420-test$(EXESUF): tests/ioh3420-test.o
+tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-pc-obj-y)
+tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-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
+
+ifeq ($(CONFIG_POSIX),y)
+LIBS += -lutil
+endif
# QTest rules
@@ -379,9 +434,14 @@ check-tests/test-qapi.py: tests/test-qapi.py
.PHONY: $(patsubst %, check-%, $(check-qapi-schema-y))
$(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json
- $(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py <$^ >$*.test.out 2>$*.test.err; echo $$? >$*.test.exit, " TEST $*.out")
+ $(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts \
+ $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py \
+ $^ >$*.test.out 2>$*.test.err; \
+ echo $$? >$*.test.exit, \
+ " TEST $*.out")
@diff -q $(SRC_PATH)/$*.out $*.test.out
- @diff -q $(SRC_PATH)/$*.err $*.test.err
+ @# Sanitize error messages (make them independent of build directory)
+ @perl -p -e 's|\Q$(SRC_PATH)\E/||g' $*.test.err | diff -q $(SRC_PATH)/$*.err -
@diff -q $(SRC_PATH)/$*.exit $*.test.exit
# Consolidated targets
diff --git a/tests/ac97-test.c b/tests/ac97-test.c
new file mode 100644
index 000000000..af30ea1dd
--- /dev/null
+++ b/tests/ac97-test.c
@@ -0,0 +1,33 @@
+/*
+ * QTest testcase for AC97
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * 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 <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)
+{
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/ac97/nop", nop);
+
+ qtest_start("-device AC97");
+ ret = g_test_run();
+
+ qtest_end();
+
+ return ret;
+}
diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT
index d0bb3de79..d37ec3445 100644
--- a/tests/acpi-test-data/pc/DSDT
+++ b/tests/acpi-test-data/pc/DSDT
Binary files differ
diff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT
index c987fb237..eb2d8b698 100644
--- a/tests/acpi-test-data/pc/SSDT
+++ b/tests/acpi-test-data/pc/SSDT
Binary files differ
diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT
index fc5b97000..2d2bc4ada 100644
--- a/tests/acpi-test-data/q35/DSDT
+++ b/tests/acpi-test-data/q35/DSDT
Binary files differ
diff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT
index 919963875..778b79bf4 100644
--- a/tests/acpi-test-data/q35/SSDT
+++ b/tests/acpi-test-data/q35/SSDT
Binary files differ
diff --git a/tests/acpi-test.c b/tests/bios-tables-test.c
index 76fbccfa4..045eb2757 100644
--- a/tests/acpi-test.c
+++ b/tests/bios-tables-test.c
@@ -18,6 +18,8 @@
#include "libqtest.h"
#include "qemu/compiler.h"
#include "hw/i386/acpi-defs.h"
+#include "hw/i386/smbios.h"
+#include "qemu/bitmap.h"
#define MACHINE_PC "pc"
#define MACHINE_Q35 "q35"
@@ -46,6 +48,8 @@ typedef struct {
uint32_t *rsdt_tables_addr;
int rsdt_tables_nr;
GArray *tables;
+ uint32_t smbios_ep_addr;
+ struct smbios_entry_point smbios_ep_table;
} test_data;
#define LOW(x) ((x) & 0xff)
@@ -483,7 +487,11 @@ static GString *normalize_asl(gchar *asl_code)
/* strip comments (different generation days) */
comment = g_strstr_len(asl->str, asl->len, COMMENT_END);
if (comment) {
- asl = g_string_erase(asl, 0, comment + sizeof(COMMENT_END) - asl->str);
+ comment += strlen(COMMENT_END);
+ while (*comment == '\n') {
+ comment++;
+ }
+ asl = g_string_erase(asl, 0, comment - asl->str);
}
/* strip def block name (it has file path in it) */
@@ -581,6 +589,124 @@ static void test_acpi_asl(test_data *data)
free_test_data(&exp_data);
}
+static void test_smbios_ep_address(test_data *data)
+{
+ uint32_t off;
+
+ /* find smbios entry point structure */
+ for (off = 0xf0000; off < 0x100000; off += 0x10) {
+ uint8_t sig[] = "_SM_";
+ int i;
+
+ for (i = 0; i < sizeof sig - 1; ++i) {
+ sig[i] = readb(off + i);
+ }
+
+ if (!memcmp(sig, "_SM_", sizeof sig)) {
+ break;
+ }
+ }
+
+ g_assert_cmphex(off, <, 0x100000);
+ data->smbios_ep_addr = off;
+}
+
+static void test_smbios_ep_table(test_data *data)
+{
+ struct smbios_entry_point *ep_table = &data->smbios_ep_table;
+ uint32_t addr = data->smbios_ep_addr;
+
+ ACPI_READ_ARRAY(ep_table->anchor_string, addr);
+ g_assert(!memcmp(ep_table->anchor_string, "_SM_", 4));
+ ACPI_READ_FIELD(ep_table->checksum, addr);
+ ACPI_READ_FIELD(ep_table->length, addr);
+ ACPI_READ_FIELD(ep_table->smbios_major_version, addr);
+ ACPI_READ_FIELD(ep_table->smbios_minor_version, addr);
+ ACPI_READ_FIELD(ep_table->max_structure_size, addr);
+ ACPI_READ_FIELD(ep_table->entry_point_revision, addr);
+ ACPI_READ_ARRAY(ep_table->formatted_area, addr);
+ ACPI_READ_ARRAY(ep_table->intermediate_anchor_string, addr);
+ g_assert(!memcmp(ep_table->intermediate_anchor_string, "_DMI_", 5));
+ ACPI_READ_FIELD(ep_table->intermediate_checksum, addr);
+ ACPI_READ_FIELD(ep_table->structure_table_length, addr);
+ g_assert_cmpuint(ep_table->structure_table_length, >, 0);
+ ACPI_READ_FIELD(ep_table->structure_table_address, addr);
+ ACPI_READ_FIELD(ep_table->number_of_structures, addr);
+ g_assert_cmpuint(ep_table->number_of_structures, >, 0);
+ ACPI_READ_FIELD(ep_table->smbios_bcd_revision, addr);
+ g_assert(!acpi_checksum((uint8_t *)ep_table, sizeof *ep_table));
+ g_assert(!acpi_checksum((uint8_t *)ep_table + 0x10,
+ sizeof *ep_table - 0x10));
+}
+
+static inline bool smbios_single_instance(uint8_t type)
+{
+ switch (type) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 16:
+ case 32:
+ case 127:
+ return true;
+ default:
+ return false;
+ }
+}
+
+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;
+ uint32_t addr = ep_table->structure_table_address;
+ int i, len, max_len = 0;
+ uint8_t type, prv, crt;
+ uint8_t required_struct_types[] = {0, 1, 3, 4, 16, 17, 19, 32, 127};
+
+ /* walk the smbios tables */
+ for (i = 0; i < ep_table->number_of_structures; i++) {
+
+ /* grab type and formatted area length from struct header */
+ type = readb(addr);
+ g_assert_cmpuint(type, <=, SMBIOS_MAX_TYPE);
+ len = readb(addr + 1);
+
+ /* single-instance structs must not have been encountered before */
+ if (smbios_single_instance(type)) {
+ g_assert(!test_bit(type, struct_bitmap));
+ }
+ set_bit(type, struct_bitmap);
+
+ /* seek to end of unformatted string area of this struct ("\0\0") */
+ prv = crt = 1;
+ while (prv || crt) {
+ prv = crt;
+ crt = readb(addr + len);
+ len++;
+ }
+
+ /* keep track of max. struct size */
+ if (max_len < len) {
+ max_len = len;
+ g_assert_cmpuint(max_len, <=, ep_table->max_structure_size);
+ }
+
+ /* start of next structure */
+ addr += len;
+ }
+
+ /* total table length and max struct size must match entry point values */
+ g_assert_cmpuint(ep_table->structure_table_length, ==,
+ addr - ep_table->structure_table_address);
+ g_assert_cmpuint(ep_table->max_structure_size, ==, max_len);
+
+ /* required struct types must all be present */
+ for (i = 0; i < ARRAY_SIZE(required_struct_types); i++) {
+ g_assert(test_bit(required_struct_types[i], struct_bitmap));
+ }
+}
+
static void test_acpi_one(const char *params, test_data *data)
{
char *args;
@@ -633,6 +759,10 @@ static void test_acpi_one(const char *params, test_data *data)
}
}
+ test_smbios_ep_address(data);
+ test_smbios_ep_table(data);
+ test_smbios_structs(data);
+
qtest_quit(global_qtest);
g_free(args);
}
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index 2ad0f7827..a9296f083 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -444,6 +444,92 @@ static void qdict_array_split_test(void)
QDECREF(test_dict);
}
+static void qdict_join_test(void)
+{
+ QDict *dict1, *dict2;
+ bool overwrite = false;
+ int i;
+
+ dict1 = qdict_new();
+ dict2 = qdict_new();
+
+
+ /* Test everything once without overwrite and once with */
+ do
+ {
+ /* Test empty dicts */
+ qdict_join(dict1, dict2, overwrite);
+
+ g_assert(qdict_size(dict1) == 0);
+ g_assert(qdict_size(dict2) == 0);
+
+
+ /* First iteration: Test movement */
+ /* Second iteration: Test empty source and non-empty destination */
+ qdict_put(dict2, "foo", qint_from_int(42));
+
+ for (i = 0; i < 2; i++) {
+ qdict_join(dict1, dict2, overwrite);
+
+ g_assert(qdict_size(dict1) == 1);
+ g_assert(qdict_size(dict2) == 0);
+
+ g_assert(qdict_get_int(dict1, "foo") == 42);
+ }
+
+
+ /* Test non-empty source and destination without conflict */
+ qdict_put(dict2, "bar", qint_from_int(23));
+
+ qdict_join(dict1, dict2, overwrite);
+
+ g_assert(qdict_size(dict1) == 2);
+ g_assert(qdict_size(dict2) == 0);
+
+ g_assert(qdict_get_int(dict1, "foo") == 42);
+ g_assert(qdict_get_int(dict1, "bar") == 23);
+
+
+ /* Test conflict */
+ qdict_put(dict2, "foo", qint_from_int(84));
+
+ qdict_join(dict1, dict2, overwrite);
+
+ g_assert(qdict_size(dict1) == 2);
+ g_assert(qdict_size(dict2) == !overwrite);
+
+ g_assert(qdict_get_int(dict1, "foo") == overwrite ? 84 : 42);
+ g_assert(qdict_get_int(dict1, "bar") == 23);
+
+ if (!overwrite) {
+ g_assert(qdict_get_int(dict2, "foo") == 84);
+ }
+
+
+ /* Check the references */
+ g_assert(qdict_get(dict1, "foo")->refcnt == 1);
+ g_assert(qdict_get(dict1, "bar")->refcnt == 1);
+
+ if (!overwrite) {
+ g_assert(qdict_get(dict2, "foo")->refcnt == 1);
+ }
+
+
+ /* Clean up */
+ qdict_del(dict1, "foo");
+ qdict_del(dict1, "bar");
+
+ if (!overwrite) {
+ qdict_del(dict2, "foo");
+ }
+ }
+ while (overwrite ^= true);
+
+
+ QDECREF(dict1);
+ QDECREF(dict2);
+}
+
/*
* Errors test-cases
*/
@@ -584,6 +670,7 @@ int main(int argc, char **argv)
g_test_add_func("/public/iterapi", qdict_iterapi_test);
g_test_add_func("/public/flatten", qdict_flatten_test);
g_test_add_func("/public/array_split", qdict_array_split_test);
+ g_test_add_func("/public/join", qdict_join_test);
g_test_add_func("/errors/put_exists", qdict_put_exists_test);
g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 4e7454810..95497a037 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -45,6 +45,13 @@ static void escaped_string(void)
{ "\"single byte utf-8 \\u0020\"", "single byte utf-8 ", .skip = 1 },
{ "\"double byte utf-8 \\u00A2\"", "double byte utf-8 \xc2\xa2" },
{ "\"triple byte utf-8 \\u20AC\"", "triple byte utf-8 \xe2\x82\xac" },
+ { "'\\b'", "\b", .skip = 1 },
+ { "'\\f'", "\f", .skip = 1 },
+ { "'\\n'", "\n", .skip = 1 },
+ { "'\\r'", "\r", .skip = 1 },
+ { "'\\t'", "\t", .skip = 1 },
+ { "'\\/'", "/", .skip = 1 },
+ { "'\\\\'", "\\", .skip = 1 },
{}
};
diff --git a/tests/display-vga-test.c b/tests/display-vga-test.c
new file mode 100644
index 000000000..17f59101e
--- /dev/null
+++ b/tests/display-vga-test.c
@@ -0,0 +1,52 @@
+/*
+ * QTest testcase for vga cards
+ *
+ * Copyright (c) 2014 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 <glib.h>
+#include <string.h>
+#include "libqtest.h"
+#include "qemu/osdep.h"
+
+static void pci_cirrus(void)
+{
+ qtest_start("-vga none -device cirrus-vga");
+ qtest_end();
+}
+
+static void pci_stdvga(void)
+{
+ qtest_start("-vga none -device VGA");
+ qtest_end();
+}
+
+static void pci_secondary(void)
+{
+ qtest_start("-vga none -device secondary-vga");
+ qtest_end();
+}
+
+static void pci_multihead(void)
+{
+ qtest_start("-vga none -device VGA -device secondary-vga");
+ qtest_end();
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_func("/display/pci/cirrus", pci_cirrus);
+ qtest_add_func("/display/pci/stdvga", pci_stdvga);
+ qtest_add_func("/display/pci/secondary", pci_secondary);
+ qtest_add_func("/display/pci/multihead", pci_multihead);
+ ret = g_test_run();
+
+ return ret;
+}
diff --git a/tests/e1000-test.c b/tests/e1000-test.c
index a8ba2fc0a..81f164d9e 100644
--- a/tests/e1000-test.c
+++ b/tests/e1000-test.c
@@ -13,21 +13,40 @@
#include "qemu/osdep.h"
/* Tests only initialization so far. TODO: Replace with functional tests */
-static void nop(void)
+static void test_device(gconstpointer data)
{
+ const char *model = data;
+ QTestState *s;
+ char *args;
+
+ args = g_strdup_printf("-device %s", model);
+ s = qtest_start(args);
+
+ if (s) {
+ qtest_quit(s);
+ }
+ g_free(args);
}
+static const char *models[] = {
+ "e1000",
+ "e1000-82540em",
+ "e1000-82544gc",
+ "e1000-82545em",
+};
+
int main(int argc, char **argv)
{
- int ret;
+ int i;
g_test_init(&argc, &argv, NULL);
- qtest_add_func("/e1000/nop", nop);
- qtest_start("-device e1000");
- ret = g_test_run();
+ for (i = 0; i < ARRAY_SIZE(models); i++) {
+ char *path;
- qtest_end();
+ path = g_strdup_printf("/%s/e1000/%s", qtest_get_arch(), models[i]);
+ g_test_add_data_func(path, models[i], test_device);
+ }
- return ret;
+ return g_test_run();
}
diff --git a/tests/es1370-test.c b/tests/es1370-test.c
new file mode 100644
index 000000000..cc23fb5c6
--- /dev/null
+++ b/tests/es1370-test.c
@@ -0,0 +1,33 @@
+/*
+ * QTest testcase for ES1370
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * 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 <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)
+{
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/es1370/nop", nop);
+
+ qtest_start("-device ES1370");
+ ret = g_test_run();
+
+ qtest_end();
+
+ return ret;
+}
diff --git a/tests/fdc-test.c b/tests/fdc-test.c
index 37096dcc1..203074cda 100644
--- a/tests/fdc-test.c
+++ b/tests/fdc-test.c
@@ -65,7 +65,7 @@ enum {
DSKCHG = 0x80,
};
-char test_image[] = "/tmp/qtest.XXXXXX";
+static char test_image[] = "/tmp/qtest.XXXXXX";
#define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, (mask))
#define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0)
@@ -291,7 +291,7 @@ static void test_media_insert(void)
/* Insert media in drive. DSKCHK should not be reset until a step pulse
* is sent. */
qmp_discard_response("{'execute':'change', 'arguments':{"
- " 'device':'floppy0', 'target': '%s' }}",
+ " 'device':'floppy0', 'target': %s }}",
test_image);
qmp_discard_response(""); /* ignore event
(FIXME open -> open transition?!) */
diff --git a/tests/intel-hda-test.c b/tests/intel-hda-test.c
new file mode 100644
index 000000000..d89b407dc
--- /dev/null
+++ b/tests/intel-hda-test.c
@@ -0,0 +1,45 @@
+/*
+ * QTest testcase for Intel HDA
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * 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 <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" \
+ " -device hda-micro,bus=" HDA_ID ".0" \
+ " -device hda-duplex,bus=" HDA_ID ".0"
+
+/* Tests only initialization so far. TODO: Replace with functional tests */
+static void ich6_test(void)
+{
+ qtest_start("-device intel-hda,id=" HDA_ID CODEC_DEVICES);
+ qtest_end();
+}
+
+static void ich9_test(void)
+{
+ qtest_start("-machine q35 -device ich9-intel-hda,bus=pcie.0,addr=1b.0,id="
+ HDA_ID CODEC_DEVICES);
+ qtest_end();
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/intel-hda/ich6", ich6_test);
+ qtest_add_func("/intel-hda/ich9", ich9_test);
+
+ ret = g_test_run();
+
+ return ret;
+}
diff --git a/tests/ioh3420-test.c b/tests/ioh3420-test.c
new file mode 100644
index 000000000..c991a5f87
--- /dev/null
+++ b/tests/ioh3420-test.c
@@ -0,0 +1,34 @@
+/*
+ * QTest testcase for Intel X58 north bridge IOH
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * 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 <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)
+{
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/ioh3420/nop", nop);
+
+ qtest_start("-machine q35 -device ioh3420,bus=pcie.0,addr=1c.0,port=1,"
+ "chassis=1,multifunction=on");
+ ret = g_test_run();
+
+ qtest_end();
+
+ return ret;
+}
diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index bf741a43a..4adf4006a 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -41,7 +41,7 @@ static uint8_t qpci_pc_io_readb(QPCIBus *bus, void *addr)
if (port < 0x10000) {
value = inb(port);
} else {
- memread(port, &value, sizeof(value));
+ value = readb(port);
}
return value;
@@ -55,7 +55,7 @@ static uint16_t qpci_pc_io_readw(QPCIBus *bus, void *addr)
if (port < 0x10000) {
value = inw(port);
} else {
- memread(port, &value, sizeof(value));
+ value = readw(port);
}
return value;
@@ -69,7 +69,7 @@ static uint32_t qpci_pc_io_readl(QPCIBus *bus, void *addr)
if (port < 0x10000) {
value = inl(port);
} else {
- memread(port, &value, sizeof(value));
+ value = readl(port);
}
return value;
@@ -82,7 +82,7 @@ static void qpci_pc_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
if (port < 0x10000) {
outb(port, value);
} else {
- memwrite(port, &value, sizeof(value));
+ writeb(port, value);
}
}
@@ -93,7 +93,7 @@ static void qpci_pc_io_writew(QPCIBus *bus, void *addr, uint16_t value)
if (port < 0x10000) {
outw(port, value);
} else {
- memwrite(port, &value, sizeof(value));
+ writew(port, value);
}
}
@@ -104,7 +104,7 @@ static void qpci_pc_io_writel(QPCIBus *bus, void *addr, uint32_t value)
if (port < 0x10000) {
outl(port, value);
} else {
- memwrite(port, &value, sizeof(value));
+ writel(port, value);
}
}
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
index 7e0907b51..c9a0b9134 100644
--- a/tests/libqos/pci.c
+++ b/tests/libqos/pci.c
@@ -103,7 +103,7 @@ void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value)
void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
{
- dev->bus->config_writew(dev->bus, dev->devfn, offset, value);
+ dev->bus->config_writel(dev->bus, dev->devfn, offset, value);
}
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 815569584..98e8f4b64 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -30,8 +30,9 @@
#include "qemu/compiler.h"
#include "qemu/osdep.h"
-#include "qapi/qmp/json-streamer.h"
#include "qapi/qmp/json-parser.h"
+#include "qapi/qmp/json-streamer.h"
+#include "qapi/qmp/qjson.h"
#define MAX_IRQ 256
#define SOCKET_TIMEOUT 5
@@ -72,7 +73,8 @@ static int init_socket(const char *socket_path)
ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
} while (ret == -1 && errno == EINTR);
g_assert_no_errno(ret);
- listen(sock, 1);
+ ret = listen(sock, 1);
+ g_assert_no_errno(ret);
return sock;
}
@@ -88,10 +90,13 @@ static int socket_accept(int sock)
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (void *)&timeout,
sizeof(timeout));
- addrlen = sizeof(addr);
do {
+ addrlen = sizeof(addr);
ret = accept(sock, (struct sockaddr *)&addr, &addrlen);
} while (ret == -1 && errno == EINTR);
+ if (ret == -1) {
+ fprintf(stderr, "%s failed: %s\n", __func__, strerror(errno));
+ }
close(sock);
return ret;
@@ -216,19 +221,15 @@ void qtest_quit(QTestState *s)
g_free(s);
}
-static void socket_sendf(int fd, const char *fmt, va_list ap)
+static void socket_send(int fd, const char *buf, size_t size)
{
- gchar *str;
- size_t size, offset;
-
- str = g_strdup_vprintf(fmt, ap);
- size = strlen(str);
+ size_t offset;
offset = 0;
while (offset < size) {
ssize_t len;
- len = write(fd, str + offset, size - offset);
+ len = write(fd, buf + offset, size - offset);
if (len == -1 && errno == EINTR) {
continue;
}
@@ -240,6 +241,15 @@ static void socket_sendf(int fd, const char *fmt, va_list ap)
}
}
+static void socket_sendf(int fd, const char *fmt, va_list ap)
+{
+ gchar *str = g_strdup_vprintf(fmt, ap);
+ size_t size = strlen(str);
+
+ socket_send(fd, str, size);
+ g_free(str);
+}
+
static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
{
va_list ap;
@@ -374,8 +384,29 @@ QDict *qtest_qmp_receive(QTestState *s)
QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap)
{
- /* Send QMP request */
- socket_sendf(s->qmp_fd, fmt, ap);
+ va_list ap_copy;
+ QObject *qobj;
+
+ /* Going through qobject ensures we escape strings properly.
+ * This seemingly unnecessary copy is required in case va_list
+ * is an array type.
+ */
+ va_copy(ap_copy, ap);
+ qobj = qobject_from_jsonv(fmt, &ap_copy);
+ va_end(ap_copy);
+
+ /* No need to send anything for an empty QObject. */
+ if (qobj) {
+ QString *qstr = qobject_to_json(qobj);
+ const char *str = qstring_get_str(qstr);
+ size_t size = qstring_get_length(qstr);
+
+ /* Send QMP request */
+ socket_send(s->qmp_fd, str, size);
+
+ QDECREF(qstr);
+ qobject_decref(qobj);
+ }
/* Receive reply */
return qtest_qmp_receive(s);
diff --git a/tests/qapi-schema/duplicate-key.err b/tests/qapi-schema/duplicate-key.err
index 0801c6a9b..768b276f8 100644
--- a/tests/qapi-schema/duplicate-key.err
+++ b/tests/qapi-schema/duplicate-key.err
@@ -1 +1 @@
-<stdin>:2:10: Duplicate key "key"
+tests/qapi-schema/duplicate-key.json:2:10: Duplicate key "key"
diff --git a/tests/qapi-schema/event-nest-struct.err b/tests/qapi-schema/event-nest-struct.err
new file mode 100644
index 000000000..91bde1c96
--- /dev/null
+++ b/tests/qapi-schema/event-nest-struct.err
@@ -0,0 +1 @@
+tests/qapi-schema/event-nest-struct.json:1: Nested structure define in event is not supported, event 'EVENT_A', argname 'a'
diff --git a/tests/qapi-schema/event-nest-struct.exit b/tests/qapi-schema/event-nest-struct.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/qapi-schema/event-nest-struct.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/event-nest-struct.json b/tests/qapi-schema/event-nest-struct.json
new file mode 100644
index 000000000..ee6f3ecb6
--- /dev/null
+++ b/tests/qapi-schema/event-nest-struct.json
@@ -0,0 +1,2 @@
+{ 'event': 'EVENT_A',
+ 'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
diff --git a/tests/qapi-schema/event-nest-struct.out b/tests/qapi-schema/event-nest-struct.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/event-nest-struct.out
diff --git a/tests/qapi-schema/flat-union-invalid-branch-key.err b/tests/qapi-schema/flat-union-invalid-branch-key.err
index 1125caf5d..ccf72d2df 100644
--- a/tests/qapi-schema/flat-union-invalid-branch-key.err
+++ b/tests/qapi-schema/flat-union-invalid-branch-key.err
@@ -1 +1 @@
-<stdin>:13: Discriminator value 'value_wrong' is not found in enum 'TestEnum'
+tests/qapi-schema/flat-union-invalid-branch-key.json:13: Discriminator value 'value_wrong' is not found in enum 'TestEnum'
diff --git a/tests/qapi-schema/flat-union-invalid-discriminator.err b/tests/qapi-schema/flat-union-invalid-discriminator.err
index cad9dbf22..790b6759b 100644
--- a/tests/qapi-schema/flat-union-invalid-discriminator.err
+++ b/tests/qapi-schema/flat-union-invalid-discriminator.err
@@ -1 +1 @@
-<stdin>:13: Discriminator 'enum_wrong' is not a member of base type 'TestBase'
+tests/qapi-schema/flat-union-invalid-discriminator.json:13: Discriminator 'enum_wrong' is not a member of base type 'TestBase'
diff --git a/tests/qapi-schema/flat-union-no-base.err b/tests/qapi-schema/flat-union-no-base.err
index e2d7443a3..a59749eb8 100644
--- a/tests/qapi-schema/flat-union-no-base.err
+++ b/tests/qapi-schema/flat-union-no-base.err
@@ -1 +1 @@
-<stdin>:7: Flat union 'TestUnion' must have a base field
+tests/qapi-schema/flat-union-no-base.json:7: Flat union 'TestUnion' must have a base field
diff --git a/tests/qapi-schema/flat-union-string-discriminator.err b/tests/qapi-schema/flat-union-string-discriminator.err
index 87482704e..200016bd5 100644
--- a/tests/qapi-schema/flat-union-string-discriminator.err
+++ b/tests/qapi-schema/flat-union-string-discriminator.err
@@ -1 +1 @@
-<stdin>:13: Discriminator 'kind' must be of enumeration type
+tests/qapi-schema/flat-union-string-discriminator.json:13: Discriminator 'kind' must be of enumeration type
diff --git a/tests/qapi-schema/funny-char.err b/tests/qapi-schema/funny-char.err
index d3dd293fa..bfc890cd9 100644
--- a/tests/qapi-schema/funny-char.err
+++ b/tests/qapi-schema/funny-char.err
@@ -1 +1 @@
-<stdin>:2:36: Stray ";"
+tests/qapi-schema/funny-char.json:2:36: Stray ";"
diff --git a/tests/qapi-schema/include-before-err.err b/tests/qapi-schema/include-before-err.err
new file mode 100644
index 000000000..55652751e
--- /dev/null
+++ b/tests/qapi-schema/include-before-err.err
@@ -0,0 +1 @@
+tests/qapi-schema/include-before-err.json:2:13: Expected ":"
diff --git a/tests/qapi-schema/include-before-err.exit b/tests/qapi-schema/include-before-err.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/qapi-schema/include-before-err.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/include-before-err.json b/tests/qapi-schema/include-before-err.json
new file mode 100644
index 000000000..afb6cb63c
--- /dev/null
+++ b/tests/qapi-schema/include-before-err.json
@@ -0,0 +1,2 @@
+{ 'include': 'include-simple-sub.json' }
+{ 'command' 'missing-colon' }
diff --git a/tests/qapi-schema/include-before-err.out b/tests/qapi-schema/include-before-err.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-before-err.out
diff --git a/tests/qapi-schema/include-cycle-b.json b/tests/qapi-schema/include-cycle-b.json
new file mode 100644
index 000000000..4fa985dcd
--- /dev/null
+++ b/tests/qapi-schema/include-cycle-b.json
@@ -0,0 +1 @@
+{ 'include': 'include-cycle-c.json' }
diff --git a/tests/qapi-schema/include-cycle-c.json b/tests/qapi-schema/include-cycle-c.json
new file mode 100644
index 000000000..d12b5924a
--- /dev/null
+++ b/tests/qapi-schema/include-cycle-c.json
@@ -0,0 +1 @@
+{ 'include': 'include-cycle.json' }
diff --git a/tests/qapi-schema/include-cycle.err b/tests/qapi-schema/include-cycle.err
new file mode 100644
index 000000000..602cf6232
--- /dev/null
+++ b/tests/qapi-schema/include-cycle.err
@@ -0,0 +1,3 @@
+In file included from tests/qapi-schema/include-cycle.json:1:
+In file included from include-cycle-b.json:1:
+include-cycle-c.json:1: Inclusion loop for include-cycle.json
diff --git a/tests/qapi-schema/include-cycle.exit b/tests/qapi-schema/include-cycle.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/qapi-schema/include-cycle.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/include-cycle.json b/tests/qapi-schema/include-cycle.json
new file mode 100644
index 000000000..6fcf1ebaa
--- /dev/null
+++ b/tests/qapi-schema/include-cycle.json
@@ -0,0 +1 @@
+{ 'include': 'include-cycle-b.json' }
diff --git a/tests/qapi-schema/include-cycle.out b/tests/qapi-schema/include-cycle.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-cycle.out
diff --git a/tests/qapi-schema/include-format-err.err b/tests/qapi-schema/include-format-err.err
new file mode 100644
index 000000000..721ff4ecc
--- /dev/null
+++ b/tests/qapi-schema/include-format-err.err
@@ -0,0 +1 @@
+tests/qapi-schema/include-format-err.json:1: Invalid 'include' directive
diff --git a/tests/qapi-schema/include-format-err.exit b/tests/qapi-schema/include-format-err.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/qapi-schema/include-format-err.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/include-format-err.json b/tests/qapi-schema/include-format-err.json
new file mode 100644
index 000000000..44980f026
--- /dev/null
+++ b/tests/qapi-schema/include-format-err.json
@@ -0,0 +1,2 @@
+{ 'include': 'include-simple-sub.json',
+ 'foo': 'bar' }
diff --git a/tests/qapi-schema/include-format-err.out b/tests/qapi-schema/include-format-err.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-format-err.out
diff --git a/tests/qapi-schema/include-nested-err.err b/tests/qapi-schema/include-nested-err.err
new file mode 100644
index 000000000..1dacbda3b
--- /dev/null
+++ b/tests/qapi-schema/include-nested-err.err
@@ -0,0 +1,2 @@
+In file included from tests/qapi-schema/include-nested-err.json:1:
+missing-colon.json:1:10: Expected ":"
diff --git a/tests/qapi-schema/include-nested-err.exit b/tests/qapi-schema/include-nested-err.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/qapi-schema/include-nested-err.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/include-nested-err.json b/tests/qapi-schema/include-nested-err.json
new file mode 100644
index 000000000..5631e56ea
--- /dev/null
+++ b/tests/qapi-schema/include-nested-err.json
@@ -0,0 +1 @@
+{ 'include': 'missing-colon.json' }
diff --git a/tests/qapi-schema/include-nested-err.out b/tests/qapi-schema/include-nested-err.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-nested-err.out
diff --git a/tests/qapi-schema/include-no-file.err b/tests/qapi-schema/include-no-file.err
new file mode 100644
index 000000000..d5b9b22d8
--- /dev/null
+++ b/tests/qapi-schema/include-no-file.err
@@ -0,0 +1 @@
+tests/qapi-schema/include-no-file.json:1: No such file or directory: include-no-file-sub.json
diff --git a/tests/qapi-schema/include-no-file.exit b/tests/qapi-schema/include-no-file.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/qapi-schema/include-no-file.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/include-no-file.json b/tests/qapi-schema/include-no-file.json
new file mode 100644
index 000000000..9249ebd50
--- /dev/null
+++ b/tests/qapi-schema/include-no-file.json
@@ -0,0 +1 @@
+{ 'include': 'include-no-file-sub.json' }
diff --git a/tests/qapi-schema/include-no-file.out b/tests/qapi-schema/include-no-file.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-no-file.out
diff --git a/tests/qapi-schema/include-non-file.err b/tests/qapi-schema/include-non-file.err
new file mode 100644
index 000000000..9658c7880
--- /dev/null
+++ b/tests/qapi-schema/include-non-file.err
@@ -0,0 +1 @@
+tests/qapi-schema/include-non-file.json:1: Expected a file name (string), got: ['foo', 'bar']
diff --git a/tests/qapi-schema/include-non-file.exit b/tests/qapi-schema/include-non-file.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/qapi-schema/include-non-file.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/include-non-file.json b/tests/qapi-schema/include-non-file.json
new file mode 100644
index 000000000..cd43c3f9d
--- /dev/null
+++ b/tests/qapi-schema/include-non-file.json
@@ -0,0 +1 @@
+{ 'include': [ 'foo', 'bar' ] }
diff --git a/tests/qapi-schema/include-non-file.out b/tests/qapi-schema/include-non-file.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-non-file.out
diff --git a/tests/qapi-schema/include-relpath-sub.json b/tests/qapi-schema/include-relpath-sub.json
new file mode 100644
index 000000000..4bd4af416
--- /dev/null
+++ b/tests/qapi-schema/include-relpath-sub.json
@@ -0,0 +1,2 @@
+{ 'enum': 'Status',
+ 'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/include-relpath.err b/tests/qapi-schema/include-relpath.err
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-relpath.err
diff --git a/tests/qapi-schema/include-relpath.exit b/tests/qapi-schema/include-relpath.exit
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/tests/qapi-schema/include-relpath.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/include-relpath.json b/tests/qapi-schema/include-relpath.json
new file mode 100644
index 000000000..05018f390
--- /dev/null
+++ b/tests/qapi-schema/include-relpath.json
@@ -0,0 +1 @@
+{ 'include': 'include/relpath.json' }
diff --git a/tests/qapi-schema/include-relpath.out b/tests/qapi-schema/include-relpath.out
new file mode 100644
index 000000000..4ce3dcf12
--- /dev/null
+++ b/tests/qapi-schema/include-relpath.out
@@ -0,0 +1,3 @@
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}]
+[]
diff --git a/tests/qapi-schema/include-repetition-sub.json b/tests/qapi-schema/include-repetition-sub.json
new file mode 100644
index 000000000..6bfffdfd5
--- /dev/null
+++ b/tests/qapi-schema/include-repetition-sub.json
@@ -0,0 +1,2 @@
+{ 'include': 'comments.json' }
+{ 'include': 'comments.json' }
diff --git a/tests/qapi-schema/include-repetition.err b/tests/qapi-schema/include-repetition.err
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-repetition.err
diff --git a/tests/qapi-schema/include-repetition.exit b/tests/qapi-schema/include-repetition.exit
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/tests/qapi-schema/include-repetition.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/include-repetition.json b/tests/qapi-schema/include-repetition.json
new file mode 100644
index 000000000..ec329dde5
--- /dev/null
+++ b/tests/qapi-schema/include-repetition.json
@@ -0,0 +1,3 @@
+{ 'include': 'comments.json' }
+{ 'include': 'include-repetition-sub.json' }
+{ 'include': 'comments.json' }
diff --git a/tests/qapi-schema/include-repetition.out b/tests/qapi-schema/include-repetition.out
new file mode 100644
index 000000000..4ce3dcf12
--- /dev/null
+++ b/tests/qapi-schema/include-repetition.out
@@ -0,0 +1,3 @@
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}]
+[]
diff --git a/tests/qapi-schema/include-self-cycle.err b/tests/qapi-schema/include-self-cycle.err
new file mode 100644
index 000000000..981742ae5
--- /dev/null
+++ b/tests/qapi-schema/include-self-cycle.err
@@ -0,0 +1 @@
+tests/qapi-schema/include-self-cycle.json:1: Inclusion loop for include-self-cycle.json
diff --git a/tests/qapi-schema/include-self-cycle.exit b/tests/qapi-schema/include-self-cycle.exit
new file mode 100644
index 000000000..d00491fd7
--- /dev/null
+++ b/tests/qapi-schema/include-self-cycle.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/include-self-cycle.json b/tests/qapi-schema/include-self-cycle.json
new file mode 100644
index 000000000..55fb1b596
--- /dev/null
+++ b/tests/qapi-schema/include-self-cycle.json
@@ -0,0 +1 @@
+{ 'include': 'include-self-cycle.json' }
diff --git a/tests/qapi-schema/include-self-cycle.out b/tests/qapi-schema/include-self-cycle.out
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-self-cycle.out
diff --git a/tests/qapi-schema/include-simple-sub.json b/tests/qapi-schema/include-simple-sub.json
new file mode 100644
index 000000000..4bd4af416
--- /dev/null
+++ b/tests/qapi-schema/include-simple-sub.json
@@ -0,0 +1,2 @@
+{ 'enum': 'Status',
+ 'data': [ 'good', 'bad', 'ugly' ] }
diff --git a/tests/qapi-schema/include-simple.err b/tests/qapi-schema/include-simple.err
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/qapi-schema/include-simple.err
diff --git a/tests/qapi-schema/include-simple.exit b/tests/qapi-schema/include-simple.exit
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/tests/qapi-schema/include-simple.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/include-simple.json b/tests/qapi-schema/include-simple.json
new file mode 100644
index 000000000..1dd391a59
--- /dev/null
+++ b/tests/qapi-schema/include-simple.json
@@ -0,0 +1 @@
+{ 'include': 'include-simple-sub.json' }
diff --git a/tests/qapi-schema/include-simple.out b/tests/qapi-schema/include-simple.out
new file mode 100644
index 000000000..4ce3dcf12
--- /dev/null
+++ b/tests/qapi-schema/include-simple.out
@@ -0,0 +1,3 @@
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])])]
+[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}]
+[]
diff --git a/tests/qapi-schema/include/relpath.json b/tests/qapi-schema/include/relpath.json
new file mode 100644
index 000000000..45dee2470
--- /dev/null
+++ b/tests/qapi-schema/include/relpath.json
@@ -0,0 +1 @@
+{ 'include': '../include-relpath-sub.json' }
diff --git a/tests/qapi-schema/missing-colon.err b/tests/qapi-schema/missing-colon.err
index 9f2a35515..d9d66b377 100644
--- a/tests/qapi-schema/missing-colon.err
+++ b/tests/qapi-schema/missing-colon.err
@@ -1 +1 @@
-<stdin>:1:10: Expected ":"
+tests/qapi-schema/missing-colon.json:1:10: Expected ":"
diff --git a/tests/qapi-schema/missing-comma-list.err b/tests/qapi-schema/missing-comma-list.err
index 4fe070019..e73d2770d 100644
--- a/tests/qapi-schema/missing-comma-list.err
+++ b/tests/qapi-schema/missing-comma-list.err
@@ -1 +1 @@
-<stdin>:2:20: Expected "," or "]"
+tests/qapi-schema/missing-comma-list.json:2:20: Expected "," or "]"
diff --git a/tests/qapi-schema/missing-comma-object.err b/tests/qapi-schema/missing-comma-object.err
index b0121b5f3..52b3a8a1e 100644
--- a/tests/qapi-schema/missing-comma-object.err
+++ b/tests/qapi-schema/missing-comma-object.err
@@ -1 +1 @@
-<stdin>:2:3: Expected "," or "}"
+tests/qapi-schema/missing-comma-object.json:2:3: Expected "," or "}"
diff --git a/tests/qapi-schema/non-objects.err b/tests/qapi-schema/non-objects.err
index a6c2dc26a..334f0c91a 100644
--- a/tests/qapi-schema/non-objects.err
+++ b/tests/qapi-schema/non-objects.err
@@ -1 +1 @@
-<stdin>:1:1: Expected "{"
+tests/qapi-schema/non-objects.json:1:1: Expected "{"
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 818c06dc7..ab4d3d96b 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -89,3 +89,15 @@
'*u16' : [ 'uint16' ],
'*i64x': 'int' ,
'*u64x': 'uint64' } }
+
+# testing event
+{ 'type': 'EventStructOne',
+ 'data': { 'struct1': 'UserDefOne', 'string': 'str', '*enum2': 'EnumOne' } }
+
+{ 'event': 'EVENT_A' }
+{ 'event': 'EVENT_B',
+ 'data': { } }
+{ 'event': 'EVENT_C',
+ 'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } }
+{ 'event': 'EVENT_D',
+ 'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 6cd03f31c..95e989925 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -15,7 +15,12 @@
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([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])]
+ OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
+ OrderedDict([('type', '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')]))])]
[{'enum_name': 'EnumOne', 'enum_values': ['value1', 'value2', 'value3']},
{'enum_name': 'UserDefUnionKind', 'enum_values': None},
{'enum_name': 'UserDefAnonUnionKind', 'enum_values': None},
@@ -28,4 +33,5 @@
OrderedDict([('type', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
OrderedDict([('type', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
OrderedDict([('type', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
- OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))])]
+ OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
+ OrderedDict([('type', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))])]
diff --git a/tests/qapi-schema/quoted-structural-chars.err b/tests/qapi-schema/quoted-structural-chars.err
index a6c2dc26a..9b183841d 100644
--- a/tests/qapi-schema/quoted-structural-chars.err
+++ b/tests/qapi-schema/quoted-structural-chars.err
@@ -1 +1 @@
-<stdin>:1:1: Expected "{"
+tests/qapi-schema/quoted-structural-chars.json:1:1: Expected "{"
diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py
index b3d1e1dbc..634ef2d00 100644
--- a/tests/qapi-schema/test-qapi.py
+++ b/tests/qapi-schema/test-qapi.py
@@ -12,15 +12,13 @@
from qapi import *
from pprint import pprint
+import os
import sys
try:
- exprs = parse_schema(sys.stdin)
+ exprs = parse_schema(sys.argv[1])
except SystemExit:
raise
-except:
- print >>sys.stderr, "Crashed:", sys.exc_info()[0]
- exit(1)
pprint(exprs)
pprint(enum_types)
diff --git a/tests/qapi-schema/trailing-comma-list.err b/tests/qapi-schema/trailing-comma-list.err
index ff839a34e..24c24b010 100644
--- a/tests/qapi-schema/trailing-comma-list.err
+++ b/tests/qapi-schema/trailing-comma-list.err
@@ -1 +1 @@
-<stdin>:2:36: Expected "{", "[" or string
+tests/qapi-schema/trailing-comma-list.json:2:36: Expected "{", "[" or string
diff --git a/tests/qapi-schema/trailing-comma-object.err b/tests/qapi-schema/trailing-comma-object.err
index f5409627d..30bce5e19 100644
--- a/tests/qapi-schema/trailing-comma-object.err
+++ b/tests/qapi-schema/trailing-comma-object.err
@@ -1 +1 @@
-<stdin>:2:38: Expected string
+tests/qapi-schema/trailing-comma-object.json:2:38: Expected string
diff --git a/tests/qapi-schema/unclosed-list.err b/tests/qapi-schema/unclosed-list.err
index 0e837a7fa..fb41a86ab 100644
--- a/tests/qapi-schema/unclosed-list.err
+++ b/tests/qapi-schema/unclosed-list.err
@@ -1 +1 @@
-<stdin>:1:20: Expected "," or "]"
+tests/qapi-schema/unclosed-list.json:1:20: Expected "," or "]"
diff --git a/tests/qapi-schema/unclosed-object.err b/tests/qapi-schema/unclosed-object.err
index e6dc9501d..db3deedd6 100644
--- a/tests/qapi-schema/unclosed-object.err
+++ b/tests/qapi-schema/unclosed-object.err
@@ -1 +1 @@
-<stdin>:1:21: Expected "," or "}"
+tests/qapi-schema/unclosed-object.json:1:21: Expected "," or "}"
diff --git a/tests/qapi-schema/unclosed-string.err b/tests/qapi-schema/unclosed-string.err
index 948d88339..12b187074 100644
--- a/tests/qapi-schema/unclosed-string.err
+++ b/tests/qapi-schema/unclosed-string.err
@@ -1 +1 @@
-<stdin>:1:11: Missing terminating "'"
+tests/qapi-schema/unclosed-string.json:1:11: Missing terminating "'"
diff --git a/tests/qapi-schema/union-invalid-base.err b/tests/qapi-schema/union-invalid-base.err
index dd8e3d1b3..938f96962 100644
--- a/tests/qapi-schema/union-invalid-base.err
+++ b/tests/qapi-schema/union-invalid-base.err
@@ -1 +1 @@
-<stdin>:7: Base 'TestBaseWrong' is not a valid type
+tests/qapi-schema/union-invalid-base.json:7: Base 'TestBaseWrong' is not a valid type
diff --git a/tests/qemu-iotests-quick.sh b/tests/qemu-iotests-quick.sh
index c449e8ab4..8a9a4c68e 100755
--- a/tests/qemu-iotests-quick.sh
+++ b/tests/qemu-iotests-quick.sh
@@ -1,16 +1,6 @@
#!/bin/sh
-# We don't know which of the system emulator binaries there is (or if there is
-# any at all), so the 'quick' group doesn't contain any tests that require
-# running qemu proper. Assign a fake binary name so that qemu-iotests doesn't
-# complain about the missing binary.
-export QEMU_PROG="this_should_be_unused"
-
-export QEMU_IMG_PROG="$(pwd)/qemu-img"
-export QEMU_IO_PROG="$(pwd)/qemu-io"
-export QEMU_NBD_PROG="$(pwd)/qemu-nbd"
-
-cd $SRC_PATH/tests/qemu-iotests
+cd tests/qemu-iotests
ret=0
./check -T -nocache -qcow2 -g quick || ret=1
diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019
index e67445c75..f5ecbf545 100755
--- a/tests/qemu-iotests/019
+++ b/tests/qemu-iotests/019
@@ -96,7 +96,7 @@ mv "$TEST_IMG" "$TEST_IMG.orig"
for backing_option in "-B " "-o backing_file="; do
echo
- echo Testing conversion with $backing_option$TEST_IMG.base | _filter_testdir | _filter_imgfmt
+ 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"
diff --git a/tests/qemu-iotests/028 b/tests/qemu-iotests/028
index a99e4fa2b..9e701e1c2 100755
--- a/tests/qemu-iotests/028
+++ b/tests/qemu-iotests/028
@@ -33,7 +33,8 @@ status=1 # failure is the default!
_cleanup()
{
- _cleanup_test_img
+ rm -f "${TEST_IMG}.copy"
+ _cleanup_test_img
}
trap "_cleanup; exit \$status" 0 1 2 3 15
@@ -41,6 +42,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
. ./common.rc
. ./common.filter
. ./common.pattern
+. ./common.qemu
# Any format supporting backing files except vmdk and qcow which do not support
# smaller backing files.
@@ -99,6 +101,31 @@ _check_test_img
# Rebase it on top of its base image
$QEMU_IMG rebase -b "$TEST_IMG.base" "$TEST_IMG"
+echo
+echo block-backup
+echo
+
+qemu_comm_method="monitor"
+_launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk
+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
+_send_qemu_cmd $h "drive_backup disk ${TEST_IMG}.copy" "(qemu)" >/dev/null
+qemu_cmd_repeat=20 _send_qemu_cmd $h "info block-jobs" "No active jobs"
+_send_qemu_cmd $h 'quit' ""
+
+# Base image sectors
+TEST_IMG="${TEST_IMG}.copy" io readv $(( offset )) 512 1024 32
+
+# Image sectors
+TEST_IMG="${TEST_IMG}.copy" io readv $(( offset + 512 )) 512 1024 64
+
+# Zero sectors beyond end of base image
+TEST_IMG="${TEST_IMG}.copy" io_zero readv $(( offset + 32 * 1024 )) 512 1024 32
+
+
_check_test_img
# success, all done
diff --git a/tests/qemu-iotests/028.out b/tests/qemu-iotests/028.out
index 8affb7f3a..0e1a5ae65 100644
--- a/tests/qemu-iotests/028.out
+++ b/tests/qemu-iotests/028.out
@@ -465,5 +465,272 @@ read 512/512 bytes at offset 3221257728
read 512/512 bytes at offset 3221258752
512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
+
+block-backup
+
+Formatting 'TEST_DIR/t.qcow2.copy', fmt=qcow2 size=4294968832 backing_file='TEST_DIR/t.qcow2.base' backing_fmt='qcow2' encryption=off cluster_size=65536 lazy_refcounts=off
+(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
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221195264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221196288
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221197312
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221198336
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221199360
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221200384
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221201408
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221202432
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221203456
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221204480
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221205504
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221206528
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221207552
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221208576
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221209600
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221210624
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221211648
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221212672
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221213696
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221214720
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221215744
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221216768
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221217792
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221218816
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221219840
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221220864
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221221888
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221222912
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221223936
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221224960
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221225984
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== IO: pattern 196
+read 512/512 bytes at offset 3221194752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221195776
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221196800
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221197824
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221198848
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221199872
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221200896
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221201920
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221202944
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221203968
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221204992
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221206016
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221207040
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221208064
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221209088
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221210112
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221211136
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221212160
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221213184
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221214208
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221215232
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221216256
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221217280
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221218304
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221219328
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221220352
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221221376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221222400
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221223424
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221224448
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221225472
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221226496
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221227520
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221228544
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221229568
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221230592
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221231616
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221232640
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221233664
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221234688
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221235712
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221236736
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221237760
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221238784
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221239808
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221240832
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221241856
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221242880
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221243904
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221244928
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221245952
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221246976
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221248000
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221249024
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221250048
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221251072
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221252096
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221253120
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221254144
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221255168
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221256192
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221257216
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221258240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221259264
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+=== IO: pattern 0
+read 512/512 bytes at offset 3221227008
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221228032
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221229056
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221230080
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221231104
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221232128
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221233152
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221234176
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221235200
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221236224
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221237248
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221238272
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221239296
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221240320
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221241344
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221242368
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221243392
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221244416
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221245440
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221246464
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221247488
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221248512
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221249536
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221250560
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221251584
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221252608
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221253632
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221254656
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221255680
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221256704
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221257728
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 512/512 bytes at offset 3221258752
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
No errors were found on the image.
*** done
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030
index 59a34f76f..8ce2373cf 100755
--- a/tests/qemu-iotests/030
+++ b/tests/qemu-iotests/030
@@ -35,7 +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('-c', 'write -P 0x1 0 512', backing_img)
- self.vm = iotests.VM().add_drive(test_img)
+ self.vm = iotests.VM().add_drive("blkdebug::" + test_img)
self.vm.launch()
def tearDown(self):
@@ -50,15 +50,7 @@ class TestSingleDrive(iotests.QMPTestCase):
result = self.vm.qmp('block-stream', device='drive0')
self.assert_qmp(result, 'return', {})
- completed = False
- while not completed:
- for event in self.vm.get_qmp_events(wait=True):
- if event['event'] == 'BLOCK_JOB_COMPLETED':
- self.assert_qmp(event, 'data/type', 'stream')
- self.assert_qmp(event, 'data/device', 'drive0')
- self.assert_qmp(event, 'data/offset', self.image_len)
- self.assert_qmp(event, 'data/len', self.image_len)
- completed = True
+ self.wait_until_completed()
self.assert_no_active_block_jobs()
self.vm.shutdown()
@@ -89,15 +81,7 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_qmp(result, 'return', {})
self.vm.resume_drive('drive0')
- completed = False
- while not completed:
- for event in self.vm.get_qmp_events(wait=True):
- if event['event'] == 'BLOCK_JOB_COMPLETED':
- self.assert_qmp(event, 'data/type', 'stream')
- self.assert_qmp(event, 'data/device', 'drive0')
- self.assert_qmp(event, 'data/offset', self.image_len)
- self.assert_qmp(event, 'data/len', self.image_len)
- completed = True
+ self.wait_until_completed()
self.assert_no_active_block_jobs()
self.vm.shutdown()
@@ -112,15 +96,7 @@ class TestSingleDrive(iotests.QMPTestCase):
result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
self.assert_qmp(result, 'return', {})
- completed = False
- while not completed:
- for event in self.vm.get_qmp_events(wait=True):
- if event['event'] == 'BLOCK_JOB_COMPLETED':
- self.assert_qmp(event, 'data/type', 'stream')
- self.assert_qmp(event, 'data/device', 'drive0')
- self.assert_qmp(event, 'data/offset', self.image_len)
- self.assert_qmp(event, 'data/len', self.image_len)
- completed = True
+ self.wait_until_completed()
self.assert_no_active_block_jobs()
self.vm.shutdown()
@@ -152,15 +128,7 @@ class TestSmallerBackingFile(iotests.QMPTestCase):
result = self.vm.qmp('block-stream', device='drive0')
self.assert_qmp(result, 'return', {})
- completed = False
- while not completed:
- for event in self.vm.get_qmp_events(wait=True):
- if event['event'] == 'BLOCK_JOB_COMPLETED':
- self.assert_qmp(event, 'data/type', 'stream')
- self.assert_qmp(event, 'data/device', 'drive0')
- self.assert_qmp(event, 'data/offset', self.image_len)
- self.assert_qmp(event, 'data/len', self.image_len)
- completed = True
+ self.wait_until_completed()
self.assert_no_active_block_jobs()
self.vm.shutdown()
@@ -442,15 +410,7 @@ class TestSetSpeed(iotests.QMPTestCase):
result = self.vm.qmp('block-job-set-speed', device='drive0', speed=8 * 1024 * 1024)
self.assert_qmp(result, 'return', {})
- completed = False
- while not completed:
- for event in self.vm.get_qmp_events(wait=True):
- if event['event'] == 'BLOCK_JOB_COMPLETED':
- self.assert_qmp(event, 'data/type', 'stream')
- self.assert_qmp(event, 'data/device', 'drive0')
- self.assert_qmp(event, 'data/offset', self.image_len)
- self.assert_qmp(event, 'data/len', self.image_len)
- completed = True
+ self.wait_until_completed()
self.assert_no_active_block_jobs()
diff --git a/tests/qemu-iotests/031 b/tests/qemu-iotests/031
index 1d920ea87..2a77ba8cb 100755
--- a/tests/qemu-iotests/031
+++ b/tests/qemu-iotests/031
@@ -56,22 +56,22 @@ for IMGOPTS in "compat=0.10" "compat=1.1"; do
echo === Create image with unknown header extension ===
echo
_make_test_img 64M
- ./qcow2.py "$TEST_IMG" add-header-ext 0x12345678 "This is a test header extension"
- ./qcow2.py "$TEST_IMG" dump-header
+ $PYTHON qcow2.py "$TEST_IMG" add-header-ext 0x12345678 "This is a test header extension"
+ $PYTHON qcow2.py "$TEST_IMG" dump-header
_check_test_img
echo
echo === Rewrite header with no backing file ===
echo
$QEMU_IMG rebase -u -b "" "$TEST_IMG"
- ./qcow2.py "$TEST_IMG" dump-header
+ $PYTHON qcow2.py "$TEST_IMG" dump-header
_check_test_img
echo
echo === Add a backing file and format ===
echo
$QEMU_IMG rebase -u -b "/some/backing/file/path" -F host_device "$TEST_IMG"
- ./qcow2.py "$TEST_IMG" dump-header
+ $PYTHON qcow2.py "$TEST_IMG" dump-header
done
# success, all done
diff --git a/tests/qemu-iotests/036 b/tests/qemu-iotests/036
index 03b6aa9de..392f1ef3e 100755
--- a/tests/qemu-iotests/036
+++ b/tests/qemu-iotests/036
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Test that qcow2 unknown autoclear feature bits are cleared
+# Test qcow2 feature bits
#
# Copyright (C) 2011 Red Hat, Inc.
# Copyright IBM, Corp. 2010
@@ -50,18 +50,68 @@ _supported_os Linux
# Only qcow2v3 and later supports feature bits
IMGOPTS="compat=1.1"
+echo
+echo === Image with unknown incompatible feature bit ===
+echo
+_make_test_img 64M
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
+
+# Without feature table
+$PYTHON qcow2.py "$TEST_IMG" dump-header
+_img_info
+
+# With feature table containing bit 63
+printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+echo
+echo === Image with multiple incompatible feature bits ===
+echo
+_make_test_img 64M
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 61
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 62
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit incompatible 63
+
+# Without feature table
+_img_info
+
+# With feature table containing bit 63
+printf "\x00\x3f%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing bit 61
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x00\x3d%s" "Test feature" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing bits 61 and 62
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s" "test1" "" "test2" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing all bits
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x00\x3d%s\x00%40s\x00\x3e%s\x00%40s\x00\x3f%s\x00%40s" "test1" "" "test2" "" "test3" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+# With feature table containing unrelated bits, including compatible/autoclear
+$PYTHON qcow2.py "$TEST_IMG" del-header-ext 0x6803f857
+printf "\x01\x3d%s\x00%40s\x00\x3e%s\x00%40s\x02\x3f%s\x00%40s\x00\x3c%s\x00%40s" "test1" "" "test2" "" "test3" "" "test4" "" | $PYTHON qcow2.py "$TEST_IMG" add-header-ext-stdio 0x6803f857
+_img_info
+
+
echo === Create image with unknown autoclear feature bit ===
echo
_make_test_img 64M
-./qcow2.py "$TEST_IMG" set-feature-bit autoclear 63
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit autoclear 63
+$PYTHON qcow2.py "$TEST_IMG" dump-header
echo
echo === Repair image ===
echo
_check_test_img -r all
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
# success, all done
echo "*** done"
diff --git a/tests/qemu-iotests/036.out b/tests/qemu-iotests/036.out
index 55a3e6e44..720bd8916 100644
--- a/tests/qemu-iotests/036.out
+++ b/tests/qemu-iotests/036.out
@@ -1,4 +1,39 @@
QA output created by 036
+
+=== Image with unknown incompatible feature bit ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+magic 0x514649fb
+version 3
+backing_file_offset 0x0
+backing_file_size 0x0
+cluster_bits 16
+size 67108864
+crypt_method 0
+l1_size 1
+l1_table_offset 0x30000
+refcount_table_offset 0x10000
+refcount_table_clusters 1
+nb_snapshots 0
+snapshot_offset 0x0
+incompatible_features 0x8000000000000000
+compatible_features 0x0
+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
+
+=== 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
=== Create image with unknown autoclear feature bit ===
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039
index b9cbe9956..84c916766 100755
--- a/tests/qemu-iotests/039
+++ b/tests/qemu-iotests/039
@@ -47,6 +47,11 @@ _supported_os Linux
_default_cache_mode "writethrough"
_supported_cache_modes "writethrough"
+_no_dump_exec()
+{
+ (ulimit -c 0; exec "$@")
+}
+
size=128M
echo
@@ -58,7 +63,7 @@ _make_test_img $size
$QEMU_IO -c "write -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
# The dirty bit must not be set
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
_check_test_img
echo
@@ -67,13 +72,10 @@ echo "== Creating a dirty image file =="
IMGOPTS="compat=1.1,lazy_refcounts=on"
_make_test_img $size
-old_ulimit=$(ulimit -c)
-ulimit -c 0 # do not produce a core dump on abort(3)
-$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io
-ulimit -c "$old_ulimit"
+_no_dump_exec $QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" 2>&1 | _filter_qemu_io
# The dirty bit must be set
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
_check_test_img
echo
@@ -82,7 +84,7 @@ echo "== Read-only access must still work =="
$QEMU_IO -r -c "read -P 0x5a 0 512" "$TEST_IMG" | _filter_qemu_io
# The dirty bit must be set
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
echo
echo "== Repairing the image file must succeed =="
@@ -90,7 +92,7 @@ echo "== Repairing the image file must succeed =="
_check_test_img -r all
# The dirty bit must not be set
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
echo
echo "== Data should still be accessible after repair =="
@@ -103,18 +105,15 @@ echo "== Opening a dirty image read/write should repair it =="
IMGOPTS="compat=1.1,lazy_refcounts=on"
_make_test_img $size
-old_ulimit=$(ulimit -c)
-ulimit -c 0 # do not produce a core dump on abort(3)
-$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io
-ulimit -c "$old_ulimit"
+_no_dump_exec $QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" 2>&1 | _filter_qemu_io
# The dirty bit must be set
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
$QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io
# The dirty bit must not be set
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
echo
echo "== Creating an image file with lazy_refcounts=off =="
@@ -122,13 +121,10 @@ echo "== Creating an image file with lazy_refcounts=off =="
IMGOPTS="compat=1.1,lazy_refcounts=off"
_make_test_img $size
-old_ulimit=$(ulimit -c)
-ulimit -c 0 # do not produce a core dump on abort(3)
-$QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" | _filter_qemu_io
-ulimit -c "$old_ulimit"
+_no_dump_exec $QEMU_IO -c "write -P 0x5a 0 512" -c "abort" "$TEST_IMG" 2>&1 | _filter_qemu_io
# The dirty bit must not be set since lazy_refcounts=off
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
_check_test_img
echo
@@ -144,8 +140,8 @@ $QEMU_IO -c "write 0 512" "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG commit "$TEST_IMG"
# The dirty bit must not be set
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
-./qcow2.py "$TEST_IMG".base dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG".base dump-header | grep incompatible_features
_check_test_img
TEST_IMG="$TEST_IMG".base _check_test_img
diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out
index fb31ae062..67e774430 100644
--- a/tests/qemu-iotests/039.out
+++ b/tests/qemu-iotests/039.out
@@ -11,6 +11,7 @@ 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: Aborted ( ulimit -c 0; exec "$@" )
incompatible_features 0x1
ERROR cluster 5 refcount=0 reference=1
ERROR OFLAG_COPIED data cluster: l2_entry=8000000000050000 refcount=0
@@ -42,6 +43,7 @@ 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: Aborted ( ulimit -c 0; exec "$@" )
incompatible_features 0x1
Repairing cluster 5 refcount=0 reference=1
wrote 512/512 bytes at offset 0
@@ -52,6 +54,7 @@ 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: Aborted ( ulimit -c 0; exec "$@" )
incompatible_features 0x0
No errors were found on the image.
diff --git a/tests/qemu-iotests/040 b/tests/qemu-iotests/040
index 734b6a6bb..f1e16c11c 100755
--- a/tests/qemu-iotests/040
+++ b/tests/qemu-iotests/040
@@ -35,12 +35,9 @@ test_img = os.path.join(iotests.test_dir, 'test.img')
class ImageCommitTestCase(iotests.QMPTestCase):
'''Abstract base class for image commit test cases'''
- def run_commit_test(self, top, base):
- self.assert_no_active_block_jobs()
- result = self.vm.qmp('block-commit', device='drive0', top=top, base=base)
- self.assert_qmp(result, 'return', {})
-
+ def wait_for_complete(self, need_ready=False):
completed = False
+ ready = False
while not completed:
for event in self.vm.get_qmp_events(wait=True):
if event['event'] == 'BLOCK_JOB_COMPLETED':
@@ -48,8 +45,11 @@ class ImageCommitTestCase(iotests.QMPTestCase):
self.assert_qmp(event, 'data/device', 'drive0')
self.assert_qmp(event, 'data/offset', self.image_len)
self.assert_qmp(event, 'data/len', self.image_len)
+ if need_ready:
+ self.assertTrue(ready, "Expecting BLOCK_JOB_COMPLETED event")
completed = True
elif event['event'] == 'BLOCK_JOB_READY':
+ ready = True
self.assert_qmp(event, 'data/type', 'commit')
self.assert_qmp(event, 'data/device', 'drive0')
self.assert_qmp(event, 'data/len', self.image_len)
@@ -58,12 +58,24 @@ class ImageCommitTestCase(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
self.vm.shutdown()
+ def run_commit_test(self, top, base, need_ready=False):
+ self.assert_no_active_block_jobs()
+ result = self.vm.qmp('block-commit', device='drive0', top=top, base=base)
+ self.assert_qmp(result, 'return', {})
+ self.wait_for_complete(need_ready)
+
+ def run_default_commit_test(self):
+ self.assert_no_active_block_jobs()
+ result = self.vm.qmp('block-commit', device='drive0')
+ self.assert_qmp(result, 'return', {})
+ self.wait_for_complete()
+
class TestSingleDrive(ImageCommitTestCase):
image_len = 1 * 1024 * 1024
test_len = 1 * 1024 * 256
def setUp(self):
- iotests.create_image(backing_img, TestSingleDrive.image_len)
+ iotests.create_image(backing_img, self.image_len)
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('-c', 'write -P 0xab 0 524288', backing_img)
@@ -105,7 +117,12 @@ class TestSingleDrive(ImageCommitTestCase):
self.assert_qmp(result, 'error/desc', 'Base \'badfile\' not found')
def test_top_is_active(self):
- self.run_commit_test(test_img, backing_img)
+ self.run_commit_test(test_img, backing_img, need_ready=True)
+ self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
+ self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
+
+ def test_top_is_default_active(self):
+ self.run_default_commit_test()
self.assertEqual(-1, qemu_io('-c', 'read -P 0xab 0 524288', backing_img).find("verification failed"))
self.assertEqual(-1, qemu_io('-c', 'read -P 0xef 524288 524288', backing_img).find("verification failed"))
@@ -115,11 +132,6 @@ class TestSingleDrive(ImageCommitTestCase):
self.assert_qmp(result, 'error/class', 'GenericError')
self.assert_qmp(result, 'error/desc', 'Base \'%s\' not found' % mid_img)
- def test_top_omitted(self):
- self.assert_no_active_block_jobs()
- result = self.vm.qmp('block-commit', device='drive0')
- self.assert_qmp(result, 'error/class', 'GenericError')
- self.assert_qmp(result, 'error/desc', "Parameter 'top' is missing")
class TestRelativePaths(ImageCommitTestCase):
image_len = 1 * 1024 * 1024
@@ -238,6 +250,8 @@ class TestSetSpeed(ImageCommitTestCase):
self.cancel_and_wait(resume=True)
+class TestActiveZeroLengthImage(TestSingleDrive):
+ image_len = 0
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/040.out b/tests/qemu-iotests/040.out
index b6f257674..42314e9c0 100644
--- a/tests/qemu-iotests/040.out
+++ b/tests/qemu-iotests/040.out
@@ -1,5 +1,5 @@
-................
+........................
----------------------------------------------------------------------
-Ran 16 tests
+Ran 24 tests
OK
diff --git a/tests/qemu-iotests/041 b/tests/qemu-iotests/041
index ec470b200..5dbd4ee91 100755
--- a/tests/qemu-iotests/041
+++ b/tests/qemu-iotests/041
@@ -28,6 +28,12 @@ target_backing_img = os.path.join(iotests.test_dir, 'target-backing.img')
test_img = os.path.join(iotests.test_dir, 'test.img')
target_img = os.path.join(iotests.test_dir, 'target.img')
+quorum_img1 = os.path.join(iotests.test_dir, 'quorum1.img')
+quorum_img2 = os.path.join(iotests.test_dir, 'quorum2.img')
+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 ImageMirroringTestCase(iotests.QMPTestCase):
'''Abstract base class for image mirroring test cases'''
@@ -42,8 +48,8 @@ class ImageMirroringTestCase(iotests.QMPTestCase):
ready = True
def wait_ready_and_cancel(self, drive='drive0'):
- self.wait_ready(drive)
- event = self.cancel_and_wait()
+ self.wait_ready(drive=drive)
+ event = self.cancel_and_wait(drive=drive)
self.assertEquals(event['event'], 'BLOCK_JOB_COMPLETED')
self.assert_qmp(event, 'data/type', 'mirror')
self.assert_qmp(event, 'data/offset', self.image_len)
@@ -52,19 +58,19 @@ class ImageMirroringTestCase(iotests.QMPTestCase):
def complete_and_wait(self, drive='drive0', wait_ready=True):
'''Complete a block job and wait for it to finish'''
if wait_ready:
- self.wait_ready()
+ self.wait_ready(drive=drive)
result = self.vm.qmp('block-job-complete', device=drive)
self.assert_qmp(result, 'return', {})
- event = self.wait_until_completed()
+ event = self.wait_until_completed(drive=drive)
self.assert_qmp(event, 'data/type', 'mirror')
class TestSingleDrive(ImageMirroringTestCase):
image_len = 1 * 1024 * 1024 # MB
def setUp(self):
- iotests.create_image(backing_img, TestSingleDrive.image_len)
+ 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)
self.vm.launch()
@@ -163,7 +169,7 @@ class TestSingleDrive(ImageMirroringTestCase):
self.assert_no_active_block_jobs()
qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,size=%d'
- % (TestSingleDrive.image_len, TestSingleDrive.image_len), target_img)
+ % (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)
self.assert_qmp(result, 'return', {})
@@ -179,7 +185,7 @@ class TestSingleDrive(ImageMirroringTestCase):
self.assert_no_active_block_jobs()
qemu_img('create', '-f', iotests.imgfmt, '-o', 'cluster_size=%d,backing_file=%s'
- % (TestSingleDrive.image_len, backing_img), target_img)
+ % (self.image_len, backing_img), target_img)
result = self.vm.qmp('drive-mirror', device='drive0', sync='full',
mode='existing', target=target_img)
self.assert_qmp(result, 'return', {})
@@ -206,6 +212,16 @@ class TestSingleDrive(ImageMirroringTestCase):
target=target_img)
self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+class TestSingleDriveZeroLength(TestSingleDrive):
+ image_len = 0
+ test_small_buffer2 = None
+ test_large_cluster = None
+
+class TestSingleDriveUnalignedLength(TestSingleDrive):
+ image_len = 1025 * 1024
+ test_small_buffer2 = None
+ test_large_cluster = None
+
class TestMirrorNoBacking(ImageMirroringTestCase):
image_len = 2 * 1024 * 1024 # MB
@@ -718,5 +734,224 @@ class TestUnbackedSource(ImageMirroringTestCase):
self.complete_and_wait()
self.assert_no_active_block_jobs()
+class TestRepairQuorum(ImageMirroringTestCase):
+ """ This class test quorum file repair using drive-mirror.
+ It's mostly a fork of TestSingleDrive """
+ image_len = 1 * 1024 * 1024 # MB
+ IMAGES = [ quorum_img1, quorum_img2, quorum_img3 ]
+
+ def has_quorum(self):
+ return 'quorum' in iotests.qemu_img_pipe('--help')
+
+ def setUp(self):
+ self.vm = iotests.VM()
+
+ # Add each individual quorum images
+ for i in self.IMAGES:
+ qemu_img('create', '-f', iotests.imgfmt, i,
+ str(TestSingleDrive.image_len))
+ # Assign a node name to each quorum image in order to manipulate
+ # them
+ opts = "node-name=img%i" % self.IMAGES.index(i)
+ self.vm = self.vm.add_drive(i, opts)
+
+ self.vm.launch()
+
+ #assemble the quorum block device from the individual files
+ args = { "options" : { "driver": "quorum", "id": "quorum0",
+ "vote-threshold": 2, "children": [ "img0", "img1", "img2" ] } }
+ if self.has_quorum():
+ result = self.vm.qmp("blockdev-add", **args)
+ self.assert_qmp(result, 'return', {})
+
+
+ def tearDown(self):
+ self.vm.shutdown()
+ for i in self.IMAGES + [ quorum_repair_img ]:
+ # Do a try/except because the test may have deleted some images
+ try:
+ os.remove(i)
+ except OSError:
+ pass
+
+ def test_complete(self):
+ if not self.has_quorum():
+ return
+
+ self.assert_no_active_block_jobs()
+
+ result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
+ node_name="repair0",
+ replaces="img1",
+ target=quorum_repair_img, format=iotests.imgfmt)
+ 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)
+ # TODO: a better test requiring some QEMU infrastructure will be added
+ # to check that this file is really driven by quorum
+ self.vm.shutdown()
+ self.assertTrue(iotests.compare_images(quorum_img2, quorum_repair_img),
+ 'target image does not match source after mirroring')
+
+ def test_cancel(self):
+ if not self.has_quorum():
+ return
+
+ self.assert_no_active_block_jobs()
+
+ result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
+ node_name="repair0",
+ replaces="img1",
+ target=quorum_repair_img, format=iotests.imgfmt)
+ self.assert_qmp(result, 'return', {})
+
+ 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.vm.shutdown()
+
+ def test_cancel_after_ready(self):
+ if not self.has_quorum():
+ return
+
+ self.assert_no_active_block_jobs()
+
+ result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
+ node_name="repair0",
+ replaces="img1",
+ target=quorum_repair_img, format=iotests.imgfmt)
+ 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.vm.shutdown()
+ self.assertTrue(iotests.compare_images(quorum_img2, quorum_repair_img),
+ 'target image does not match source after mirroring')
+
+ def test_pause(self):
+ if not self.has_quorum():
+ return
+
+ self.assert_no_active_block_jobs()
+
+ result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
+ node_name="repair0",
+ replaces="img1",
+ target=quorum_repair_img, format=iotests.imgfmt)
+ self.assert_qmp(result, 'return', {})
+
+ result = self.vm.qmp('block-job-pause', device='quorum0')
+ self.assert_qmp(result, 'return', {})
+
+ time.sleep(1)
+ result = self.vm.qmp('query-block-jobs')
+ offset = self.dictpath(result, 'return[0]/offset')
+
+ time.sleep(1)
+ result = self.vm.qmp('query-block-jobs')
+ self.assert_qmp(result, 'return[0]/offset', offset)
+
+ result = self.vm.qmp('block-job-resume', device='quorum0')
+ self.assert_qmp(result, 'return', {})
+
+ self.complete_and_wait(drive="quorum0")
+ self.vm.shutdown()
+ self.assertTrue(iotests.compare_images(quorum_img2, quorum_repair_img),
+ 'target image does not match source after mirroring')
+
+ def test_medium_not_found(self):
+ if not self.has_quorum():
+ return
+
+ result = self.vm.qmp('drive-mirror', device='ide1-cd0', sync='full',
+ node_name='repair0',
+ replaces='img1',
+ target=quorum_repair_img, format=iotests.imgfmt)
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ def test_image_not_found(self):
+ if not self.has_quorum():
+ return
+
+ result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
+ node_name='repair0',
+ replaces='img1',
+ mode='existing',
+ target=quorum_repair_img, format=iotests.imgfmt)
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ def test_device_not_found(self):
+ if not self.has_quorum():
+ return
+
+ result = self.vm.qmp('drive-mirror', device='nonexistent', sync='full',
+ node_name='repair0',
+ replaces='img1',
+ target=quorum_repair_img, format=iotests.imgfmt)
+ self.assert_qmp(result, 'error/class', 'DeviceNotFound')
+
+ def test_wrong_sync_mode(self):
+ if not self.has_quorum():
+ return
+
+ result = self.vm.qmp('drive-mirror', device='quorum0',
+ node_name='repair0',
+ replaces='img1',
+ target=quorum_repair_img, format=iotests.imgfmt)
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ def test_no_node_name(self):
+ if not self.has_quorum():
+ return
+
+ result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
+ replaces='img1',
+ target=quorum_repair_img, format=iotests.imgfmt)
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ def test_unexistant_replaces(self):
+ if not self.has_quorum():
+ return
+
+ result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
+ node_name='repair0',
+ replaces='img77',
+ target=quorum_repair_img, format=iotests.imgfmt)
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ def test_after_a_quorum_snapshot(self):
+ if not self.has_quorum():
+ return
+
+ result = self.vm.qmp('blockdev-snapshot-sync', node_name='img1',
+ snapshot_file=quorum_snapshot_file,
+ snapshot_node_name="snap1");
+
+ result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
+ node_name='repair0',
+ replaces="img1",
+ target=quorum_repair_img, format=iotests.imgfmt)
+ self.assert_qmp(result, 'error/class', 'GenericError')
+
+ result = self.vm.qmp('drive-mirror', device='quorum0', sync='full',
+ node_name='repair0',
+ replaces="snap1",
+ target=quorum_repair_img, format=iotests.imgfmt)
+ 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)
+ # TODO: a better test requiring some QEMU infrastructure will be added
+ # to check that this file is really driven by quorum
+ self.vm.shutdown()
+
if __name__ == '__main__':
iotests.main(supported_fmts=['qcow2', 'qed'])
diff --git a/tests/qemu-iotests/041.out b/tests/qemu-iotests/041.out
index 6d9bee1a4..24093bc63 100644
--- a/tests/qemu-iotests/041.out
+++ b/tests/qemu-iotests/041.out
@@ -1,5 +1,5 @@
-...........................
+......................................................
----------------------------------------------------------------------
-Ran 27 tests
+Ran 54 tests
OK
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index ceb23289f..71ca44d76 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -120,7 +120,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
-qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'.
+qemu-img: TEST_DIR/t.qcow2: Invalid options for file format 'qcow2'
== Check correct interpretation of suffixes for cluster size ==
diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051
index 073dc7a2d..a41334e02 100755
--- a/tests/qemu-iotests/051
+++ b/tests/qemu-iotests/051
@@ -92,6 +92,7 @@ echo
run_qemu -drive file="$TEST_IMG",format=foo
run_qemu -drive file="$TEST_IMG",driver=foo
+run_qemu -drive file="$TEST_IMG",driver=raw,format=qcow2
echo
echo === Overriding backing file ===
@@ -99,6 +100,11 @@ echo
echo "info block" | run_qemu -drive file="$TEST_IMG",driver=qcow2,backing.file.filename="$TEST_IMG.orig" -nodefaults
+# Drivers that don't support backing files
+run_qemu -drive file="$TEST_IMG",driver=raw,backing.file.filename="$TEST_IMG.orig"
+run_qemu -drive file="$TEST_IMG",file.backing.driver=file,file.backing.filename="$TEST_IMG.orig"
+run_qemu -drive file="$TEST_IMG",file.backing.driver=qcow2,file.backing.file.filename="$TEST_IMG.orig"
+
echo
echo === Enable and disable lazy refcounting on the command line, plus some invalid values ===
echo
@@ -233,6 +239,10 @@ echo 'qemu-io ide0-hd0 "write -P 0x22 0 4k"' | run_qemu -drive file="$TEST_IMG",
$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
+
+$QEMU_IO -c "read -P 0x33 0 4k" "$TEST_IMG" | _filter_qemu_io
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out
index 01b038447..d7b0f503a 100644
--- a/tests/qemu-iotests/051.out
+++ b/tests/qemu-iotests/051.out
@@ -38,7 +38,10 @@ Testing: -drive file=TEST_DIR/t.qcow2,format=foo
QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=foo: 'foo' invalid format
Testing: -drive file=TEST_DIR/t.qcow2,driver=foo
-QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: could not open disk image TEST_DIR/t.qcow2: Invalid driver: 'foo'
+QEMU_PROG: -drive file=TEST_DIR/t.qcow2,driver=foo: could not open disk image TEST_DIR/t.qcow2: 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: could not open disk image TEST_DIR/t.qcow2: Driver specified twice
=== Overriding backing file ===
@@ -50,6 +53,15 @@ ide0-hd0: TEST_DIR/t.qcow2 (qcow2)
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: could not open disk image TEST_DIR/t.qcow2: 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: could not open disk image TEST_DIR/t.qcow2: 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: could not open disk image TEST_DIR/t.qcow2: Driver doesn't support backing files
+
=== Enable and disable lazy refcounting on the command line, plus some invalid values ===
@@ -358,4 +370,14 @@ wrote 4096/4096 bytes at offset 0
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
+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"
+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) 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/tests/qemu-iotests/054 b/tests/qemu-iotests/054
index c8b7082b4..bd94153d6 100755
--- a/tests/qemu-iotests/054
+++ b/tests/qemu-iotests/054
@@ -49,7 +49,7 @@ _make_test_img $((1024*1024))T
echo
echo "creating too large image (1 EB) using qcow2.py"
_make_test_img 4G
-./qcow2.py "$TEST_IMG" set-header size $((1024 ** 6))
+$PYTHON qcow2.py "$TEST_IMG" set-header size $((1024 ** 6))
_check_test_img
# success, all done
diff --git a/tests/qemu-iotests/056 b/tests/qemu-iotests/056
index 63893423c..54e4bd069 100755
--- a/tests/qemu-iotests/056
+++ b/tests/qemu-iotests/056
@@ -57,14 +57,7 @@ class TestSyncModesNoneAndTop(iotests.QMPTestCase):
format=iotests.imgfmt, target=target_img)
self.assert_qmp(result, 'return', {})
- # Custom completed check as we are not copying all data.
- completed = False
- while not completed:
- for event in self.vm.get_qmp_events(wait=True):
- if event['event'] == 'BLOCK_JOB_COMPLETED':
- self.assert_qmp(event, 'data/device', 'drive0')
- self.assert_qmp_absent(event, 'data/error')
- completed = True
+ self.wait_until_completed(check_offset=False)
self.assert_no_active_block_jobs()
self.vm.shutdown()
diff --git a/tests/qemu-iotests/059 b/tests/qemu-iotests/059
index ca5aa16ff..26a2fd3e0 100755
--- a/tests/qemu-iotests/059
+++ b/tests/qemu-iotests/059
@@ -104,6 +104,13 @@ truncate -s 10M $TEST_IMG
_img_info
echo
+echo "=== Converting to streamOptimized from image with small cluster size==="
+TEST_IMG="$TEST_IMG.qcow2" IMGFMT=qcow2 IMGOPTS="cluster_size=4096" _make_test_img 1G
+$QEMU_IO -c "write -P 0xa 0 512" "$TEST_IMG.qcow2" | _filter_qemu_io
+$QEMU_IO -c "write -P 0xb 10240 512" "$TEST_IMG.qcow2" | _filter_qemu_io
+$QEMU_IMG convert -f qcow2 -O vmdk -o subformat=streamOptimized "$TEST_IMG.qcow2" "$TEST_IMG" 2>&1
+
+echo
echo "=== Testing version 3 ==="
_use_sample_img iotest-version3.vmdk.bz2
_img_info
diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out
index 3371c867b..eba0dedda 100644
--- a/tests/qemu-iotests/059.out
+++ b/tests/qemu-iotests/059.out
@@ -2046,10 +2046,18 @@ RW 12582912 VMFS "dummy.IMGFMT" 1
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=107374182400
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===
+Formatting 'TEST_DIR/t.vmdk.IMGFMT', fmt=IMGFMT size=1073741824
+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 10240
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
=== Testing version 3 ===
image: TEST_DIR/iotest-version3.IMGFMT
file format: IMGFMT
virtual size: 1.0G (1073741824 bytes)
+cluster_size: 65536
=== Testing 4TB monolithicFlat creation and IO ===
Formatting 'TEST_DIR/iotest-version3.IMGFMT', fmt=IMGFMT size=4398046511104
diff --git a/tests/qemu-iotests/060 b/tests/qemu-iotests/060
index f0116aab1..3cffc12fe 100755
--- a/tests/qemu-iotests/060
+++ b/tests/qemu-iotests/060
@@ -68,13 +68,13 @@ poke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x03\x00\x00"
_check_test_img
# The corrupt bit should not be set anyway
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
# Try to write something, thereby forcing the corrupt bit to be set
$QEMU_IO -c "$OPEN_RW" -c "write -P 0x2a 0 512" | _filter_qemu_io
# The corrupt bit must now be set
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
# Try to open the image R/W (which should fail)
$QEMU_IO -c "$OPEN_RW" -c "read 0 512" 2>&1 | _filter_qemu_io \
@@ -99,19 +99,19 @@ poke_file "$TEST_IMG" "$(($rb_offset+8))" "\x00\x01"
# Redirect new data cluster onto refcount block
poke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x02\x00\x00"
_check_test_img
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
$QEMU_IO -c "$OPEN_RW" -c "write -P 0x2a 0 512" | _filter_qemu_io
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
# Try to fix it
_check_test_img -r all
# The corrupt bit should be cleared
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
# Look if it's really really fixed
$QEMU_IO -c "$OPEN_RW" -c "write -P 0x2a 0 512" | _filter_qemu_io
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
echo
echo "=== Testing cluster data reference into inactive L2 table ==="
@@ -124,13 +124,13 @@ $QEMU_IO -c "$OPEN_RW" -c "write -P 2 0 512" | _filter_qemu_io
poke_file "$TEST_IMG" "$l2_offset_after_snapshot" \
"\x80\x00\x00\x00\x00\x04\x00\x00"
_check_test_img
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
$QEMU_IO -c "$OPEN_RW" -c "write -P 3 0 512" | _filter_qemu_io
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
_check_test_img -r all
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
$QEMU_IO -c "$OPEN_RW" -c "write -P 4 0 512" | _filter_qemu_io
-./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
+$PYTHON qcow2.py "$TEST_IMG" dump-header | grep incompatible_features
# Check data
$QEMU_IO -c "$OPEN_RO" -c "read -P 4 0 512" | _filter_qemu_io
diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061
index d3a6b388b..ab98def6d 100755
--- a/tests/qemu-iotests/061
+++ b/tests/qemu-iotests/061
@@ -48,9 +48,9 @@ echo "=== Testing version downgrade with zero expansion ==="
echo
IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img 64M
$QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IO -c "read -P 0 0 128k" "$TEST_IMG" | _filter_qemu_io
_check_test_img
@@ -59,9 +59,9 @@ 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
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IO -c "read -P 0x2a 0 128k" "$TEST_IMG" | _filter_qemu_io
_check_test_img
@@ -69,11 +69,11 @@ echo
echo "=== Testing version downgrade with unknown compat/autoclear flags ==="
echo
IMGOPTS="compat=1.1" _make_test_img 64M
-./qcow2.py "$TEST_IMG" set-feature-bit compatible 42
-./qcow2.py "$TEST_IMG" set-feature-bit autoclear 42
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit compatible 42
+$PYTHON qcow2.py "$TEST_IMG" set-feature-bit autoclear 42
+$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IMG amend -o "compat=0.10" "$TEST_IMG"
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
_check_test_img
echo
@@ -81,9 +81,9 @@ echo "=== Testing version upgrade and resize ==="
echo
IMGOPTS="compat=0.10" _make_test_img 64M
$QEMU_IO -c "write -P 0x2a 42M 64k" "$TEST_IMG" | _filter_qemu_io
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IMG amend -o "compat=1.1,lazy_refcounts=on,size=128M" "$TEST_IMG"
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IO -c "read -P 0x2a 42M 64k" "$TEST_IMG" | _filter_qemu_io
_check_test_img
@@ -92,9 +92,9 @@ 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
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IMG amend -o "lazy_refcounts=off" "$TEST_IMG"
-./qcow2.py "$TEST_IMG" dump-header
+$PYTHON qcow2.py "$TEST_IMG" dump-header
$QEMU_IO -c "read -P 0x2a 0 128k" "$TEST_IMG" | _filter_qemu_io
_check_test_img
diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out
index 4027e0077..e3724700b 100644
--- a/tests/qemu-iotests/061.out
+++ b/tests/qemu-iotests/061.out
@@ -281,7 +281,7 @@ Lazy refcounts only supported with compatibility level 1.1 and above (use compat
qemu-img: Error while amending options: Invalid argument
Unknown compatibility level 0.42.
qemu-img: Error while amending options: Invalid argument
-Unknown option 'foo'
+qemu-img: Invalid parameter 'foo'
qemu-img: Invalid options for file format 'qcow2'
Changing the cluster size is not supported.
qemu-img: Error while amending options: Operation not supported
diff --git a/tests/qemu-iotests/065 b/tests/qemu-iotests/065
index ab5445f62..e89b61d70 100755
--- a/tests/qemu-iotests/065
+++ b/tests/qemu-iotests/065
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python
#
# Test for additional information emitted by qemu-img info on qcow2
# images
diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out
index 8d271cc41..7e090b95a 100644
--- a/tests/qemu-iotests/067.out
+++ b/tests/qemu-iotests/067.out
@@ -6,7 +6,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk -device virtio-blk-pci,drive=disk,id=virtio0
QMP_VERSION
{"return": {}}
-{"return": [{"io-status": "ok", "device": "disk", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "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"}]}
+{"return": [{"io-status": "ok", "device": "disk", "locked": false, "removable": false, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "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"}]}
{"return": {}}
{"return": {}}
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_DELETED", "data": {"path": "/machine/peripheral/virtio0/virtio-backend"}}
@@ -24,7 +24,7 @@ QMP_VERSION
Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,if=none,id=disk
QMP_VERSION
{"return": {}}
-{"return": [{"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "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"}]}
+{"return": [{"device": "disk", "locked": false, "removable": true, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "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"}]}
{"return": {}}
{"return": {}}
{"return": {}}
@@ -44,7 +44,7 @@ Testing:
QMP_VERSION
{"return": {}}
{"return": "OK\r\n"}
-{"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, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"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, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
{"return": {}}
{"return": {}}
{"return": {}}
@@ -64,14 +64,14 @@ Testing:
QMP_VERSION
{"return": {}}
{"return": {}}
-{"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, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"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, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
{"return": {}}
{"return": {}}
{"return": {}}
{"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, "inserted": {"iops_rd": 0, "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "tray_open": false, "type": "unknown"}]}
+{"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, "inserted": {"iops_rd": 0, "detect_zeroes": "off", "image": {"virtual-size": 134217728, "filename": "TEST_DIR/t.qcow2", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, "format-specific": {"type": "qcow2", "data": {"compat": "1.1", "lazy-refcounts": false}}, "dirty-flag": false}, "iops_wr": 0, "ro": false, "backing_file_depth": 0, "drv": "qcow2", "iops": 0, "bps_wr": 0, "encrypted": false, "bps": 0, "bps_rd": 0, "file": "TEST_DIR/t.qcow2", "encryption_key_missing": false}, "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}}
diff --git a/tests/qemu-iotests/070 b/tests/qemu-iotests/070
index ce71fa4a2..ea0dae7e9 100755
--- a/tests/qemu-iotests/070
+++ b/tests/qemu-iotests/070
@@ -72,6 +72,13 @@ echo "=== Verify open image read-only succeeds after log replay ==="
$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | _filter_testdir \
| _filter_qemu_io
+_cleanup_test_img
+_use_sample_img test-disk2vhd.vhdx.bz2
+
+echo
+echo "=== Verify image created by Disk2VHD can be opened ==="
+$QEMU_IMG info "$TEST_IMG" 2>&1 | _filter_testdir | _filter_qemu
+
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/070.out b/tests/qemu-iotests/070.out
index 922d62cb5..15f1fc147 100644
--- a/tests/qemu-iotests/070.out
+++ b/tests/qemu-iotests/070.out
@@ -18,4 +18,11 @@ No errors were found on the image.
=== Verify open image read-only succeeds after log replay ===
read 18874368/18874368 bytes at offset 0
18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Verify image created by Disk2VHD can be opened ===
+image: TEST_DIR/test-disk2vhd.vhdx
+file format: vhdx
+virtual size: 256M (268435456 bytes)
+disk size: 260M
+cluster_size: 2097152
*** done
diff --git a/tests/qemu-iotests/081 b/tests/qemu-iotests/081
index b512d00cc..7ae4be205 100755
--- a/tests/qemu-iotests/081
+++ b/tests/qemu-iotests/081
@@ -134,15 +134,28 @@ run_qemu -drive "file=$TEST_DIR/2.raw,format=$IMGFMT,if=none,id=drive2" <<EOF
EOF
echo
+echo "== using quorum rewrite corrupted mode =="
+
+quorum="$quorum,file.rewrite-corrupted=on"
+
+$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
+
+echo
+echo "== checking that quorum has corrected the corrupted file =="
+
+$QEMU_IO -c "read -P 0x32 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
+
+echo
echo "== breaking quorum =="
$QEMU_IO -c "write -P 0x41 0 $size" "$TEST_DIR/1.raw" | _filter_qemu_io
+$QEMU_IO -c "write -P 0x42 0 $size" "$TEST_DIR/2.raw" | _filter_qemu_io
+
echo
echo "== checking that quorum is broken =="
$QEMU_IO -c "open -o $quorum" -c "read -P 0x32 0 $size" | _filter_qemu_io
-
# success, all done
echo "*** done"
rm -f $seq.full
diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
index 84aeb0c73..073515ea5 100644
--- a/tests/qemu-iotests/081.out
+++ b/tests/qemu-iotests/081.out
@@ -40,10 +40,20 @@ read 10485760/10485760 bytes at offset 0
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+== using quorum rewrite corrupted mode ==
+read 10485760/10485760 bytes at offset 0
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== checking that quorum has corrected the corrupted file ==
+read 10485760/10485760 bytes at offset 0
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
== breaking quorum ==
wrote 10485760/10485760 bytes at offset 0
10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 10485760/10485760 bytes at offset 0
+10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
== checking that quorum is broken ==
-qemu-io: can't open device (null): Could not read image for determining its format: Input/output error
+qemu-io: can't open: Could not read image for determining its format: Input/output error
*** done
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
index 28309a032..413e7ef39 100644
--- a/tests/qemu-iotests/082.out
+++ b/tests/qemu-iotests/082.out
@@ -66,6 +66,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: create -f qcow2 -o ? TEST_DIR/t.qcow2 128M
Supported options:
@@ -77,6 +78,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: create -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 128M
Supported options:
@@ -88,6 +90,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: create -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 128M
Supported options:
@@ -99,6 +102,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: create -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 128M
Supported options:
@@ -110,6 +114,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: create -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 128M
Supported options:
@@ -121,6 +126,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: create -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 128M
Supported options:
@@ -132,6 +138,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: create -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 128M
Supported options:
@@ -143,6 +150,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+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
@@ -247,6 +255,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: convert -O qcow2 -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
Supported options:
@@ -258,6 +267,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: convert -O qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
Supported options:
@@ -269,6 +279,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: convert -O qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
Supported options:
@@ -280,6 +291,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: convert -O qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
Supported options:
@@ -291,6 +303,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: convert -O qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
Supported options:
@@ -302,6 +315,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: convert -O qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
Supported options:
@@ -313,6 +327,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: convert -O qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
Supported options:
@@ -324,6 +339,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
qemu-img: Could not open 'TEST_DIR/t.qcow2.base': Could not open backing file: Could not open 'TEST_DIR/t.qcow2,help': No such file or directory
@@ -417,6 +433,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2
Supported options:
@@ -428,6 +445,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2
Supported options:
@@ -439,6 +457,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2
Supported options:
@@ -450,6 +469,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2
Supported options:
@@ -461,6 +481,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2
Supported options:
@@ -472,6 +493,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2
Supported options:
@@ -483,6 +505,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2
Supported options:
@@ -494,6 +517,7 @@ encryption Encrypt the image
cluster_size qcow2 cluster size
preallocation Preallocation mode (allowed values: off, metadata)
lazy_refcounts Postpone refcount updates
+nocow Turn off copy-on-write (valid only on btrfs)
Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2
diff --git a/tests/qemu-iotests/083 b/tests/qemu-iotests/083
index f76453478..991a9d91d 100755
--- a/tests/qemu-iotests/083
+++ b/tests/qemu-iotests/083
@@ -44,7 +44,7 @@ choose_tcp_port() {
wait_for_tcp_port() {
while ! (netstat --tcp --listening --numeric | \
- grep "$1.*0.0.0.0:\*.*LISTEN") 2>&1 >/dev/null; do
+ grep "$1.*0\\.0\\.0\\.0:\\*.*LISTEN") 2>&1 >/dev/null; do
sleep 0.1
done
}
@@ -55,8 +55,8 @@ filter_nbd() {
# 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'
+ sed -e 's#^.*nbd\.c:.*##g' \
+ -e 's#nbd:127\.0\.0\.1:[^:]*:#nbd:127\.0\.0\.1:PORT:#g'
}
check_disconnect() {
@@ -81,8 +81,8 @@ EOF
nbd_url="nbd:127.0.0.1:$port:exportname=foo"
fi
- ./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"
+ $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
echo
diff --git a/tests/qemu-iotests/084.out b/tests/qemu-iotests/084.out
index e681924b8..c7120d9b0 100644
--- a/tests/qemu-iotests/084.out
+++ b/tests/qemu-iotests/084.out
@@ -4,10 +4,7 @@ QA output created by 084
Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
Test 1: Maximum size (1024 TB):
-image: TEST_DIR/t.IMGFMT
-file format: IMGFMT
-virtual size: 1024T (1125899905794048 bytes)
-cluster_size: 1048576
+qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'TEST_DIR/t.IMGFMT': Invalid argument
Test 2: Size too large (1024TB + 1)
qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Unsupported VDI image size (size is 0x3fffffff10000, max supported is 0x3fffffff00000)
diff --git a/tests/qemu-iotests/085 b/tests/qemu-iotests/085
index 33c8dc410..56cd6f89b 100755
--- a/tests/qemu-iotests/085
+++ b/tests/qemu-iotests/085
@@ -30,10 +30,6 @@ echo "QA output created by $seq"
here=`pwd`
status=1 # failure is the default!
-qemu_pid=
-
-QMP_IN="${TEST_DIR}/qmp-in-$$"
-QMP_OUT="${TEST_DIR}/qmp-out-$$"
snapshot_virt0="snapshot-v0.qcow2"
snapshot_virt1="snapshot-v1.qcow2"
@@ -42,10 +38,7 @@ MAX_SNAPSHOTS=10
_cleanup()
{
- kill -KILL ${qemu_pid}
- wait ${qemu_pid} 2>/dev/null # silent kill
-
- rm -f "${QMP_IN}" "${QMP_OUT}"
+ _cleanup_qemu
for i in $(seq 1 ${MAX_SNAPSHOTS})
do
rm -f "${TEST_DIR}/${i}-${snapshot_virt0}"
@@ -59,43 +52,12 @@ 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
-# Wait for expected QMP response from QEMU. Will time out
-# after 10 seconds, which counts as failure.
-#
-# $1 is the string to expect
-#
-# If $silent is set to anything but an empty string, then
-# response is not echoed out.
-function timed_wait_for()
-{
- while read -t 10 resp <&5
- do
- if [ "${silent}" == "" ]; then
- echo "${resp}" | _filter_testdir | _filter_qemu
- fi
- grep -q "${1}" < <(echo ${resp})
- if [ $? -eq 0 ]; then
- return
- fi
- done
- echo "Timeout waiting for ${1}"
- exit 1 # Timeout means the test failed
-}
-
-# Sends QMP command to QEMU, and waits for the expected response
-#
-# ${1}: String of the QMP command to send
-# ${2}: String that the QEMU response should contain
-function send_qmp_cmd()
-{
- echo "${1}" >&6
- timed_wait_for "${2}"
-}
# ${1}: unique identifier for the snapshot filename
function create_single_snapshot()
@@ -104,7 +66,7 @@ function create_single_snapshot()
'arguments': { 'device': 'virtio0',
'snapshot-file':'"${TEST_DIR}/${1}-${snapshot_virt0}"',
'format': 'qcow2' } }"
- send_qmp_cmd "${cmd}" "return"
+ _send_qemu_cmd $h "${cmd}" "return"
}
# ${1}: unique identifier for the snapshot filename
@@ -120,14 +82,11 @@ function create_group_snapshot()
'snapshot-file': '"${TEST_DIR}/${1}-${snapshot_virt1}"' } } ]
} }"
- send_qmp_cmd "${cmd}" "return"
+ _send_qemu_cmd $h "${cmd}" "return"
}
size=128M
-mkfifo "${QMP_IN}"
-mkfifo "${QMP_OUT}"
-
_make_test_img $size
mv "${TEST_IMG}" "${TEST_IMG}.orig"
_make_test_img $size
@@ -136,23 +95,15 @@ echo
echo === Running QEMU ===
echo
-"${QEMU}" -nographic -monitor none -serial none -qmp stdio\
- -drive file="${TEST_IMG}.orig",if=virtio\
- -drive file="${TEST_IMG}",if=virtio 2>&1 >"${QMP_OUT}" <"${QMP_IN}"&
-qemu_pid=$!
-
-# redirect fifos to file descriptors, to keep from blocking
-exec 5<"${QMP_OUT}"
-exec 6>"${QMP_IN}"
-
-# Don't print response, since it has version information in it
-silent=yes timed_wait_for "capabilities"
+qemu_comm_method="qmp"
+_launch_qemu -drive file="${TEST_IMG}.orig",if=virtio -drive file="${TEST_IMG}",if=virtio
+h=$QEMU_HANDLE
echo
echo === Sending capabilities ===
echo
-send_qmp_cmd "{ 'execute': 'qmp_capabilities' }" "return"
+_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return"
echo
echo === Create a single snapshot on virtio0 ===
@@ -165,16 +116,16 @@ echo
echo === Invalid command - missing device and nodename ===
echo
-send_qmp_cmd "{ 'execute': 'blockdev-snapshot-sync',
- 'arguments': { 'snapshot-file':'"${TEST_DIR}"/1-${snapshot_virt0}',
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'snapshot-file':'"${TEST_DIR}/1-${snapshot_virt0}"',
'format': 'qcow2' } }" "error"
echo
echo === Invalid command - missing snapshot-file ===
echo
-send_qmp_cmd "{ 'execute': 'blockdev-snapshot-sync',
- 'arguments': { 'device': 'virtio0',
+_send_qemu_cmd $h "{ 'execute': 'blockdev-snapshot-sync',
+ 'arguments': { 'device': 'virtio0',
'format': 'qcow2' } }" "error"
echo
echo
diff --git a/tests/qemu-iotests/086 b/tests/qemu-iotests/086
index 48fe85bc4..d9a80cf86 100755
--- a/tests/qemu-iotests/086
+++ b/tests/qemu-iotests/086
@@ -51,10 +51,10 @@ function run_qemu_img()
size=128M
_make_test_img $size
-$QEMU_IO -c 'write 0 1M' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'write 2M 1M' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'write 4M 1M' $TEST_IMG | _filter_qemu_io
-$QEMU_IO -c 'write 32M 1M' $TEST_IMG | _filter_qemu_io
+$QEMU_IO -c 'write 0 1M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'write 2M 1M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'write 4M 1M' "$TEST_IMG" | _filter_qemu_io
+$QEMU_IO -c 'write 32M 1M' "$TEST_IMG" | _filter_qemu_io
$QEMU_IMG convert -p -O $IMGFMT -f $IMGFMT "$TEST_IMG" "$TEST_IMG".base 2>&1 |\
_filter_testdir | sed -e 's/\r/\n/g'
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
index a38bb702b..82c56b139 100755
--- a/tests/qemu-iotests/087
+++ b/tests/qemu-iotests/087
@@ -73,6 +73,91 @@ run_qemu <<EOF
EOF
echo
+echo === Duplicate ID ===
+echo
+
+run_qemu <<EOF
+{ "execute": "qmp_capabilities" }
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
+ "driver": "$IMGFMT",
+ "id": "disk",
+ "node-name": "test-node",
+ "file": {
+ "driver": "file",
+ "filename": "$TEST_IMG"
+ }
+ }
+ }
+ }
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
+ "driver": "$IMGFMT",
+ "id": "disk",
+ "file": {
+ "driver": "file",
+ "filename": "$TEST_IMG"
+ }
+ }
+ }
+ }
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
+ "driver": "$IMGFMT",
+ "id": "test-node",
+ "file": {
+ "driver": "file",
+ "filename": "$TEST_IMG"
+ }
+ }
+ }
+ }
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
+ "driver": "$IMGFMT",
+ "id": "disk2",
+ "node-name": "disk",
+ "file": {
+ "driver": "file",
+ "filename": "$TEST_IMG"
+ }
+ }
+ }
+ }
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
+ "driver": "$IMGFMT",
+ "id": "disk2",
+ "node-name": "test-node",
+ "file": {
+ "driver": "file",
+ "filename": "$TEST_IMG"
+ }
+ }
+ }
+ }
+{ "execute": "blockdev-add",
+ "arguments": {
+ "options": {
+ "driver": "$IMGFMT",
+ "id": "disk3",
+ "node-name": "disk3",
+ "file": {
+ "driver": "file",
+ "filename": "$TEST_IMG"
+ }
+ }
+ }
+ }
+{ "execute": "quit" }
+EOF
+
+echo
echo === aio=native without O_DIRECT ===
echo
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index e65dcdfbb..7fbee3ff5 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -13,6 +13,24 @@ QMP_VERSION
{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "DEVICE_TRAY_MOVED", "data": {"device": "floppy0", "tray-open": true}}
+=== Duplicate ID ===
+
+Testing:
+QMP_VERSION
+{"return": {}}
+{"return": {}}
+{"error": {"class": "GenericError", "desc": "Device with id 'disk' already exists"}}
+{"error": {"class": "GenericError", "desc": "Device with node-name 'test-node' already exists"}}
+main-loop: WARNING: I/O thread spun for 1000 iterations
+{"error": {"class": "GenericError", "desc": "could not open disk image disk2: node-name=disk is conflicting with a device id"}}
+{"error": {"class": "GenericError", "desc": "could not open disk image disk2: Duplicate node name"}}
+{"error": {"class": "GenericError", "desc": "could not open disk image disk3: node-name=disk3 is conflicting with a device id"}}
+{"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 ===
Testing:
diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089
new file mode 100755
index 000000000..dffc977e1
--- /dev/null
+++ b/tests/qemu-iotests/089
@@ -0,0 +1,129 @@
+#!/bin/bash
+#
+# Test case for support of JSON filenames
+#
+# Copyright (C) 2014 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"
+tmp=/tmp/$$
+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
+
+# Using an image filename containing quotation marks will render the JSON data
+# below invalid. In that case, we have little choice but simply not to run this
+# test.
+case $TEST_IMG in
+ *'"'*)
+ _notrun "image filename may not contain quotation marks"
+ ;;
+esac
+
+IMG_SIZE=64M
+
+# Taken from test 072
+echo
+echo "=== Testing nested image formats ==="
+echo
+
+TEST_IMG="$TEST_IMG.base" _make_test_img $IMG_SIZE
+
+$QEMU_IO -c 'write -P 42 0 512' -c 'write -P 23 512 512' \
+ -c 'write -P 66 1024 512' "$TEST_IMG.base" | _filter_qemu_io
+
+$QEMU_IMG convert -f raw -O $IMGFMT "$TEST_IMG.base" "$TEST_IMG"
+
+$QEMU_IO -c 'read -P 42 0 512' -c 'read -P 23 512 512' \
+ -c 'read -P 66 1024 512' "json:{
+ \"driver\": \"$IMGFMT\",
+ \"file\": {
+ \"driver\": \"$IMGFMT\",
+ \"file\": {
+ \"filename\": \"$TEST_IMG\"
+ }
+ }
+}" | _filter_qemu_io
+
+# This should fail (see test 072)
+$QEMU_IO -c 'read -P 42 0 512' "$TEST_IMG" | _filter_qemu_io
+
+
+# Taken from test 071
+echo
+echo "=== Testing blkdebug ==="
+echo
+
+_make_test_img $IMG_SIZE
+
+$QEMU_IO -c 'write -P 42 0x38000 512' "$TEST_IMG" | _filter_qemu_io
+
+# The "image.filename" part tests whether "a": { "b": "c" } and "a.b": "c" do
+# the same (which they should).
+$QEMU_IO -c 'read -P 42 0x38000 512' "json:{
+ \"driver\": \"$IMGFMT\",
+ \"file\": {
+ \"driver\": \"blkdebug\",
+ \"inject-error\": [{
+ \"event\": \"l2_load\"
+ }],
+ \"image.filename\": \"$TEST_IMG\"
+ }
+}" | _filter_qemu_io
+
+
+echo
+echo "=== Testing qemu-img info output ==="
+echo
+
+TEST_IMG="json:{\"driver\":\"qcow2\",\"file.filename\":\"$TEST_IMG\"}" _img_info
+
+
+echo
+echo "=== Testing option merging ==="
+echo
+
+# Both options given directly and those given in the filename should be used
+$QEMU_IO -c "open -o driver=qcow2 json:{\"file.filename\":\"$TEST_IMG\"}" \
+ -c "info" 2>&1 | _filter_testdir | _filter_imgfmt
+
+# Options given directly should be prioritized over those given in the filename
+$QEMU_IO -c "open -o driver=qcow2 json:{\"driver\":\"raw\",\"file.filename\":\"$TEST_IMG\"}" \
+ -c "info" 2>&1 | _filter_testdir | _filter_imgfmt
+
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out
new file mode 100644
index 000000000..4ca2f88e6
--- /dev/null
+++ b/tests/qemu-iotests/089.out
@@ -0,0 +1,50 @@
+QA output created by 089
+
+=== Testing nested image formats ===
+
+Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864
+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
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 512/512 bytes at offset 1024
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+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 512/512 bytes at offset 1024
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Pattern verification failed at offset 0, 512 bytes
+read 512/512 bytes at offset 0
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+=== Testing blkdebug ===
+
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864
+wrote 512/512 bytes at offset 229376
+512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read failed: Input/output error
+
+=== Testing qemu-img info output ===
+
+image: TEST_DIR/t.IMGFMT
+file format: IMGFMT
+virtual size: 64M (67108864 bytes)
+cluster_size: 65536
+
+=== Testing option merging ===
+
+format name: IMGFMT
+cluster size: 64 KiB
+vm state offset: 512 MiB
+Format specific information:
+ compat: 1.1
+ lazy refcounts: false
+format name: IMGFMT
+cluster size: 64 KiB
+vm state offset: 512 MiB
+Format specific information:
+ compat: 1.1
+ lazy refcounts: false
+*** done
diff --git a/tests/qemu-iotests/090 b/tests/qemu-iotests/090
new file mode 100755
index 000000000..8d032f811
--- /dev/null
+++ b/tests/qemu-iotests/090
@@ -0,0 +1,61 @@
+#!/bin/bash
+#
+# Test for discarding compressed clusters on qcow2 images
+#
+# Copyright (C) 2014 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"
+tmp=/tmp/$$
+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
+
+IMG_SIZE=128K
+
+_make_test_img $IMG_SIZE
+
+$QEMU_IO -c 'write -c -P 42 0 64k' \
+ -c 'write -c -P 23 64k 64k' \
+ -c 'discard 64k 64k' \
+ "$TEST_IMG" | _filter_qemu_io
+
+$QEMU_IO -c 'read -P 0 64k 64k' "$TEST_IMG" | _filter_qemu_io
+
+_check_test_img
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/090.out b/tests/qemu-iotests/090.out
new file mode 100644
index 000000000..2df93e0d9
--- /dev/null
+++ b/tests/qemu-iotests/090.out
@@ -0,0 +1,12 @@
+QA output created by 090
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=131072
+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
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+discard 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 65536/65536 bytes at offset 65536
+64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+No errors were found on the image.
+*** done
diff --git a/tests/qemu-iotests/091 b/tests/qemu-iotests/091
new file mode 100755
index 000000000..32bbd5697
--- /dev/null
+++ b/tests/qemu-iotests/091
@@ -0,0 +1,107 @@
+#!/bin/bash
+#
+# Live migration test
+#
+# Performs a migration from one VM to another via monitor commands
+#
+# Copyright (C) 2014 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!
+
+MIG_FIFO="${TEST_DIR}/migrate"
+
+_cleanup()
+{
+ rm -f "${MIG_FIFO}"
+ _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 qcow2
+_supported_proto file
+_supported_os Linux
+_default_cache_mode "none"
+_supported_cache_modes "writethrough" "none" "writeback"
+
+size=1G
+
+_make_test_img $size
+
+mkfifo "${MIG_FIFO}"
+
+echo
+echo === Starting QEMU VM1 ===
+echo
+
+qemu_comm_method="monitor"
+_launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk
+h1=$QEMU_HANDLE
+
+echo
+echo === Starting QEMU VM2 ===
+echo
+_launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk \
+ -incoming "exec: cat '${MIG_FIFO}'"
+h2=$QEMU_HANDLE
+
+echo
+echo === VM 1: Migrate from VM1 to VM2 ===
+echo
+
+silent=yes
+_send_qemu_cmd $h1 'qemu-io disk "write -P 0x22 0 4M"' "(qemu)"
+echo "vm1: qemu-io disk write complete"
+_send_qemu_cmd $h1 "migrate \"exec: cat > '${MIG_FIFO}'\"" "(qemu)"
+echo "vm1: live migration started"
+qemu_cmd_repeat=20 _send_qemu_cmd $h1 "info migrate" "completed"
+echo "vm1: live migration completed"
+
+echo
+echo === VM 2: Post-migration, write to disk, verify running ===
+echo
+
+_send_qemu_cmd $h2 'qemu-io disk "write 4M 1M"' "(qemu)"
+echo "vm2: qemu-io disk write complete"
+qemu_cmd_repeat=20 _send_qemu_cmd $h2 "info status" "running"
+echo "vm2: qemu process running successfully"
+
+echo "vm2: flush io, and quit"
+_send_qemu_cmd $h2 'qemu-io disk flush' "(qemu)"
+_send_qemu_cmd $h2 'quit' ""
+
+echo "Check image pattern"
+${QEMU_IO} -c "read -P 0x22 0 4M" "${TEST_IMG}" | _filter_testdir | _filter_qemu_io
+
+echo "Running 'qemu-img check -r all \$TEST_IMG'"
+"${QEMU_IMG}" check -r all "${TEST_IMG}" 2>&1 | _filter_testdir | _filter_qemu
+
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/091.out b/tests/qemu-iotests/091.out
new file mode 100644
index 000000000..a2e012296
--- /dev/null
+++ b/tests/qemu-iotests/091.out
@@ -0,0 +1,28 @@
+QA output created by 091
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824
+
+=== Starting QEMU VM1 ===
+
+
+=== Starting QEMU VM2 ===
+
+
+=== VM 1: Migrate from VM1 to VM2 ===
+
+vm1: qemu-io disk write complete
+vm1: live migration started
+vm1: live migration completed
+
+=== VM 2: Post-migration, write to disk, verify running ===
+
+vm2: qemu-io disk write complete
+vm2: qemu process running successfully
+vm2: flush io, and quit
+Check image pattern
+read 4194304/4194304 bytes at offset 0
+4 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Running 'qemu-img check -r all $TEST_IMG'
+No errors were found on the image.
+80/16384 = 0.49% allocated, 0.00% fragmented, 0.00% compressed clusters
+Image end offset: 5570560
+*** done
diff --git a/tests/qemu-iotests/092 b/tests/qemu-iotests/092
new file mode 100755
index 000000000..a8c0c9ca2
--- /dev/null
+++ b/tests/qemu-iotests/092
@@ -0,0 +1,98 @@
+#!/bin/bash
+#
+# qcow1 format input validation tests
+#
+# Copyright (C) 2014 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`
+tmp=/tmp/$$
+status=1 # failure is the default!
+
+_cleanup()
+{
+ rm -f $TEST_IMG.snap
+ _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow
+_supported_proto generic
+_supported_os Linux
+
+offset_backing_file_offset=8
+offset_backing_file_size=16
+offset_size=24
+offset_cluster_bits=32
+offset_l2_bits=33
+
+echo
+echo "== Invalid cluster size =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_cluster_bits" "\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_cluster_bits" "\x1f"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_cluster_bits" "\x08"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_cluster_bits" "\x11"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== Invalid L2 table size =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_l2_bits" "\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_l2_bits" "\x05"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_l2_bits" "\x0e"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+# 1 << 0x1b = 2^31 / L2_CACHE_SIZE
+poke_file "$TEST_IMG" "$offset_l2_bits" "\x1b"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== Invalid size =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_size" "\xee\xee\xee\xee\xee\xee\xee\xee"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_size" "\x7f\xff\xff\xff\xff\xff\xff\xff"
+{ $QEMU_IO -c "write 0 64M" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== Invalid backing file length =="
+_make_test_img 64M
+poke_file "$TEST_IMG" "$offset_backing_file_offset" "\x00\x00\x00\xff"
+poke_file "$TEST_IMG" "$offset_backing_file_size" "\xff\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+poke_file "$TEST_IMG" "$offset_backing_file_size" "\x7f\xff\xff\xff"
+{ $QEMU_IO -c "read 0 512" $TEST_IMG; } 2>&1 | _filter_qemu_io | _filter_testdir
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/092.out b/tests/qemu-iotests/092.out
new file mode 100644
index 000000000..496d8f0a6
--- /dev/null
+++ b/tests/qemu-iotests/092.out
@@ -0,0 +1,38 @@
+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
+no file open, try 'help open'
+qemu-io: 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
+no file open, try 'help open'
+qemu-io: 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
+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
+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
+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
+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
+no file open, try 'help open'
+qemu-io: 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
+no file open, try 'help open'
+qemu-io: can't open device TEST_DIR/t.qcow: Backing file name too long
+no file open, try 'help open'
+*** done
diff --git a/tests/qemu-iotests/095 b/tests/qemu-iotests/095
new file mode 100755
index 000000000..acc7dbf18
--- /dev/null
+++ b/tests/qemu-iotests/095
@@ -0,0 +1,86 @@
+#!/bin/bash
+#
+# Test for commit of larger active layer
+#
+# This tests live snapshots of images on a running QEMU instance, using
+# QMP commands. Both single disk snapshots, and transactional group
+# snapshots are performed.
+#
+# Copyright (C) 2014 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
+ rm -f "${TEST_IMG}.base" "${TEST_IMG}.snp1"
+ _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
+
+size_smaller=5M
+size_larger=100M
+
+_make_test_img $size_smaller
+mv "${TEST_IMG}" "${TEST_IMG}.base"
+
+_make_test_img -b "${TEST_IMG}.base" $size_larger
+mv "${TEST_IMG}" "${TEST_IMG}.snp1"
+
+_make_test_img -b "${TEST_IMG}.snp1" $size_larger
+
+echo
+echo "=== Base image info before commit and resize ==="
+$QEMU_IMG info "${TEST_IMG}.base" | _filter_testdir
+
+echo
+echo === Running QEMU Live Commit Test ===
+echo
+
+qemu_comm_method="qmp"
+_launch_qemu -drive file="${TEST_IMG}",if=virtio,id=test
+h=$QEMU_HANDLE
+
+_send_qemu_cmd $h "{ 'execute': 'qmp_capabilities' }" "return"
+
+_send_qemu_cmd $h "{ 'execute': 'block-commit',
+ 'arguments': { 'device': 'test',
+ 'top': '"${TEST_IMG}.snp1"' } }" "BLOCK_JOB_COMPLETED"
+
+echo
+echo "=== Base image info after commit and resize ==="
+$QEMU_IMG info "${TEST_IMG}.base" | _filter_testdir
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/095.out b/tests/qemu-iotests/095.out
new file mode 100644
index 000000000..5864ddac2
--- /dev/null
+++ b/tests/qemu-iotests/095.out
@@ -0,0 +1,31 @@
+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'
+
+=== Base image info before commit and resize ===
+image: TEST_DIR/t.qcow2.base
+file format: qcow2
+virtual size: 5.0M (5242880 bytes)
+disk size: 196K
+cluster_size: 65536
+Format specific information:
+ compat: 1.1
+ lazy refcounts: false
+
+=== Running QEMU Live Commit Test ===
+
+{"return": {}}
+{"return": {}}
+{"timestamp": {"seconds": TIMESTAMP, "microseconds": TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "test", "len": 104857600, "offset": 104857600, "speed": 0, "type": "commit"}}
+
+=== Base image info after commit and resize ===
+image: TEST_DIR/t.qcow2.base
+file format: qcow2
+virtual size: 100M (104857600 bytes)
+disk size: 196K
+cluster_size: 65536
+Format specific information:
+ compat: 1.1
+ lazy refcounts: false
+*** done
diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index e2ed5a95f..8ca40116d 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -34,22 +34,95 @@ timestamp=${TIMESTAMP:=false}
# generic initialization
iam=check
+_init_error()
+{
+ echo "$iam: $1" >&2
+ exit 1
+}
+
+if [ -L "$0" ]
+then
+ # called from the build tree
+ source_iotests=$(dirname "$(readlink "$0")")
+ if [ -z "$source_iotests" ]
+ then
+ _init_error "failed to obtain source tree name from check symlink"
+ fi
+ source_iotests=$(cd "$source_iotests"; pwd) || _init_error "failed to enter source tree"
+ build_iotests=$PWD
+else
+ # called from the source tree
+ source_iotests=$PWD
+ # this may be an in-tree build (note that in the following code we may not
+ # assume that it truly is and have to test whether the build results
+ # actually exist)
+ build_iotests=$PWD
+fi
+
+build_root="$build_iotests/../.."
+
+if [ -x "$build_iotests/socket_scm_helper" ]
+then
+ export SOCKET_SCM_HELPER="$build_iotests/socket_scm_helper"
+fi
+
+# if ./qemu exists, it should be prioritized and will be chosen by common.config
+if [[ -z "$QEMU_PROG" && ! -x './qemu' ]]
+then
+ arch=$(uname -m 2> /dev/null)
+
+ if [[ -n $arch && -x "$build_root/$arch-softmmu/qemu-system-$arch" ]]
+ then
+ export QEMU_PROG="$build_root/$arch-softmmu/qemu-system-$arch"
+ else
+ pushd "$build_root" > /dev/null
+ for binary in *-softmmu/qemu-system-*
+ do
+ if [ -x "$binary" ]
+ then
+ export QEMU_PROG="$build_root/$binary"
+ break
+ fi
+ done
+ popd > /dev/null
+ fi
+fi
+
+if [[ -z $QEMU_IMG_PROG && -x "$build_root/qemu-img" && ! -x './qemu-img' ]]
+then
+ export QEMU_IMG_PROG="$build_root/qemu-img"
+fi
+
+if [[ -z $QEMU_IO_PROG && -x "$build_root/qemu-io" && ! -x './qemu-io' ]]
+then
+ export QEMU_IO_PROG="$build_root/qemu-io"
+fi
+
+if [[ -z $QEMU_NBD_PROG && -x "$build_root/qemu-nbd" && ! -x './qemu-nbd' ]]
+then
+ export QEMU_NBD_PROG="$build_root/qemu-nbd"
+fi
+
+# we need common.env
+if ! . "$build_iotests/common.env"
+then
+ _init_error "failed to source common.env (make sure the qemu-iotests are run from tests/qemu-iotests in the build tree)"
+fi
+
# we need common.config
-if ! . ./common.config
+if ! . "$source_iotests/common.config"
then
- echo "$iam: failed to source common.config"
- exit 1
+ _init_error "failed to source common.config"
fi
# we need common.rc
-if ! . ./common.rc
+if ! . "$source_iotests/common.rc"
then
- echo "check: failed to source common.rc"
- exit 1
+ _init_error "failed to source common.rc"
fi
# we need common
-. ./common
+. "$source_iotests/common"
#if [ `id -u` -ne 0 ]
#then
@@ -194,7 +267,7 @@ do
echo " - expunged"
rm -f $seq.out.bad
echo "/^$seq\$/d" >>$tmp.expunged
- elif [ ! -f $seq ]
+ elif [ ! -f "$source_iotests/$seq" ]
then
echo " - no such test?"
echo "/^$seq\$/d" >>$tmp.expunged
@@ -215,9 +288,16 @@ do
start=`_wallclock`
$timestamp && echo -n " ["`date "+%T"`"]"
- [ ! -x $seq ] && chmod u+x $seq # ensure we can run it
+
+ if [ "$(head -n 1 "$source_iotests/$seq")" == "#!/usr/bin/env python" ]; then
+ run_command="$PYTHON $seq"
+ else
+ run_command="./$seq"
+ fi
+ export OUTPUT_DIR=$PWD
+ (cd "$source_iotests";
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(($RANDOM % 255 + 1))} \
- ./$seq >$tmp.out 2>&1
+ $run_command >$tmp.out 2>&1)
sts=$?
$timestamp && _timestamp
stop=`_wallclock`
@@ -242,17 +322,17 @@ do
err=true
fi
- reference=$seq.out
+ reference="$source_iotests/$seq.out"
if [ "$CACHEMODE" = "none" ]; then
- [ -f $seq.out.nocache ] && reference=$seq.out.nocache
+ [ -f "$source_iotests/$seq.out.nocache" ] && reference="$source_iotests/$seq.out.nocache"
fi
- if [ ! -f $reference ]
+ if [ ! -f "$reference" ]
then
echo " - no qualified output"
err=true
else
- if diff -w $reference $tmp.out >/dev/null 2>&1
+ if diff -w "$reference" $tmp.out >/dev/null 2>&1
then
echo ""
if $err
@@ -264,7 +344,7 @@ do
else
echo " - output mismatch (see $seq.out.bad)"
mv $tmp.out $seq.out.bad
- $diff -w $reference $seq.out.bad
+ $diff -w "$reference" $seq.out.bad
err=true
fi
fi
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index 0aaf84d01..e4083f421 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -25,8 +25,7 @@ _setenvironment()
export MSGVERB
}
-here=`pwd`
-rm -f $here/$iam.out
+rm -f "$OUTPUT_DIR/$iam.out"
_setenvironment
check=${check-true}
@@ -59,7 +58,7 @@ do
if $group
then
# arg after -g
- group_list=`sed -n <group -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
+ group_list=`sed -n <"$source_iotests/group" -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
s/ .*//p
}'`
if [ -z "$group_list" ]
@@ -84,7 +83,7 @@ s/ .*//p
then
# arg after -x
[ ! -s $tmp.list ] && ls [0-9][0-9][0-9] [0-9][0-9][0-9][0-9] >$tmp.list 2>/dev/null
- group_list=`sed -n <group -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
+ group_list=`sed -n <"$source_iotests/group" -e 's/$/ /' -e "/^[0-9][0-9][0-9].* $r /"'{
s/ .*//p
}'`
if [ -z "$group_list" ]
@@ -366,7 +365,7 @@ testlist options
BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \
| while read id
do
- if grep -s "^$id " group >/dev/null
+ if grep -s "^$id " "$source_iotests/group" >/dev/null
then
# in group file ... OK
echo $id >>$tmp.list
@@ -402,7 +401,7 @@ else
touch $tmp.list
else
# no test numbers, do everything from group file
- sed -n -e '/^[0-9][0-9][0-9]*/s/[ ].*//p' <group >$tmp.list
+ sed -n -e '/^[0-9][0-9][0-9]*/s/[ ].*//p' <"$source_iotests/group" >$tmp.list
fi
fi
diff --git a/tests/qemu-iotests/common.config b/tests/qemu-iotests/common.config
index d90a8bca8..bd6790be6 100644
--- a/tests/qemu-iotests/common.config
+++ b/tests/qemu-iotests/common.config
@@ -126,7 +126,7 @@ fi
export TEST_DIR
if [ -z "$SAMPLE_IMG_DIR" ]; then
- SAMPLE_IMG_DIR=`pwd`/sample_images
+ SAMPLE_IMG_DIR="$source_iotests/sample_images"
fi
if [ ! -d "$SAMPLE_IMG_DIR" ]; then
diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter
index 776985d15..a04df7f6d 100644
--- a/tests/qemu-iotests/common.filter
+++ b/tests/qemu-iotests/common.filter
@@ -150,6 +150,7 @@ _filter_win32()
_filter_qemu_io()
{
_filter_win32 | sed -e "s/[0-9]* ops\; [0-9/:. sec]* ([0-9/.inf]* [EPTGMKiBbytes]*\/sec and [0-9/.inf]* ops\/sec)/X ops\; XX:XX:XX.X (XXX YYY\/sec and XXX ops\/sec)/" \
+ -e "s/: line [0-9][0-9]*: *[0-9][0-9]*\( Aborted\)/:\1/" \
-e "s/qemu-io> //g"
}
diff --git a/tests/qemu-iotests/common.qemu b/tests/qemu-iotests/common.qemu
new file mode 100644
index 000000000..ee7ebb4c1
--- /dev/null
+++ b/tests/qemu-iotests/common.qemu
@@ -0,0 +1,200 @@
+#!/bin/bash
+#
+# This allows for launching of multiple QEMU instances, with independent
+# communication possible to each instance.
+#
+# Each instance can choose, at launch, to use either the QMP or the
+# HMP (monitor) interface.
+#
+# All instances are cleaned up via _cleanup_qemu, including killing the
+# running qemu instance.
+#
+# Copyright (C) 2014 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/>.
+#
+
+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
+# file descriptor values assigned.
+_out_fd=3
+_in_fd=4
+
+# Wait for expected QMP response from QEMU. Will time out
+# after 10 seconds, which counts as failure.
+#
+# Override QEMU_COMM_TIMEOUT for a timeout different than the
+# default 10 seconds
+#
+# $1: The handle to use
+# $2+ All remaining arguments comprise the string to search for
+# in the response.
+#
+# If $silent is set to anything but an empty string, then
+# response is not echoed out.
+function _timed_wait_for()
+{
+ local h=${1}
+ shift
+
+ QEMU_STATUS[$h]=0
+ while read -t ${QEMU_COMM_TIMEOUT} resp <&${QEMU_OUT[$h]}
+ do
+ if [ -z "${silent}" ]; then
+ echo "${resp}" | _filter_testdir | _filter_qemu \
+ | _filter_qemu_io | _filter_qmp
+ fi
+ grep -q "${*}" < <(echo ${resp})
+ if [ $? -eq 0 ]; then
+ return
+ fi
+ done
+ QEMU_STATUS[$h]=-1
+ if [ -z "${qemu_error_no_exit}" ]; then
+ echo "Timeout waiting for ${*} on handle ${h}"
+ exit 1 # Timeout means the test failed
+ fi
+}
+
+
+# Sends QMP or HMP command to QEMU, and waits for the expected response
+#
+# $1: QEMU handle to use
+# $2: String of the QMP command to send
+# ${@: -1} (Last string passed)
+# String that the QEMU response should contain. If it is a null
+# string, do not wait for a response
+#
+# Set qemu_cmd_repeat to the number of times to repeat the cmd
+# until either timeout, or a response. If it is not set, or <=0,
+# then the command is only sent once.
+#
+# If $qemu_error_no_exit is set, then even if the expected response
+# is not seen, we will not exit. $QEMU_STATUS[$1] will be set it -1 in
+# that case.
+function _send_qemu_cmd()
+{
+ local h=${1}
+ local count=1
+ local cmd=
+ local use_error=${qemu_error_no_exit}
+ shift
+
+ if [ ${qemu_cmd_repeat} -gt 0 ] 2>/dev/null; then
+ count=${qemu_cmd_repeat}
+ use_error="no"
+ fi
+ # This array element extraction is done to accommodate pathnames with spaces
+ cmd=${@: 1:${#@}-1}
+ shift $(($# - 1))
+
+ while [ ${count} -gt 0 ]
+ do
+ echo "${cmd}" >&${QEMU_IN[${h}]}
+ if [ -n "${1}" ]; then
+ qemu_error_no_exit=${use_error} _timed_wait_for ${h} "${1}"
+ if [ ${QEMU_STATUS[$h]} -eq 0 ]; then
+ return
+ fi
+ fi
+ let count--;
+ done
+ if [ ${QEMU_STATUS[$h]} -ne 0 ] && [ -z "${qemu_error_no_exit}" ]; then
+ echo "Timeout waiting for ${1} on handle ${h}"
+ exit 1 #Timeout means the test failed
+ fi
+}
+
+
+# Launch a QEMU process.
+#
+# Input parameters:
+# $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.
+# Returns:
+# $QEMU_HANDLE: set to a handle value to communicate with this QEMU instance.
+#
+function _launch_qemu()
+{
+ local comm=
+ local fifo_out=
+ local fifo_in=
+
+ if (shopt -s nocasematch; [[ "${qemu_comm_method}" == "monitor" ]])
+ then
+ comm="-monitor stdio"
+ else
+ local qemu_comm_method="qmp"
+ comm="-monitor none -qmp stdio"
+ fi
+
+ fifo_out=${QEMU_FIFO_OUT}_${_QEMU_HANDLE}
+ fifo_in=${QEMU_FIFO_IN}_${_QEMU_HANDLE}
+ mkfifo "${fifo_out}"
+ mkfifo "${fifo_in}"
+
+ "${QEMU}" -nographic -serial none ${comm} -machine accel=qtest "${@}" 2>&1 \
+ >"${fifo_out}" \
+ <"${fifo_in}" &
+ QEMU_PID[${_QEMU_HANDLE}]=$!
+
+ if [[ "${BASH_VERSINFO[0]}" -ge "5" ||
+ ("${BASH_VERSINFO[0]}" -ge "4" && "${BASH_VERSINFO[1]}" -ge "1") ]]
+ then
+ # bash >= 4.1 required for automatic fd
+ exec {_out_fd}<"${fifo_out}"
+ exec {_in_fd}>"${fifo_in}"
+ else
+ let _out_fd++
+ let _in_fd++
+ eval "exec ${_out_fd}<'${fifo_out}'"
+ eval "exec ${_in_fd}>'${fifo_in}'"
+ fi
+
+ QEMU_OUT[${_QEMU_HANDLE}]=${_out_fd}
+ QEMU_IN[${_QEMU_HANDLE}]=${_in_fd}
+ QEMU_STATUS[${_QEMU_HANDLE}]=0
+
+ if [ "${qemu_comm_method}" == "qmp" ]
+ then
+ # Don't print response, since it has version information in it
+ silent=yes _timed_wait_for ${_QEMU_HANDLE} "capabilities"
+ fi
+ QEMU_HANDLE=${_QEMU_HANDLE}
+ let _QEMU_HANDLE++
+}
+
+
+# Silenty kills the QEMU process
+function _cleanup_qemu()
+{
+ # QEMU_PID[], QEMU_IN[], QEMU_OUT[] all use same indices
+ for i in "${!QEMU_OUT[@]}"
+ do
+ kill -KILL ${QEMU_PID[$i]} 2>/dev/null
+ wait ${QEMU_PID[$i]} 2>/dev/null # silent kill
+ rm -f "${QEMU_FIFO_IN}_${i}" "${QEMU_FIFO_OUT}_${i}"
+ eval "exec ${QEMU_IN[$i]}<&-" # close file descriptors
+ eval "exec ${QEMU_OUT[$i]}<&-"
+ done
+}
diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc
index 7f00883ca..e0ea7e3a7 100644
--- a/tests/qemu-iotests/common.rc
+++ b/tests/qemu-iotests/common.rc
@@ -178,10 +178,10 @@ _rm_test_img()
local img=$1
if [ "$IMGFMT" = "vmdk" ]; then
# Remove all the extents for vmdk
- $QEMU_IMG info $img 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
+ "$QEMU_IMG" info "$img" 2>/dev/null | grep 'filename:' | cut -f 2 -d: \
| xargs -I {} rm -f "{}"
fi
- rm -f $img
+ rm -f "$img"
}
_cleanup_test_img()
@@ -318,9 +318,9 @@ _do()
status=1; exit
fi
- (eval "echo '---' \"$_cmd\"") >>$here/$seq.full
+ (eval "echo '---' \"$_cmd\"") >>"$OUTPUT_DIR/$seq.full"
(eval "$_cmd") >$tmp._out 2>&1; ret=$?
- cat $tmp._out >>$here/$seq.full
+ cat $tmp._out >>"$OUTPUT_DIR/$seq.full"
if [ $# -eq 2 ]; then
if [ $ret -eq 0 ]; then
echo "done"
@@ -344,7 +344,7 @@ _do()
#
_notrun()
{
- echo "$*" >$seq.notrun
+ echo "$*" >"$OUTPUT_DIR/$seq.notrun"
echo "$seq not run: $*"
status=0
exit
@@ -354,7 +354,7 @@ _notrun()
#
_fail()
{
- echo "$*" | tee -a $here/$seq.full
+ echo "$*" | tee -a "$OUTPUT_DIR/$seq.full"
echo "(see $seq.full for details)"
status=1
exit 1
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index 864643d25..6e67f6126 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -7,16 +7,16 @@
#
# test-group association ... one line per test
#
-001 rw auto
+001 rw auto quick
002 rw auto quick
003 rw auto
004 rw auto quick
-005 img auto
+005 img auto quick
006 img auto
007 snapshot auto
-008 rw auto
-009 rw auto
-010 rw auto
+008 rw auto quick
+009 rw auto quick
+010 rw auto quick
011 rw auto quick
012 auto quick
013 rw auto
@@ -24,36 +24,36 @@
015 rw snapshot auto
016 rw auto quick
017 rw backing auto quick
-018 rw backing auto
+018 rw backing auto quick
019 rw backing auto quick
020 rw backing auto quick
-021 io auto
+021 io auto quick
022 rw snapshot auto
023 rw auto
024 rw backing auto quick
025 rw auto quick
026 rw blkdbg auto
027 rw auto quick
-028 rw backing auto
+028 rw backing auto quick
029 rw auto quick
030 rw auto backing
031 rw auto quick
-032 rw auto
+032 rw auto quick
033 rw auto quick
-034 rw auto backing
+034 rw auto backing quick
035 rw auto quick
036 rw auto quick
-037 rw auto backing
-038 rw auto backing
-039 rw auto
+037 rw auto backing quick
+038 rw auto backing quick
+039 rw auto quick
040 rw auto
041 rw auto backing
042 rw auto quick
043 rw auto backing
044 rw auto
-045 rw auto
-046 rw auto aio
-047 rw auto
+045 rw auto quick
+046 rw auto aio quick
+047 rw auto quick
048 img auto quick
049 rw auto
050 rw auto backing quick
@@ -71,27 +71,32 @@
062 rw auto quick
063 rw auto quick
064 rw auto quick
-065 rw auto
+065 rw auto quick
066 rw auto quick
-067 rw auto
-068 rw auto
+067 rw auto quick
+068 rw auto quick
069 rw auto quick
070 rw auto quick
-071 rw auto
+071 rw auto quick
072 rw auto quick
073 rw auto quick
074 rw auto quick
-075 rw auto
+075 rw auto quick
076 auto
077 rw auto quick
-078 rw auto
+078 rw auto quick
079 rw auto
080 rw auto
-081 rw auto
+081 rw auto quick
082 rw auto quick
083 rw auto
-084 img auto
+084 img auto quick
085 rw auto
086 rw auto quick
-087 rw auto
-088 rw auto
+087 rw auto quick
+088 rw auto quick
+089 rw auto quick
+090 rw auto quick
+091 rw auto quick
+092 rw auto quick
+095 rw auto quick
diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py
index e4fa9af71..39a4cfcf4 100644
--- a/tests/qemu-iotests/iotests.py
+++ b/tests/qemu-iotests/iotests.py
@@ -37,6 +37,7 @@ qemu_args = os.environ.get('QEMU', 'qemu').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')
socket_scm_helper = os.environ.get('SOCKET_SCM_HELPER', 'socket_scm_helper')
@@ -257,7 +258,7 @@ class QMPTestCase(unittest.TestCase):
self.assert_no_active_block_jobs()
return result
- def wait_until_completed(self, drive='drive0'):
+ def wait_until_completed(self, drive='drive0', check_offset=True):
'''Wait for a block job to finish, returning the event'''
completed = False
while not completed:
@@ -265,7 +266,8 @@ class QMPTestCase(unittest.TestCase):
if event['event'] == 'BLOCK_JOB_COMPLETED':
self.assert_qmp(event, 'data/device', drive)
self.assert_qmp_absent(event, 'data/error')
- self.assert_qmp(event, 'data/offset', self.image_len)
+ if check_offset:
+ self.assert_qmp(event, 'data/offset', self.image_len)
self.assert_qmp(event, 'data/len', self.image_len)
completed = True
@@ -277,7 +279,7 @@ def notrun(reason):
# Each test in qemu-iotests has a number ("seq")
seq = os.path.basename(sys.argv[0])
- open('%s.notrun' % seq, 'wb').write(reason + '\n')
+ open('%s/%s.notrun' % (output_dir, seq), 'wb').write(reason + '\n')
print '%s not run: %s' % (seq, reason)
sys.exit(0)
diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py
index 44a2b4564..205859696 100755
--- a/tests/qemu-iotests/qcow2.py
+++ b/tests/qemu-iotests/qcow2.py
@@ -176,6 +176,10 @@ def cmd_add_header_ext(fd, magic, data):
h.extensions.append(QcowHeaderExtension.create(magic, data))
h.update(fd)
+def cmd_add_header_ext_stdio(fd, magic):
+ data = sys.stdin.read()
+ cmd_add_header_ext(fd, magic, data)
+
def cmd_del_header_ext(fd, magic):
try:
magic = int(magic, 0)
@@ -220,11 +224,12 @@ def cmd_set_feature_bit(fd, group, bit):
h.update(fd)
cmds = [
- [ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
- [ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
- [ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
- [ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
- [ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
+ [ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],
+ [ 'set-header', cmd_set_header, 2, 'Set a field in the header'],
+ [ 'add-header-ext', cmd_add_header_ext, 2, 'Add a header extension' ],
+ [ 'add-header-ext-stdio', cmd_add_header_ext_stdio, 1, 'Add a header extension, data from stdin' ],
+ [ 'del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension' ],
+ [ 'set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
]
def main(filename, cmd, args):
diff --git a/tests/qemu-iotests/sample_images/test-disk2vhd.vhdx.bz2 b/tests/qemu-iotests/sample_images/test-disk2vhd.vhdx.bz2
new file mode 100644
index 000000000..2891c9a6d
--- /dev/null
+++ b/tests/qemu-iotests/sample_images/test-disk2vhd.vhdx.bz2
Binary files differ
diff --git a/tests/qom-test.c b/tests/qom-test.c
index 6d9a00b44..4246382d3 100644
--- a/tests/qom-test.c
+++ b/tests/qom-test.c
@@ -44,7 +44,7 @@ static bool is_blacklisted(const char *arch, const char *mach)
return false;
}
-static void test_properties(const char *path)
+static void test_properties(const char *path, bool recurse)
{
char *child_path;
QDict *response, *tuple;
@@ -53,24 +53,31 @@ static void test_properties(const char *path)
g_test_message("Obtaining properties of %s", path);
response = qmp("{ 'execute': 'qom-list',"
- " 'arguments': { 'path': '%s' } }", path);
+ " 'arguments': { 'path': %s } }", path);
g_assert(response);
+ if (!recurse) {
+ return;
+ }
+
g_assert(qdict_haskey(response, "return"));
list = qobject_to_qlist(qdict_get(response, "return"));
QLIST_FOREACH_ENTRY(list, entry) {
tuple = qobject_to_qdict(qlist_entry_obj(entry));
- if (strstart(qdict_get_str(tuple, "type"), "child<", NULL)) {
+ bool is_child = strstart(qdict_get_str(tuple, "type"), "child<", NULL);
+ bool is_link = strstart(qdict_get_str(tuple, "type"), "link<", NULL);
+
+ if (is_child || is_link) {
child_path = g_strdup_printf("%s/%s",
path, qdict_get_str(tuple, "name"));
- test_properties(child_path);
+ test_properties(child_path, is_child);
g_free(child_path);
} 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' } }",
+ " 'arguments': { 'path': %s,"
+ " 'property': %s } }",
path, prop);
/* qom-get may fail but should not, e.g., segfault. */
g_assert(response);
@@ -87,7 +94,7 @@ static void test_machine(gconstpointer data)
args = g_strdup_printf("-machine %s", machine);
qtest_start(args);
- test_properties("/machine");
+ test_properties("/machine", true);
response = qmp("{ 'execute': 'quit' }");
g_assert(qdict_haskey(response, "return"));
diff --git a/tests/tcg/Makefile b/tests/tcg/Makefile
index 24e3154ca..89e3342f3 100644
--- a/tests/tcg/Makefile
+++ b/tests/tcg/Makefile
@@ -81,10 +81,8 @@ run-test_path: test_path
# rules to compile tests
test_path: test_path.o
- $(CC_I386) $(LDFLAGS) -o $@ $^ $(LIBS)
test_path.o: test_path.c
- $(CC_I386) $(QEMU_INCLUDES) $(GLIB_CFLAGS) $(CFLAGS) -c -o $@ $^
hello-i386: hello-i386.c
$(CC_I386) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $<
diff --git a/tests/tcg/lm32/Makefile b/tests/tcg/lm32/Makefile
index 8e5d40545..57e7363b2 100644
--- a/tests/tcg/lm32/Makefile
+++ b/tests/tcg/lm32/Makefile
@@ -3,7 +3,7 @@
CROSS=lm32-elf-
SIM = qemu-system-lm32
-SIMFLAGS = -M lm32-evr -nographic -device lm32-sys -net none -kernel
+SIMFLAGS = -M lm32-evr -nographic -semihosting -net none -kernel
CC = $(CROSS)gcc
AS = $(CROSS)as
@@ -18,6 +18,7 @@ LDFLAGS = -T$(TSRC_PATH)/linker.ld
ASFLAGS += -Wa,-I,$(TSRC_PATH)/
CRT = crt.o
+HELPER = helper.o
TESTCASES += test_add.tst
TESTCASES += test_addi.tst
TESTCASES += test_and.tst
@@ -91,15 +92,15 @@ all: build
%.o: $(TSRC_PATH)/%.S
$(AS) $(ASFLAGS) -c $< -o $@
-%.tst: %.o $(TSRC_PATH)/macros.inc $(CRT)
- $(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $< -o $@
+%.tst: %.o $(TSRC_PATH)/macros.inc $(CRT) $(HELPER)
+ $(LD) $(LDFLAGS) $(NOSTDFLAGS) $(CRT) $(HELPER) $< -o $@
-build: $(CRT) $(TESTCASES)
+build: $(TESTCASES)
check: $(TESTCASES:test_%.tst=check_%)
-check_%: test_%.tst $(CRT) $(SYS)
- $(SIM) $(SIMFLAGS) $<
+check_%: test_%.tst
+ @$(SIM) $(SIMFLAGS) $<
clean:
- $(RM) -fr $(TESTCASES) $(CRT)
+ $(RM) -fr $(TESTCASES) $(CRT) $(HELPER)
diff --git a/tests/tcg/lm32/crt.S b/tests/tcg/lm32/crt.S
index 5f9cfd95d..fc437a3de 100644
--- a/tests/tcg/lm32/crt.S
+++ b/tests/tcg/lm32/crt.S
@@ -8,9 +8,9 @@ _reset_handler:
ori r1, r1, lo(_start)
wcsr eba, r1
wcsr deba, r1
+ mvhi sp, hi(_fstack)
+ ori sp, sp, lo(_fstack)
bi _main
- nop
- nop
_breakpoint_handler:
ori r25, r25, 1
diff --git a/tests/tcg/lm32/helper.S b/tests/tcg/lm32/helper.S
new file mode 100644
index 000000000..3351d41e8
--- /dev/null
+++ b/tests/tcg/lm32/helper.S
@@ -0,0 +1,65 @@
+.text
+.global _start, _write, _exit
+.global _tc_fail, _tc_pass
+
+_write:
+ addi sp, sp, -4
+ sw (sp+4), r8
+ mvi r8, 5
+ scall
+ lw r8, (sp+4)
+ addi sp, sp, 4
+ ret
+
+_exit:
+ mvi r8, 1
+ scall
+1:
+ bi 1b
+
+_tc_pass:
+.data
+1:
+ .ascii "OK\n"
+2:
+.text
+ addi sp, sp, -16
+ sw (sp+4), ra
+ sw (sp+8), r1
+ sw (sp+12), r2
+ sw (sp+16), r3
+ mvi r1, 1
+ mvhi r2, hi(1b)
+ ori r2, r2, lo(1b)
+ mvi r3, (2b - 1b)
+ calli _write
+ lw r3, (sp+16)
+ lw r2, (sp+12)
+ lw r1, (sp+8)
+ lw ra, (sp+4)
+ addi sp, sp, 16
+ ret
+
+_tc_fail:
+.data
+1:
+ .ascii "FAILED\n"
+2:
+.text
+ addi sp, sp, -16
+ sw (sp+4), ra
+ sw (sp+8), r1
+ sw (sp+12), r2
+ sw (sp+16), r3
+ sw (sp+4), ra
+ mvi r1, 1
+ mvhi r2, hi(1b)
+ ori r2, r2, lo(1b)
+ mvi r3, (2b - 1b)
+ calli _write
+ lw r3, (sp+16)
+ lw r2, (sp+12)
+ lw r1, (sp+8)
+ lw ra, (sp+4)
+ addi sp, sp, 16
+ ret
diff --git a/tests/tcg/lm32/macros.inc b/tests/tcg/lm32/macros.inc
index 367c7c50d..360ad53c9 100644
--- a/tests/tcg/lm32/macros.inc
+++ b/tests/tcg/lm32/macros.inc
@@ -1,12 +1,26 @@
+.equ MAX_TESTNAME_LEN, 32
.macro test_name name
.data
tn_\name:
- .asciz "\name"
+ .ascii "\name"
+ .space MAX_TESTNAME_LEN - (. - tn_\name), ' '
.text
- mvhi r13, hi(tn_\name)
- ori r13, r13, lo(tn_\name)
- sw (r12+8), r13
+ .global \name
+\name:
+ addi sp, sp, -12
+ sw (sp+4), r1
+ sw (sp+8), r2
+ sw (sp+12), r3
+ mvi r1, 1
+ mvhi r2, hi(tn_\name)
+ ori r2, r2, lo(tn_\name)
+ mvi r3, MAX_TESTNAME_LEN
+ calli _write
+ lw r3, (sp+12)
+ lw r2, (sp+8)
+ lw r1, (sp+4)
+ addi sp, sp, 12
.endm
.macro load reg val
@@ -15,13 +29,12 @@ tn_\name:
.endm
.macro tc_pass
- mvi r13, 0
- sw (r12+4), r13
+ calli _tc_pass
.endm
.macro tc_fail
- mvi r13, 1
- sw (r12+4), r13
+ addi r12, r12, 1
+ calli _tc_fail
.endm
.macro check_r3 val
@@ -63,14 +76,12 @@ tn_\name:
.global _main
.text
_main:
- mvhi r12, hi(0xffff0000) # base address of test block
- ori r12, r12, lo(0xffff0000)
+ mvi r12, 0
.endm
.macro end
- sw (r12+0), r0
-1:
- bi 1b
+ mv r1, r12
+ calli _exit
.endm
# base +
diff --git a/tests/tcg/lm32/test_lb.S b/tests/tcg/lm32/test_lb.S
index f84d21ead..d677eea4c 100644
--- a/tests/tcg/lm32/test_lb.S
+++ b/tests/tcg/lm32/test_lb.S
@@ -8,10 +8,12 @@ lb r3, (r1+0)
check_r3 0x7e
test_name LB_2
+load r1 data
lb r3, (r1+1)
check_r3 0x7f
test_name LB_3
+load r1 data
lb r3, (r1+-1)
check_r3 0x7d
@@ -21,10 +23,12 @@ lb r3, (r1+0)
check_r3 0xfffffffe
test_name LB_5
+load r1 data_msb
lb r3, (r1+1)
check_r3 0xffffffff
test_name LB_6
+load r1 data_msb
lb r3, (r1+-1)
check_r3 0xfffffffd
diff --git a/tests/tcg/lm32/test_lbu.S b/tests/tcg/lm32/test_lbu.S
index 4c1786ad7..dc5d5f67d 100644
--- a/tests/tcg/lm32/test_lbu.S
+++ b/tests/tcg/lm32/test_lbu.S
@@ -8,10 +8,12 @@ lbu r3, (r1+0)
check_r3 0x7e
test_name LBU_2
+load r1 data
lbu r3, (r1+1)
check_r3 0x7f
test_name LBU_3
+load r1 data
lbu r3, (r1+-1)
check_r3 0x7d
@@ -21,10 +23,12 @@ lbu r3, (r1+0)
check_r3 0xfe
test_name LBU_5
+load r1 data_msb
lbu r3, (r1+1)
check_r3 0xff
test_name LBU_6
+load r1 data_msb
lbu r3, (r1+-1)
check_r3 0xfd
diff --git a/tests/tcg/lm32/test_lh.S b/tests/tcg/lm32/test_lh.S
index e57d9e35c..397996bdd 100644
--- a/tests/tcg/lm32/test_lh.S
+++ b/tests/tcg/lm32/test_lh.S
@@ -8,10 +8,12 @@ lh r3, (r1+0)
check_r3 0x7e7f
test_name LH_2
+load r1 data
lh r3, (r1+2)
check_r3 0x7071
test_name LH_3
+load r1 data
lh r3, (r1+-2)
check_r3 0x7c7d
@@ -21,10 +23,12 @@ lh r3, (r1+0)
check_r3 0xfffffeff
test_name LH_5
+load r1 data_msb
lh r3, (r1+2)
check_r3 0xfffff0f1
test_name LH_6
+load r1 data_msb
lh r3, (r1+-2)
check_r3 0xfffffcfd
diff --git a/tests/tcg/lm32/test_lhu.S b/tests/tcg/lm32/test_lhu.S
index e648775d9..8de7c5256 100644
--- a/tests/tcg/lm32/test_lhu.S
+++ b/tests/tcg/lm32/test_lhu.S
@@ -8,10 +8,12 @@ lhu r3, (r1+0)
check_r3 0x7e7f
test_name LHU_2
+load r1 data
lhu r3, (r1+2)
check_r3 0x7071
test_name LHU_3
+load r1 data
lhu r3, (r1+-2)
check_r3 0x7c7d
@@ -21,10 +23,12 @@ lhu r3, (r1+0)
check_r3 0xfeff
test_name LHU_5
+load r1 data_msb
lhu r3, (r1+2)
check_r3 0xf0f1
test_name LHU_6
+load r1 data_msb
lhu r3, (r1+-2)
check_r3 0xfcfd
diff --git a/tests/tcg/lm32/test_lw.S b/tests/tcg/lm32/test_lw.S
index f8c919d2b..996e5f8c8 100644
--- a/tests/tcg/lm32/test_lw.S
+++ b/tests/tcg/lm32/test_lw.S
@@ -8,10 +8,12 @@ lw r3, (r1+0)
check_r3 0x7e7f7071
test_name LW_2
+load r1 data
lw r3, (r1+4)
check_r3 0x72737475
test_name LW_3
+load r1 data
lw r3, (r1+-4)
check_r3 0x7a7b7c7d
diff --git a/tests/tcg/lm32/test_sb.S b/tests/tcg/lm32/test_sb.S
index 89e39d621..b15a89d34 100644
--- a/tests/tcg/lm32/test_sb.S
+++ b/tests/tcg/lm32/test_sb.S
@@ -9,11 +9,13 @@ sb (r1+0), r2
check_mem data 0xaa000000
test_name SB_2
+load r1 data
load r2 0xf0f1f2bb
sb (r1+1), r2
check_mem data 0xaabb0000
test_name SB_3
+load r1 data
load r2 0xf0f1f2cc
sb (r1+-1), r2
check_mem data0 0x000000cc
diff --git a/tests/tcg/lm32/test_scall.S b/tests/tcg/lm32/test_scall.S
index b442e3237..46032f841 100644
--- a/tests/tcg/lm32/test_scall.S
+++ b/tests/tcg/lm32/test_scall.S
@@ -5,6 +5,10 @@ start
test_name SCALL_1
mvi r1, 1
wcsr IE, r1
+# we are running in a semi hosted environment
+# therefore we have to set r8 to some unused system
+# call
+mvi r8, 0
insn:
scall
check_excp 64
diff --git a/tests/tcg/lm32/test_sh.S b/tests/tcg/lm32/test_sh.S
index ea8b3f206..bba10224f 100644
--- a/tests/tcg/lm32/test_sh.S
+++ b/tests/tcg/lm32/test_sh.S
@@ -9,11 +9,13 @@ sh (r1+0), r2
check_mem data 0xaaaa0000
test_name SH_2
+load r1 data
load r2 0xf0f1bbbb
sh (r1+2), r2
check_mem data 0xaaaabbbb
test_name SH_3
+load r1 data
load r2 0xf0f1cccc
sh (r1+-2), r2
check_mem data0 0x0000cccc
diff --git a/tests/tcg/lm32/test_sw.S b/tests/tcg/lm32/test_sw.S
index d1fdadce6..2b1c017e7 100644
--- a/tests/tcg/lm32/test_sw.S
+++ b/tests/tcg/lm32/test_sw.S
@@ -9,16 +9,19 @@ sw (r1+0), r2
check_mem data 0xaabbccdd
test_name SW_2
+load r1 data
load r2 0x00112233
sw (r1+4), r2
check_mem data1 0x00112233
test_name SW_3
+load r1 data
load r2 0x44556677
sw (r1+-4), r2
check_mem data0 0x44556677
test_name SW_4
+load r1 data
sw (r1+0), r1
lw r3, (r1+0)
check_r3 data
diff --git a/tests/tcg/test_path.c b/tests/tcg/test_path.c
index f8dd36aab..1c29bce26 100644
--- a/tests/tcg/test_path.c
+++ b/tests/tcg/test_path.c
@@ -1,17 +1,10 @@
/* Test path override code */
-#define _GNU_SOURCE
#include "config-host.h"
#include "util/cutils.c"
#include "util/hexdump.c"
#include "util/iov.c"
#include "util/path.c"
#include "util/qemu-timer-common.c"
-#include "trace/control.c"
-#include "../trace/generated-events.c"
-#ifdef CONFIG_TRACE_SIMPLE
-#include "trace/simple.c"
-#endif
-
#include <stdarg.h>
#include <sys/stat.h>
#include <fcntl.h>
diff --git a/tests/tcg/xtensa/test_mmu.S b/tests/tcg/xtensa/test_mmu.S
index 099031fd1..58c5bca30 100644
--- a/tests/tcg/xtensa/test_mmu.S
+++ b/tests/tcg/xtensa/test_mmu.S
@@ -4,16 +4,28 @@ test_suite mmu
.purgem test_init
-.macro test_init
- movi a2, 0x00000004
- idtlb a2
- movi a2, 0x00100004
+.macro clean_tlb_way way, page_size, n_entries
+ movi a2, \way
+ movi a3, \page_size
+ movi a4, \n_entries
+ loop a4, 1f
idtlb a2
- movi a2, 0x00200004
+ iitlb a2
+ add a2, a2, a3
+1:
+.endm
+
+.macro test_init
+ clean_tlb_way 0, 0x00001000, 4
+ clean_tlb_way 1, 0x00001000, 4
+ clean_tlb_way 2, 0x00001000, 4
+ clean_tlb_way 3, 0x00001000, 4
+ clean_tlb_way 4, 0x00100000, 4
+ movi a2, 0x00000007
idtlb a2
- movi a2, 0x00300004
+ movi a2, 0x00000008
idtlb a2
- movi a2, 0x00000007
+ movi a2, 0x00000009
idtlb a2
.endm
@@ -508,4 +520,224 @@ test autoload_3_level_pt
assert_sr exccause, 24
test_end
+test cross_page_insn
+ set_vector kernel, 2f
+
+ movi a2, 0x04000003 /* PPN */
+ movi a3, 0x00007000 /* VPN */
+ witlb a2, a3
+ wdtlb a2, a3
+ movi a3, 0x00008000 /* VPN */
+ witlb a2, a3
+ wdtlb a2, a3
+
+ movi a2, 0x00007fff
+ movi a3, 20f
+ movi a4, 21f
+ sub a4, a4, a3
+ loop a4, 1f
+ l8ui a5, a3, 0
+ s8i a5, a2, 0
+ addi a2, a2, 1
+ addi a3, a3, 1
+1:
+ movi a2, 0x00007fff
+ movi a3, 0x00008000
+ /* DTLB: OK, ITLB: OK */
+ jx a2
+
+ .begin no-transform
+20:
+ l32i a2, a3, 0
+ syscall
+21:
+ .end no-transform
+
+2:
+ rsr a2, exccause
+ movi a3, 1
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x8002
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007fff
+ assert ne, a2, a3
+
+ reset_ps
+ set_vector kernel, 3f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ wdtlb a2, a3
+ movi a2, 0x00007fff
+ movi a3, 0x00008000
+ /* DTLB: FAIL, ITLB: OK */
+ jx a2
+3:
+ rsr a2, exccause
+ movi a3, 28
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7fff
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007fff
+ assert eq, a2, a3
+
+ reset_ps
+ set_vector kernel, 4f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ witlb a2, a3
+ movi a2, 0x04000003 /* PPN */
+ wdtlb a2, a3
+ movi a2, 0x00007fff
+ movi a3, 0x00008000
+ /* DTLB: OK, ITLB: FAIL */
+ jx a2
+4:
+ rsr a2, exccause
+ movi a3, 20
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7fff
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007fff
+ assert eq, a2, a3
+
+ reset_ps
+ set_vector kernel, 5f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ wdtlb a2, a3
+ movi a2, 0x00007fff
+ movi a3, 0x00008000
+ /* DTLB: FAIL, ITLB: FAIL */
+ jx a2
+5:
+ rsr a2, exccause
+ movi a3, 20
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7fff
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007fff
+ assert eq, a2, a3
+test_end
+
+test cross_page_tb
+ set_vector kernel, 2f
+
+ movi a2, 0x04000003 /* PPN */
+ movi a3, 0x00007000 /* VPN */
+ witlb a2, a3
+ wdtlb a2, a3
+ movi a3, 0x00008000 /* VPN */
+ witlb a2, a3
+ wdtlb a2, a3
+
+ movi a2, 0x00007ffd
+ movi a3, 20f
+ movi a4, 21f
+ sub a4, a4, a3
+ loop a4, 1f
+ l8ui a5, a3, 0
+ s8i a5, a2, 0
+ addi a2, a2, 1
+ addi a3, a3, 1
+1:
+ movi a2, 0x00007ffd
+ movi a3, 0x00008000
+ /* DTLB: OK, ITLB: OK */
+ jx a2
+
+ .begin no-transform
+20:
+ l32i a2, a3, 0
+ syscall
+21:
+ .end no-transform
+
+2:
+ rsr a2, exccause
+ movi a3, 1
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x8000
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007ffd
+ assert ne, a2, a3
+
+ reset_ps
+ set_vector kernel, 3f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ wdtlb a2, a3
+ movi a2, 0x00007ffd
+ movi a3, 0x00008000
+ /* DTLB: FAIL, ITLB: OK */
+ jx a2
+3:
+ rsr a2, exccause
+ movi a3, 28
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7ffd
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007ffd
+ assert eq, a2, a3
+
+ reset_ps
+ set_vector kernel, 4f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ witlb a2, a3
+ movi a2, 0x04000003 /* PPN */
+ wdtlb a2, a3
+ movi a2, 0x00007ffd
+ movi a3, 0x00008000
+ /* DTLB: OK, ITLB: FAIL */
+ jx a2
+4:
+ rsr a2, exccause
+ movi a3, 20
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x8000
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007ffd
+ assert ne, a2, a3
+
+ reset_ps
+ set_vector kernel, 5f
+
+ movi a2, 0x0400000c /* PPN */
+ movi a3, 0x00008000 /* VPN */
+ wdtlb a2, a3
+ movi a2, 0x00007ffd
+ movi a3, 0x00008000
+ /* DTLB: FAIL, ITLB: FAIL */
+ jx a2
+5:
+ rsr a2, exccause
+ movi a3, 28
+ assert eq, a2, a3
+ rsr a2, epc1
+ movi a3, 0x7ffd
+ assert eq, a2, a3
+ rsr a2, excsave1
+ movi a3, 0x00007ffd
+ assert eq, a2, a3
+test_end
+
test_suite_end
diff --git a/tests/test-aio.c b/tests/test-aio.c
index e5f8b55d3..f12b6e0ae 100644
--- a/tests/test-aio.c
+++ b/tests/test-aio.c
@@ -15,7 +15,7 @@
#include "qemu/timer.h"
#include "qemu/sockets.h"
-AioContext *ctx;
+static AioContext *ctx;
typedef struct {
EventNotifier e;
@@ -24,14 +24,6 @@ typedef struct {
bool auto_set;
} EventNotifierTestData;
-/* Wait until there are no more BHs or AIO requests */
-static void wait_for_aio(void)
-{
- while (aio_poll(ctx, true)) {
- /* Do nothing */
- }
-}
-
/* Wait until event notifier becomes inactive */
static void wait_until_inactive(EventNotifierTestData *data)
{
@@ -204,7 +196,9 @@ static void test_bh_schedule10(void)
g_assert(aio_poll(ctx, true));
g_assert_cmpint(data.n, ==, 2);
- wait_for_aio();
+ while (data.n < 10) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data.n, ==, 10);
g_assert(!aio_poll(ctx, false));
@@ -252,7 +246,9 @@ static void test_bh_delete_from_cb(void)
qemu_bh_schedule(data1.bh);
g_assert_cmpint(data1.n, ==, 0);
- wait_for_aio();
+ while (data1.n < data1.max) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data1.n, ==, data1.max);
g_assert(data1.bh == NULL);
@@ -287,7 +283,12 @@ static void test_bh_delete_from_cb_many(void)
g_assert_cmpint(data4.n, ==, 1);
g_assert(data1.bh == NULL);
- wait_for_aio();
+ while (data1.n < data1.max ||
+ data2.n < data2.max ||
+ data3.n < data3.max ||
+ data4.n < data4.max) {
+ aio_poll(ctx, true);
+ }
g_assert_cmpint(data1.n, ==, data1.max);
g_assert_cmpint(data2.n, ==, data2.max);
g_assert_cmpint(data3.n, ==, data3.max);
@@ -306,7 +307,7 @@ static void test_bh_flush(void)
qemu_bh_schedule(data.bh);
g_assert_cmpint(data.n, ==, 0);
- wait_for_aio();
+ g_assert(aio_poll(ctx, true));
g_assert_cmpint(data.n, ==, 1);
g_assert(!aio_poll(ctx, false));
@@ -806,17 +807,16 @@ static void test_source_timer_schedule(void)
g_usleep(1 * G_USEC_PER_SEC);
g_assert_cmpint(data.n, ==, 0);
- g_assert(g_main_context_iteration(NULL, false));
+ g_assert(g_main_context_iteration(NULL, true));
g_assert_cmpint(data.n, ==, 1);
+ expiry += data.ns;
- /* The comment above was not kidding when it said this wakes up itself */
- do {
- g_assert(g_main_context_iteration(NULL, true));
- } while (qemu_clock_get_ns(data.clock_type) <= expiry);
- g_usleep(1 * G_USEC_PER_SEC);
- g_main_context_iteration(NULL, false);
+ while (data.n < 2) {
+ g_main_context_iteration(NULL, true);
+ }
g_assert_cmpint(data.n, ==, 2);
+ g_assert(qemu_clock_get_ns(data.clock_type) > expiry);
aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL);
close(pipefd[0]);
diff --git a/tests/test-qdev-global-props.c b/tests/test-qdev-global-props.c
index e4ad173d7..2bef04c76 100644
--- a/tests/test-qdev-global-props.c
+++ b/tests/test-qdev-global-props.c
@@ -150,8 +150,10 @@ static void test_dynamic_globalprop(void)
static GlobalProperty props[] = {
{ TYPE_DYNAMIC_PROPS, "prop1", "101" },
{ TYPE_DYNAMIC_PROPS, "prop2", "102" },
+ { TYPE_DYNAMIC_PROPS"-bad", "prop3", "103", true },
{}
};
+ int all_used;
qdev_prop_register_global_list(props);
@@ -160,6 +162,8 @@ static void test_dynamic_globalprop(void)
g_assert_cmpuint(mt->prop1, ==, 101);
g_assert_cmpuint(mt->prop2, ==, 102);
+ all_used = qdev_prop_check_global();
+ g_assert_cmpuint(all_used, ==, 1);
}
int main(int argc, char **argv)
diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
new file mode 100644
index 000000000..ca08ac523
--- /dev/null
+++ b/tests/test-qemu-opts.c
@@ -0,0 +1,441 @@
+/*
+ * QemuOpts unit-tests.
+ *
+ * Copyright (C) 2014 Leandro Dorileo <l@dorileo.org>
+ *
+ * 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 "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",
+ .head = QTAILQ_HEAD_INITIALIZER(opts_list_01.head),
+ .desc = {
+ {
+ .name = "str1",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "str2",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "str3",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "number1",
+ .type = QEMU_OPT_NUMBER,
+ },
+ { /* end of list */ }
+ },
+};
+
+static QemuOptsList opts_list_02 = {
+ .name = "opts_list_02",
+ .head = QTAILQ_HEAD_INITIALIZER(opts_list_02.head),
+ .desc = {
+ {
+ .name = "str1",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "bool1",
+ .type = QEMU_OPT_BOOL,
+ },{
+ .name = "str2",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "size1",
+ .type = QEMU_OPT_SIZE,
+ },
+ { /* end of list */ }
+ },
+};
+
+static QemuOptsList opts_list_03 = {
+ .name = "opts_list_03",
+ .head = QTAILQ_HEAD_INITIALIZER(opts_list_03.head),
+ .desc = {
+ /* no elements => accept any params */
+ { /* end of list */ }
+ },
+};
+
+static void register_opts(void)
+{
+ qemu_add_opts(&opts_list_01);
+ qemu_add_opts(&opts_list_02);
+ qemu_add_opts(&opts_list_03);
+}
+
+static void test_find_unknown_opts(void)
+{
+ QemuOptsList *list;
+ Error *err = NULL;
+
+ /* should not return anything, we don't have an "unknown" option */
+ list = qemu_find_opts_err("unknown", &err);
+ g_assert(list == NULL);
+ g_assert(err);
+ error_free(err);
+}
+
+static void test_qemu_find_opts(void)
+{
+ QemuOptsList *list;
+
+ /* we have an "opts_list_01" option, should return it */
+ list = qemu_find_opts("opts_list_01");
+ g_assert(list != NULL);
+ g_assert_cmpstr(list->name, ==, "opts_list_01");
+}
+
+static void test_qemu_opts_create(void)
+{
+ QemuOptsList *list;
+ QemuOpts *opts;
+
+ list = qemu_find_opts("opts_list_01");
+ g_assert(list != NULL);
+ g_assert(QTAILQ_EMPTY(&list->head));
+ g_assert_cmpstr(list->name, ==, "opts_list_01");
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+
+ /* create the opts */
+ opts = qemu_opts_create(list, NULL, 0, &error_abort);
+ g_assert(opts != NULL);
+ g_assert(!QTAILQ_EMPTY(&list->head));
+
+ /* now we've create the opts, must find it */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts != NULL);
+
+ qemu_opts_del(opts);
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+}
+
+static void test_qemu_opt_get(void)
+{
+ QemuOptsList *list;
+ QemuOpts *opts;
+ const char *opt = NULL;
+
+ list = qemu_find_opts("opts_list_01");
+ g_assert(list != NULL);
+ g_assert(QTAILQ_EMPTY(&list->head));
+ g_assert_cmpstr(list->name, ==, "opts_list_01");
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+
+ /* create the opts */
+ opts = qemu_opts_create(list, NULL, 0, &error_abort);
+ g_assert(opts != NULL);
+ g_assert(!QTAILQ_EMPTY(&list->head));
+
+ /* haven't set anything to str2 yet */
+ opt = qemu_opt_get(opts, "str2");
+ g_assert(opt == NULL);
+
+ qemu_opt_set(opts, "str2", "value");
+
+ /* now we have set str2, should know about it */
+ opt = qemu_opt_get(opts, "str2");
+ g_assert_cmpstr(opt, ==, "value");
+
+ qemu_opt_set(opts, "str2", "value2");
+
+ /* having reset the value, the returned should be the reset one */
+ opt = qemu_opt_get(opts, "str2");
+ g_assert_cmpstr(opt, ==, "value2");
+
+ qemu_opts_del(opts);
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+}
+
+static void test_qemu_opt_get_bool(void)
+{
+ QemuOptsList *list;
+ QemuOpts *opts;
+ bool opt;
+ int ret;
+
+ list = qemu_find_opts("opts_list_02");
+ g_assert(list != NULL);
+ g_assert(QTAILQ_EMPTY(&list->head));
+ g_assert_cmpstr(list->name, ==, "opts_list_02");
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+
+ /* create the opts */
+ opts = qemu_opts_create(list, NULL, 0, &error_abort);
+ g_assert(opts != NULL);
+ g_assert(!QTAILQ_EMPTY(&list->head));
+
+ /* haven't set anything to bool1 yet, so defval should be returned */
+ opt = qemu_opt_get_bool(opts, "bool1", false);
+ g_assert(opt == false);
+
+ ret = qemu_opt_set_bool(opts, "bool1", true);
+ g_assert(ret == 0);
+
+ /* now we have set bool1, should know about it */
+ opt = qemu_opt_get_bool(opts, "bool1", false);
+ g_assert(opt == true);
+
+ /* having reset the value, opt should be the reset one not defval */
+ ret = qemu_opt_set_bool(opts, "bool1", false);
+ g_assert(ret == 0);
+
+ opt = qemu_opt_get_bool(opts, "bool1", true);
+ g_assert(opt == false);
+
+ qemu_opts_del(opts);
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+}
+
+static void test_qemu_opt_get_number(void)
+{
+ QemuOptsList *list;
+ QemuOpts *opts;
+ uint64_t opt;
+ int ret;
+
+ list = qemu_find_opts("opts_list_01");
+ g_assert(list != NULL);
+ g_assert(QTAILQ_EMPTY(&list->head));
+ g_assert_cmpstr(list->name, ==, "opts_list_01");
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+
+ /* create the opts */
+ opts = qemu_opts_create(list, NULL, 0, &error_abort);
+ g_assert(opts != NULL);
+ g_assert(!QTAILQ_EMPTY(&list->head));
+
+ /* haven't set anything to number1 yet, so defval should be returned */
+ opt = qemu_opt_get_number(opts, "number1", 5);
+ g_assert(opt == 5);
+
+ ret = qemu_opt_set_number(opts, "number1", 10);
+ g_assert(ret == 0);
+
+ /* now we have set number1, should know about it */
+ opt = qemu_opt_get_number(opts, "number1", 5);
+ g_assert(opt == 10);
+
+ /* having reset it, the returned should be the reset one not defval */
+ ret = qemu_opt_set_number(opts, "number1", 15);
+ g_assert(ret == 0);
+
+ opt = qemu_opt_get_number(opts, "number1", 5);
+ g_assert(opt == 15);
+
+ qemu_opts_del(opts);
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+}
+
+static void test_qemu_opt_get_size(void)
+{
+ QemuOptsList *list;
+ QemuOpts *opts;
+ uint64_t opt;
+ QDict *dict;
+
+ list = qemu_find_opts("opts_list_02");
+ g_assert(list != NULL);
+ g_assert(QTAILQ_EMPTY(&list->head));
+ g_assert_cmpstr(list->name, ==, "opts_list_02");
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+
+ /* create the opts */
+ opts = qemu_opts_create(list, NULL, 0, &error_abort);
+ g_assert(opts != NULL);
+ g_assert(!QTAILQ_EMPTY(&list->head));
+
+ /* haven't set anything to size1 yet, so defval should be returned */
+ opt = qemu_opt_get_size(opts, "size1", 5);
+ g_assert(opt == 5);
+
+ dict = qdict_new();
+ g_assert(dict != NULL);
+
+ qdict_put(dict, "size1", qstring_from_str("10"));
+
+ qemu_opts_absorb_qdict(opts, dict, &error_abort);
+ g_assert(error_abort == NULL);
+
+ /* now we have set size1, should know about it */
+ opt = qemu_opt_get_size(opts, "size1", 5);
+ g_assert(opt == 10);
+
+ /* reset value */
+ qdict_put(dict, "size1", qstring_from_str("15"));
+
+ qemu_opts_absorb_qdict(opts, dict, &error_abort);
+ g_assert(error_abort == NULL);
+
+ /* test the reset value */
+ opt = qemu_opt_get_size(opts, "size1", 5);
+ g_assert(opt == 15);
+
+ qdict_del(dict, "size1");
+ g_free(dict);
+
+ qemu_opts_del(opts);
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+}
+
+static void test_qemu_opt_unset(void)
+{
+ QemuOpts *opts;
+ const char *value;
+ int ret;
+
+ /* dynamically initialized (parsed) opts */
+ opts = qemu_opts_parse(&opts_list_03, "key=value", 0);
+ g_assert(opts != NULL);
+
+ /* check default/parsed value */
+ value = qemu_opt_get(opts, "key");
+ g_assert_cmpstr(value, ==, "value");
+
+ /* reset it to value2 */
+ qemu_opt_set(opts, "key", "value2");
+
+ value = qemu_opt_get(opts, "key");
+ g_assert_cmpstr(value, ==, "value2");
+
+ /* unset, valid only for "accept any" */
+ ret = qemu_opt_unset(opts, "key");
+ g_assert(ret == 0);
+
+ /* after reset the value should be the parsed/default one */
+ value = qemu_opt_get(opts, "key");
+ g_assert_cmpstr(value, ==, "value");
+
+ qemu_opts_del(opts);
+}
+
+static void test_qemu_opts_reset(void)
+{
+ QemuOptsList *list;
+ QemuOpts *opts;
+ uint64_t opt;
+ int ret;
+
+ list = qemu_find_opts("opts_list_01");
+ g_assert(list != NULL);
+ g_assert(QTAILQ_EMPTY(&list->head));
+ g_assert_cmpstr(list->name, ==, "opts_list_01");
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+
+ /* create the opts */
+ opts = qemu_opts_create(list, NULL, 0, &error_abort);
+ g_assert(opts != NULL);
+ g_assert(!QTAILQ_EMPTY(&list->head));
+
+ /* haven't set anything to number1 yet, so defval should be returned */
+ opt = qemu_opt_get_number(opts, "number1", 5);
+ g_assert(opt == 5);
+
+ ret = qemu_opt_set_number(opts, "number1", 10);
+ g_assert(ret == 0);
+
+ /* now we have set number1, should know about it */
+ opt = qemu_opt_get_number(opts, "number1", 5);
+ g_assert(opt == 10);
+
+ qemu_opts_reset(list);
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+}
+
+static void test_qemu_opts_set(void)
+{
+ QemuOptsList *list;
+ QemuOpts *opts;
+ int ret;
+ const char *opt;
+
+ list = qemu_find_opts("opts_list_01");
+ g_assert(list != NULL);
+ g_assert(QTAILQ_EMPTY(&list->head));
+ g_assert_cmpstr(list->name, ==, "opts_list_01");
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+
+ /* implicitly create opts and set str3 value */
+ ret = qemu_opts_set(list, NULL, "str3", "value");
+ g_assert(ret == 0);
+ g_assert(!QTAILQ_EMPTY(&list->head));
+
+ /* get the just created opts */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts != NULL);
+
+ /* check the str3 value */
+ opt = qemu_opt_get(opts, "str3");
+ g_assert_cmpstr(opt, ==, "value");
+
+ qemu_opts_del(opts);
+
+ /* should not find anything at this point */
+ opts = qemu_opts_find(list, NULL);
+ g_assert(opts == NULL);
+}
+
+int main(int argc, char *argv[])
+{
+ register_opts();
+ g_test_init(&argc, &argv, NULL);
+ g_test_add_func("/qemu-opts/find_unknown_opts", test_find_unknown_opts);
+ g_test_add_func("/qemu-opts/find_opts", test_qemu_find_opts);
+ g_test_add_func("/qemu-opts/opts_create", test_qemu_opts_create);
+ g_test_add_func("/qemu-opts/opt_get", test_qemu_opt_get);
+ g_test_add_func("/qemu-opts/opt_get_bool", test_qemu_opt_get_bool);
+ g_test_add_func("/qemu-opts/opt_get_number", test_qemu_opt_get_number);
+ g_test_add_func("/qemu-opts/opt_get_size", test_qemu_opt_get_size);
+ g_test_add_func("/qemu-opts/opt_unset", test_qemu_opt_unset);
+ g_test_add_func("/qemu-opts/opts_reset", test_qemu_opts_reset);
+ g_test_add_func("/qemu-opts/opts_set", test_qemu_opts_set);
+ g_test_run();
+ return 0;
+}
diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c
new file mode 100644
index 000000000..cb354e6e8
--- /dev/null
+++ b/tests/test-qmp-event.c
@@ -0,0 +1,271 @@
+/*
+ * qapi event unit-tests.
+ *
+ * Copyright (c) 2014 Wenchao Xia
+ *
+ * Authors:
+ * Wenchao Xia <wenchaoqemu@gmail.com>
+ *
+ * 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 <glib.h>
+#include <stdarg.h>
+
+#include "qemu-common.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "test-qapi-event.h"
+#include "qapi/qmp/types.h"
+#include "qapi/qmp/qint.h"
+#include "qapi/qmp/qobject.h"
+#include "qapi/qmp-event.h"
+
+typedef struct TestEventData {
+ QDict *expect;
+} TestEventData;
+
+typedef struct QDictCmpData {
+ QDict *expect;
+ bool result;
+} QDictCmpData;
+
+TestEventData *test_event_data;
+static CompatGMutex test_event_lock;
+
+/* Only compares bool, int, string */
+static
+void qdict_cmp_do_simple(const char *key, QObject *obj1, void *opaque)
+
+{
+ QObject *obj2;
+ QDictCmpData d_new, *d = opaque;
+
+ if (!d->result) {
+ return;
+ }
+
+ obj2 = qdict_get(d->expect, key);
+ if (!obj2) {
+ d->result = false;
+ return;
+ }
+
+ if (qobject_type(obj1) != qobject_type(obj2)) {
+ d->result = false;
+ return;
+ }
+
+ switch (qobject_type(obj1)) {
+ case QTYPE_QBOOL:
+ d->result = (qbool_get_int(qobject_to_qbool(obj1)) ==
+ qbool_get_int(qobject_to_qbool(obj2)));
+ return;
+ case QTYPE_QINT:
+ d->result = (qint_get_int(qobject_to_qint(obj1)) ==
+ qint_get_int(qobject_to_qint(obj2)));
+ return;
+ case QTYPE_QSTRING:
+ d->result = g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)),
+ qstring_get_str(qobject_to_qstring(obj2))) == 0;
+ return;
+ case QTYPE_QDICT:
+ d_new.expect = qobject_to_qdict(obj2);
+ d_new.result = true;
+ qdict_iter(qobject_to_qdict(obj1), qdict_cmp_do_simple, &d_new);
+ d->result = d_new.result;
+ return;
+ default:
+ abort();
+ }
+}
+
+static bool qdict_cmp_simple(QDict *a, QDict *b)
+{
+ QDictCmpData d;
+
+ d.expect = b;
+ d.result = true;
+ qdict_iter(a, qdict_cmp_do_simple, &d);
+ return d.result;
+}
+
+/* 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)
+{
+ QObject *obj;
+ QDict *t;
+ int64_t s, ms;
+
+ /* Verify that we have timestamp, then remove it to compare other fields */
+ obj = qdict_get(d, "timestamp");
+ g_assert(obj);
+ t = qobject_to_qdict(obj);
+ g_assert(t);
+ obj = qdict_get(t, "seconds");
+ g_assert(obj && qobject_type(obj) == QTYPE_QINT);
+ s = qint_get_int(qobject_to_qint(obj));
+ obj = qdict_get(t, "microseconds");
+ g_assert(obj && qobject_type(obj) == QTYPE_QINT);
+ ms = qint_get_int(qobject_to_qint(obj));
+ if (s == -1) {
+ g_assert(ms == -1);
+ } else {
+ g_assert(ms >= 0 && ms <= 999999);
+ }
+ g_assert(qdict_size(t) == 2);
+
+ qdict_del(d, "timestamp");
+
+ g_assert(qdict_cmp_simple(d, test_event_data->expect));
+
+}
+
+static void event_prepare(TestEventData *data,
+ const void *unused)
+{
+ /* Global variable test_event_data was used to pass the expectation, so
+ test cases can't be executed at same time. */
+ g_mutex_lock(&test_event_lock);
+
+ data->expect = qdict_new();
+ test_event_data = data;
+}
+
+static void event_teardown(TestEventData *data,
+ const void *unused)
+{
+ QDECREF(data->expect);
+ test_event_data = NULL;
+
+ g_mutex_unlock(&test_event_lock);
+}
+
+static void event_test_add(const char *testpath,
+ void (*test_func)(TestEventData *data,
+ const void *user_data))
+{
+ g_test_add(testpath, TestEventData, NULL, event_prepare, test_func,
+ event_teardown);
+}
+
+
+/* Test cases */
+
+static void test_event_a(TestEventData *data,
+ const void *unused)
+{
+ QDict *d;
+ d = data->expect;
+ qdict_put(d, "event", qstring_from_str("EVENT_A"));
+ qapi_event_send_event_a(&error_abort);
+}
+
+static void test_event_b(TestEventData *data,
+ const void *unused)
+{
+ QDict *d;
+ d = data->expect;
+ qdict_put(d, "event", qstring_from_str("EVENT_B"));
+ qapi_event_send_event_b(&error_abort);
+}
+
+static void test_event_c(TestEventData *data,
+ const void *unused)
+{
+ QDict *d, *d_data, *d_b;
+
+ UserDefOne b;
+ UserDefZero z;
+ z.integer = 2;
+ b.base = &z;
+ b.string = g_strdup("test1");
+ b.has_enum1 = false;
+
+ d_b = qdict_new();
+ qdict_put(d_b, "integer", qint_from_int(2));
+ qdict_put(d_b, "string", qstring_from_str("test1"));
+
+ d_data = qdict_new();
+ qdict_put(d_data, "a", qint_from_int(1));
+ qdict_put(d_data, "b", d_b);
+ qdict_put(d_data, "c", qstring_from_str("test2"));
+
+ d = data->expect;
+ qdict_put(d, "event", qstring_from_str("EVENT_C"));
+ qdict_put(d, "data", d_data);
+
+ qapi_event_send_event_c(true, 1, true, &b, "test2", &error_abort);
+
+ g_free(b.string);
+}
+
+/* Complex type */
+static void test_event_d(TestEventData *data,
+ const void *unused)
+{
+ UserDefOne struct1;
+ EventStructOne a;
+ UserDefZero z;
+ QDict *d, *d_data, *d_a, *d_struct1;
+
+ z.integer = 2;
+ struct1.base = &z;
+ struct1.string = g_strdup("test1");
+ struct1.has_enum1 = true;
+ struct1.enum1 = ENUM_ONE_VALUE1;
+
+ a.struct1 = &struct1;
+ a.string = g_strdup("test2");
+ a.has_enum2 = true;
+ a.enum2 = ENUM_ONE_VALUE2;
+
+ d_struct1 = qdict_new();
+ qdict_put(d_struct1, "integer", qint_from_int(2));
+ qdict_put(d_struct1, "string", qstring_from_str("test1"));
+ qdict_put(d_struct1, "enum1", qstring_from_str("value1"));
+
+ d_a = qdict_new();
+ qdict_put(d_a, "struct1", d_struct1);
+ qdict_put(d_a, "string", qstring_from_str("test2"));
+ qdict_put(d_a, "enum2", qstring_from_str("value2"));
+
+ d_data = qdict_new();
+ qdict_put(d_data, "a", d_a);
+ qdict_put(d_data, "b", qstring_from_str("test3"));
+ qdict_put(d_data, "enum3", qstring_from_str("value3"));
+
+ d = data->expect;
+ qdict_put(d, "event", qstring_from_str("EVENT_D"));
+ qdict_put(d, "data", d_data);
+
+ qapi_event_send_event_d(&a, "test3", false, NULL, true, ENUM_ONE_VALUE3,
+ &error_abort);
+
+ g_free(struct1.string);
+ g_free(a.string);
+}
+
+int main(int argc, char **argv)
+{
+#if !GLIB_CHECK_VERSION(2, 31, 0)
+ if (!g_thread_supported()) {
+ g_thread_init(NULL);
+ }
+#endif
+
+ qmp_event_set_func_emit(event_test_emit);
+
+ g_test_init(&argc, &argv, NULL);
+
+ event_test_add("/event/event_a", test_event_a);
+ event_test_add("/event/event_b", test_event_b);
+ event_test_add("/event/event_c", test_event_c);
+ event_test_add("/event/event_d", test_event_d);
+ g_test_run();
+
+ return 0;
+}
diff --git a/tests/test-qmp-input-strict.c b/tests/test-qmp-input-strict.c
index 38b5e95f6..0f770034b 100644
--- a/tests/test-qmp-input-strict.c
+++ b/tests/test-qmp-input-strict.c
@@ -72,27 +72,43 @@ typedef struct TestStruct
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
const char *name, Error **errp)
{
- visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
- errp);
+ Error *err = NULL;
- visit_type_int(v, &(*obj)->integer, "integer", errp);
- visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
- visit_type_str(v, &(*obj)->string, "string", errp);
+ visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
+ &err);
+ if (err) {
+ goto out;
+ }
- visit_end_struct(v, errp);
+ 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_validate_struct(TestInputVisitorData *data,
const void *unused)
{
TestStruct *p = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
- visit_type_TestStruct(v, &p, NULL, &errp);
- g_assert(!errp);
+ visit_type_TestStruct(v, &p, NULL, &err);
+ g_assert(!err);
g_free(p->string);
g_free(p);
}
@@ -101,13 +117,13 @@ static void test_validate_struct_nested(TestInputVisitorData *data,
const void *unused)
{
UserDefNested *udp = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = validate_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
- visit_type_UserDefNested(v, &udp, NULL, &errp);
- g_assert(!errp);
+ visit_type_UserDefNested(v, &udp, NULL, &err);
+ g_assert(!err);
qapi_free_UserDefNested(udp);
}
@@ -115,13 +131,13 @@ static void test_validate_list(TestInputVisitorData *data,
const void *unused)
{
UserDefOneList *head = NULL;
- Error *errp = 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, &errp);
- g_assert(!errp);
+ visit_type_UserDefOneList(v, &head, NULL, &err);
+ g_assert(!err);
qapi_free_UserDefOneList(head);
}
@@ -130,12 +146,12 @@ static void test_validate_union(TestInputVisitorData *data,
{
UserDefUnion *tmp = NULL;
Visitor *v;
- Error *errp = NULL;
+ Error *err = NULL;
v = validate_test_init(data, "{ 'type': 'b', 'integer': 41, 'data' : { 'integer': 42 } }");
- visit_type_UserDefUnion(v, &tmp, NULL, &errp);
- g_assert(!errp);
+ visit_type_UserDefUnion(v, &tmp, NULL, &err);
+ g_assert(!err);
qapi_free_UserDefUnion(tmp);
}
@@ -144,7 +160,7 @@ static void test_validate_union_flat(TestInputVisitorData *data,
{
UserDefFlatUnion *tmp = NULL;
Visitor *v;
- Error *errp = NULL;
+ Error *err = NULL;
v = validate_test_init(data,
"{ 'enum1': 'value1', "
@@ -152,8 +168,8 @@ static void test_validate_union_flat(TestInputVisitorData *data,
"'boolean': true }");
/* TODO when generator bug is fixed, add 'integer': 41 */
- visit_type_UserDefFlatUnion(v, &tmp, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
+ g_assert(!err);
qapi_free_UserDefFlatUnion(tmp);
}
@@ -162,12 +178,12 @@ static void test_validate_union_anon(TestInputVisitorData *data,
{
UserDefAnonUnion *tmp = NULL;
Visitor *v;
- Error *errp = NULL;
+ Error *err = NULL;
v = validate_test_init(data, "42");
- visit_type_UserDefAnonUnion(v, &tmp, NULL, &errp);
- g_assert(!error_is_set(&errp));
+ visit_type_UserDefAnonUnion(v, &tmp, NULL, &err);
+ g_assert(!err);
qapi_free_UserDefAnonUnion(tmp);
}
@@ -175,13 +191,13 @@ static void test_validate_fail_struct(TestInputVisitorData *data,
const void *unused)
{
TestStruct *p = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = validate_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo', 'extra': 42 }");
- visit_type_TestStruct(v, &p, NULL, &errp);
- g_assert(errp);
+ visit_type_TestStruct(v, &p, NULL, &err);
+ g_assert(err);
if (p) {
g_free(p->string);
}
@@ -192,13 +208,13 @@ static void test_validate_fail_struct_nested(TestInputVisitorData *data,
const void *unused)
{
UserDefNested *udp = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
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_UserDefNested(v, &udp, NULL, &errp);
- g_assert(errp);
+ visit_type_UserDefNested(v, &udp, NULL, &err);
+ g_assert(err);
qapi_free_UserDefNested(udp);
}
@@ -206,13 +222,13 @@ static void test_validate_fail_list(TestInputVisitorData *data,
const void *unused)
{
UserDefOneList *head = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
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, &errp);
- g_assert(errp);
+ visit_type_UserDefOneList(v, &head, NULL, &err);
+ g_assert(err);
qapi_free_UserDefOneList(head);
}
@@ -220,13 +236,13 @@ static void test_validate_fail_union(TestInputVisitorData *data,
const void *unused)
{
UserDefUnion *tmp = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = validate_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }");
- visit_type_UserDefUnion(v, &tmp, NULL, &errp);
- g_assert(errp);
+ visit_type_UserDefUnion(v, &tmp, NULL, &err);
+ g_assert(err);
qapi_free_UserDefUnion(tmp);
}
@@ -234,13 +250,13 @@ static void test_validate_fail_union_flat(TestInputVisitorData *data,
const void *unused)
{
UserDefFlatUnion *tmp = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = validate_test_init(data, "{ 'string': 'c', 'integer': 41, 'boolean': true }");
- visit_type_UserDefFlatUnion(v, &tmp, NULL, &errp);
- g_assert(error_is_set(&errp));
+ visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
+ g_assert(err);
qapi_free_UserDefFlatUnion(tmp);
}
@@ -249,12 +265,12 @@ static void test_validate_fail_union_anon(TestInputVisitorData *data,
{
UserDefAnonUnion *tmp = NULL;
Visitor *v;
- Error *errp = NULL;
+ Error *err = NULL;
v = validate_test_init(data, "3.14");
- visit_type_UserDefAnonUnion(v, &tmp, NULL, &errp);
- g_assert(error_is_set(&errp));
+ visit_type_UserDefAnonUnion(v, &tmp, NULL, &err);
+ g_assert(err);
qapi_free_UserDefAnonUnion(tmp);
}
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qmp-input-visitor.c
index 1729667a6..1c8e87295 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qmp-input-visitor.c
@@ -90,13 +90,13 @@ static void test_visitor_in_int(TestInputVisitorData *data,
const void *unused)
{
int64_t res = 0, value = -42;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "%" PRId64, value);
- visit_type_int(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_int(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpint(res, ==, value);
}
@@ -104,7 +104,7 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
const void *unused)
{
int64_t res = 0;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
/* this will overflow a Qint/int64, so should be deserialized into
@@ -113,22 +113,22 @@ static void test_visitor_in_int_overflow(TestInputVisitorData *data,
*/
v = visitor_input_test_init(data, "%f", DBL_MAX);
- visit_type_int(v, &res, NULL, &errp);
- g_assert(errp);
- error_free(errp);
+ visit_type_int(v, &res, NULL, &err);
+ g_assert(err);
+ error_free(err);
}
static void test_visitor_in_bool(TestInputVisitorData *data,
const void *unused)
{
- Error *errp = NULL;
+ Error *err = NULL;
bool res = false;
Visitor *v;
v = visitor_input_test_init(data, "true");
- visit_type_bool(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_bool(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpint(res, ==, true);
}
@@ -136,13 +136,13 @@ static void test_visitor_in_number(TestInputVisitorData *data,
const void *unused)
{
double res = 0, value = 3.14;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "%f", value);
- visit_type_number(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_number(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpfloat(res, ==, value);
}
@@ -150,13 +150,13 @@ static void test_visitor_in_string(TestInputVisitorData *data,
const void *unused)
{
char *res = NULL, *value = (char *) "Q E M U";
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "%s", value);
- visit_type_str(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_str(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpstr(res, ==, value);
g_free(res);
@@ -165,7 +165,7 @@ static void test_visitor_in_string(TestInputVisitorData *data,
static void test_visitor_in_enum(TestInputVisitorData *data,
const void *unused)
{
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
EnumOne i;
@@ -174,8 +174,8 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]);
- visit_type_EnumOne(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_EnumOne(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpint(i, ==, res);
visitor_input_teardown(data, NULL);
@@ -196,34 +196,41 @@ static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
const char *name, Error **errp)
{
Error *err = NULL;
- if (!error_is_set(errp)) {
- visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct),
- &err);
- if (!err) {
- visit_type_int(v, &(*obj)->integer, "integer", &err);
- visit_type_bool(v, &(*obj)->boolean, "boolean", &err);
- visit_type_str(v, &(*obj)->string, "string", &err);
-
- /* Always call end_struct if start_struct succeeded. */
- error_propagate(errp, err);
- err = NULL;
- visit_end_struct(v, &err);
- }
- error_propagate(errp, err);
+
+ 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 *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }");
- visit_type_TestStruct(v, &p, NULL, &errp);
- g_assert(!errp);
+ visit_type_TestStruct(v, &p, NULL, &err);
+ g_assert(!err);
g_assert_cmpint(p->integer, ==, -42);
g_assert(p->boolean == true);
g_assert_cmpstr(p->string, ==, "foo");
@@ -242,13 +249,13 @@ static void test_visitor_in_struct_nested(TestInputVisitorData *data,
const void *unused)
{
UserDefNested *udp = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}");
- visit_type_UserDefNested(v, &udp, NULL, &errp);
- g_assert(!errp);
+ visit_type_UserDefNested(v, &udp, NULL, &err);
+ g_assert(!err);
check_and_free_str(udp->string0, "string0");
check_and_free_str(udp->dict1.string1, "string1");
@@ -265,14 +272,14 @@ static void test_visitor_in_list(TestInputVisitorData *data,
const void *unused)
{
UserDefOneList *item, *head = NULL;
- Error *errp = 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, &errp);
- g_assert(!errp);
+ visit_type_UserDefOneList(v, &head, NULL, &err);
+ g_assert(!err);
g_assert(head != NULL);
for (i = 0, item = head; item; item = item->next, i++) {
@@ -634,16 +641,16 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
const void *unused)
{
TestStruct *p = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "{ 'integer': false, 'boolean': 'foo', 'string': -42 }");
- visit_type_TestStruct(v, &p, NULL, &errp);
- g_assert(errp);
+ visit_type_TestStruct(v, &p, NULL, &err);
+ g_assert(err);
g_assert(p->string == NULL);
- error_free(errp);
+ error_free(err);
g_free(p->string);
g_free(p);
}
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qmp-output-visitor.c
index da279713f..74020de5e 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qmp-output-visitor.c
@@ -45,11 +45,11 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
const void *unused)
{
int64_t value = -42;
- Error *errp = NULL;
+ Error *err = NULL;
QObject *obj;
- visit_type_int(data->ov, &value, NULL, &errp);
- g_assert(!errp);
+ visit_type_int(data->ov, &value, NULL, &err);
+ g_assert(!err);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -62,12 +62,12 @@ static void test_visitor_out_int(TestOutputVisitorData *data,
static void test_visitor_out_bool(TestOutputVisitorData *data,
const void *unused)
{
- Error *errp = NULL;
+ Error *err = NULL;
bool value = true;
QObject *obj;
- visit_type_bool(data->ov, &value, NULL, &errp);
- g_assert(!errp);
+ visit_type_bool(data->ov, &value, NULL, &err);
+ g_assert(!err);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -81,11 +81,11 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
const void *unused)
{
double value = 3.14;
- Error *errp = NULL;
+ Error *err = NULL;
QObject *obj;
- visit_type_number(data->ov, &value, NULL, &errp);
- g_assert(!errp);
+ visit_type_number(data->ov, &value, NULL, &err);
+ g_assert(!err);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -99,11 +99,11 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
const void *unused)
{
char *string = (char *) "Q E M U";
- Error *errp = NULL;
+ Error *err = NULL;
QObject *obj;
- visit_type_str(data->ov, &string, NULL, &errp);
- g_assert(!errp);
+ visit_type_str(data->ov, &string, NULL, &err);
+ g_assert(!err);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -117,12 +117,12 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
const void *unused)
{
char *string = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
QObject *obj;
/* A null string should return "" */
- visit_type_str(data->ov, &string, NULL, &errp);
- g_assert(!errp);
+ visit_type_str(data->ov, &string, NULL, &err);
+ g_assert(!err);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -135,13 +135,13 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
static void test_visitor_out_enum(TestOutputVisitorData *data,
const void *unused)
{
- Error *errp = NULL;
+ Error *err = NULL;
QObject *obj;
EnumOne i;
for (i = 0; i < ENUM_ONE_MAX; i++) {
- visit_type_EnumOne(data->ov, &i, "unused", &errp);
- g_assert(!errp);
+ visit_type_EnumOne(data->ov, &i, "unused", &err);
+ g_assert(!err);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -156,13 +156,13 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
const void *unused)
{
EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
- Error *errp;
+ Error *err;
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
- errp = NULL;
- visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
- g_assert(errp);
- error_free(errp);
+ err = NULL;
+ visit_type_EnumOne(data->ov, &bad_values[i], "unused", &err);
+ g_assert(err);
+ error_free(err);
}
}
@@ -176,14 +176,30 @@ typedef struct 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),
- errp);
+ &err);
+ if (err) {
+ goto out;
+ }
- visit_type_int(v, &(*obj)->integer, "integer", errp);
- visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
- visit_type_str(v, &(*obj)->string, "string", errp);
+ 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);
- visit_end_struct(v, errp);
+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,
@@ -193,12 +209,12 @@ static void test_visitor_out_struct(TestOutputVisitorData *data,
.boolean = false,
.string = (char *) "foo"};
TestStruct *p = &test_struct;
- Error *errp = NULL;
+ Error *err = NULL;
QObject *obj;
QDict *qdict;
- visit_type_TestStruct(data->ov, &p, NULL, &errp);
- g_assert(!errp);
+ visit_type_TestStruct(data->ov, &p, NULL, &err);
+ g_assert(!err);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -217,7 +233,7 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
const void *unused)
{
int64_t value = 42;
- Error *errp = NULL;
+ Error *err = NULL;
UserDefNested *ud2;
QObject *obj;
QDict *qdict, *dict1, *dict2, *dict3, *userdef;
@@ -242,8 +258,8 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
ud2->dict1.dict3.userdef2->base->integer = value;
ud2->dict1.dict3.string3 = g_strdup(strings[3]);
- visit_type_UserDefNested(data->ov, &ud2, "unused", &errp);
- g_assert(!errp);
+ visit_type_UserDefNested(data->ov, &ud2, "unused", &err);
+ g_assert(!err);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -283,16 +299,16 @@ static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
EnumOne bad_values[] = { ENUM_ONE_MAX, -1 };
UserDefZero b;
UserDefOne u = { .base = &b }, *pu = &u;
- Error *errp;
+ Error *err;
int i;
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
- errp = NULL;
+ err = NULL;
u.has_enum1 = true;
u.enum1 = bad_values[i];
- visit_type_UserDefOne(data->ov, &pu, "unused", &errp);
- g_assert(errp);
- error_free(errp);
+ visit_type_UserDefOne(data->ov, &pu, "unused", &err);
+ g_assert(err);
+ error_free(err);
}
}
@@ -328,7 +344,7 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
const int max_items = 10;
bool value_bool = true;
int value_int = 10;
- Error *errp = NULL;
+ Error *err = NULL;
QListEntry *entry;
QObject *obj;
QList *qlist;
@@ -345,8 +361,8 @@ static void test_visitor_out_list(TestOutputVisitorData *data,
head = p;
}
- visit_type_TestStructList(data->ov, &head, NULL, &errp);
- g_assert(!errp);
+ visit_type_TestStructList(data->ov, &head, NULL, &err);
+ g_assert(!err);
obj = qmp_output_get_qobject(data->qov);
g_assert(obj != NULL);
@@ -491,6 +507,15 @@ static void test_visitor_out_union_anon(TestOutputVisitorData *data,
qapi_free_UserDefAnonUnion(tmp);
}
+static void test_visitor_out_empty(TestOutputVisitorData *data,
+ const void *unused)
+{
+ QObject *arg;
+
+ arg = qmp_output_get_qobject(data->qov);
+ g_assert(!arg);
+}
+
static void init_native_list(UserDefNativeListUnion *cvalue)
{
int i;
@@ -843,6 +868,8 @@ int main(int argc, char **argv)
&out_visitor_data, test_visitor_out_union_flat);
output_visitor_test_add("/visitor/output/union-anon",
&out_visitor_data, test_visitor_out_union_anon);
+ output_visitor_test_add("/visitor/output/empty",
+ &out_visitor_data, test_visitor_out_empty);
output_visitor_test_add("/visitor/output/native_list/int",
&out_visitor_data, test_visitor_out_native_list_int);
output_visitor_test_add("/visitor/output/native_list/int8",
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
index d406263ae..8e3433e0c 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -54,62 +54,89 @@ static void test_visitor_in_int(TestInputVisitorData *data,
const void *unused)
{
int64_t res = 0, value = -42;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "-42");
- visit_type_int(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_int(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpint(res, ==, value);
}
+static void test_visitor_in_intList(TestInputVisitorData *data,
+ const void *unused)
+{
+ int64_t value[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20};
+ int16List *res = NULL, *tmp;
+ Visitor *v;
+ int i = 0;
+
+ v = visitor_input_test_init(data, "1,2,0,2-4,20,5-9,1-8");
+
+ visit_type_int16List(v, &res, NULL, &error_abort);
+ tmp = res;
+ while (i < sizeof(value) / sizeof(value[0])) {
+ g_assert(tmp);
+ g_assert_cmpint(tmp->value, ==, value[i++]);
+ tmp = tmp->next;
+ }
+ g_assert(!tmp);
+
+ tmp = res;
+ while (tmp) {
+ res = res->next;
+ g_free(tmp);
+ tmp = res;
+ }
+}
+
static void test_visitor_in_bool(TestInputVisitorData *data,
const void *unused)
{
- Error *errp = NULL;
+ Error *err = NULL;
bool res = false;
Visitor *v;
v = visitor_input_test_init(data, "true");
- visit_type_bool(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_bool(v, &res, NULL, &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, &errp);
- g_assert(!errp);
+ visit_type_bool(v, &res, NULL, &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, &errp);
- g_assert(!errp);
+ visit_type_bool(v, &res, NULL, &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, &errp);
- g_assert(!errp);
+ visit_type_bool(v, &res, NULL, &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, &errp);
- g_assert(!errp);
+ visit_type_bool(v, &res, NULL, &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, &errp);
- g_assert(!errp);
+ visit_type_bool(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpint(res, ==, false);
}
@@ -117,13 +144,13 @@ static void test_visitor_in_number(TestInputVisitorData *data,
const void *unused)
{
double res = 0, value = 3.14;
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, "3.14");
- visit_type_number(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_number(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpfloat(res, ==, value);
}
@@ -131,13 +158,13 @@ static void test_visitor_in_string(TestInputVisitorData *data,
const void *unused)
{
char *res = NULL, *value = (char *) "Q E M U";
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
v = visitor_input_test_init(data, value);
- visit_type_str(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_str(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpstr(res, ==, value);
g_free(res);
@@ -146,7 +173,7 @@ static void test_visitor_in_string(TestInputVisitorData *data,
static void test_visitor_in_enum(TestInputVisitorData *data,
const void *unused)
{
- Error *errp = NULL;
+ Error *err = NULL;
Visitor *v;
EnumOne i;
@@ -155,8 +182,8 @@ static void test_visitor_in_enum(TestInputVisitorData *data,
v = visitor_input_test_init(data, EnumOne_lookup[i]);
- visit_type_EnumOne(v, &res, NULL, &errp);
- g_assert(!errp);
+ visit_type_EnumOne(v, &res, NULL, &err);
+ g_assert(!err);
g_assert_cmpint(i, ==, res);
visitor_input_teardown(data, NULL);
@@ -170,6 +197,7 @@ static void test_visitor_in_fuzz(TestInputVisitorData *data,
const void *unused)
{
int64_t ires;
+ intList *ilres;
bool bres;
double nres;
char *sres;
@@ -193,6 +221,11 @@ static void test_visitor_in_fuzz(TestInputVisitorData *data,
v = visitor_input_test_init(data, buf);
visit_type_int(v, &ires, NULL, NULL);
+ visitor_input_teardown(data, NULL);
+
+ v = visitor_input_test_init(data, buf);
+ visit_type_intList(v, &ilres, NULL, NULL);
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, buf);
visit_type_bool(v, &bres, NULL, NULL);
@@ -200,11 +233,13 @@ static void test_visitor_in_fuzz(TestInputVisitorData *data,
v = visitor_input_test_init(data, buf);
visit_type_number(v, &nres, NULL, NULL);
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, buf);
sres = NULL;
visit_type_str(v, &sres, NULL, NULL);
g_free(sres);
+ visitor_input_teardown(data, NULL);
v = visitor_input_test_init(data, buf);
visit_type_EnumOne(v, &eres, NULL, NULL);
@@ -228,6 +263,8 @@ int main(int argc, char **argv)
input_visitor_test_add("/string-visitor/input/int",
&in_visitor_data, test_visitor_in_int);
+ input_visitor_test_add("/string-visitor/input/intList",
+ &in_visitor_data, test_visitor_in_intList);
input_visitor_test_add("/string-visitor/input/bool",
&in_visitor_data, test_visitor_in_bool);
input_visitor_test_add("/string-visitor/input/number",
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 22363d100..101fb27dd 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -21,12 +21,25 @@
typedef struct TestOutputVisitorData {
StringOutputVisitor *sov;
Visitor *ov;
+ bool human;
} TestOutputVisitorData;
static void visitor_output_setup(TestOutputVisitorData *data,
const void *unused)
{
- data->sov = string_output_visitor_new(false);
+ data->human = false;
+ data->sov = string_output_visitor_new(data->human);
+ g_assert(data->sov != NULL);
+
+ data->ov = string_output_get_visitor(data->sov);
+ g_assert(data->ov != NULL);
+}
+
+static void visitor_output_setup_human(TestOutputVisitorData *data,
+ const void *unused)
+{
+ data->human = true;
+ data->sov = string_output_visitor_new(data->human);
g_assert(data->sov != NULL);
data->ov = string_output_get_visitor(data->sov);
@@ -44,28 +57,71 @@ static void visitor_output_teardown(TestOutputVisitorData *data,
static void test_visitor_out_int(TestOutputVisitorData *data,
const void *unused)
{
- int64_t value = -42;
+ int64_t value = 42;
+ Error *err = NULL;
+ char *str;
+
+ visit_type_int(data->ov, &value, NULL, &err);
+ g_assert(!err);
+
+ str = string_output_get_string(data->sov);
+ g_assert(str != NULL);
+ if (data->human) {
+ g_assert_cmpstr(str, ==, "42 (0x2a)");
+ } else {
+ g_assert_cmpstr(str, ==, "42");
+ }
+ g_free(str);
+}
+
+static void test_visitor_out_intList(TestOutputVisitorData *data,
+ const void *unused)
+{
+ int64_t value[] = {0, 1, 9, 10, 16, 15, 14,
+ 3, 4, 5, 6, 11, 12, 13, 21, 22, INT64_MAX - 1, INT64_MAX};
+ intList *list = NULL, **tmp = &list;
+ int i;
Error *errp = NULL;
char *str;
- visit_type_int(data->ov, &value, NULL, &errp);
- g_assert(!errp);
+ for (i = 0; i < sizeof(value) / sizeof(value[0]); i++) {
+ *tmp = g_malloc0(sizeof(**tmp));
+ (*tmp)->value = value[i];
+ tmp = &(*tmp)->next;
+ }
+
+ visit_type_intList(data->ov, &list, NULL, &errp);
+ g_assert(errp == NULL);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
- g_assert_cmpstr(str, ==, "-42");
+ if (data->human) {
+ g_assert_cmpstr(str, ==,
+ "0-1,3-6,9-16,21-22,9223372036854775806-9223372036854775807 "
+ "(0x0-0x1,0x3-0x6,0x9-0x10,0x15-0x16,"
+ "0x7ffffffffffffffe-0x7fffffffffffffff)");
+ } else {
+ g_assert_cmpstr(str, ==,
+ "0-1,3-6,9-16,21-22,9223372036854775806-9223372036854775807");
+ }
g_free(str);
+ while (list) {
+ intList *tmp2;
+ tmp2 = list->next;
+ g_free(list);
+ list = tmp2;
+ }
}
static void test_visitor_out_bool(TestOutputVisitorData *data,
const void *unused)
{
- Error *errp = NULL;
+ Error *err = NULL;
bool value = true;
char *str;
- visit_type_bool(data->ov, &value, NULL, &errp);
- g_assert(!errp);
+ visit_type_bool(data->ov, &value, NULL, &err);
+ g_assert(!err);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
@@ -77,11 +133,11 @@ static void test_visitor_out_number(TestOutputVisitorData *data,
const void *unused)
{
double value = 3.14;
- Error *errp = NULL;
+ Error *err = NULL;
char *str;
- visit_type_number(data->ov, &value, NULL, &errp);
- g_assert(!errp);
+ visit_type_number(data->ov, &value, NULL, &err);
+ g_assert(!err);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
@@ -93,15 +149,20 @@ static void test_visitor_out_string(TestOutputVisitorData *data,
const void *unused)
{
char *string = (char *) "Q E M U";
- Error *errp = NULL;
+ const char *string_human = "\"Q E M U\"";
+ Error *err = NULL;
char *str;
- visit_type_str(data->ov, &string, NULL, &errp);
- g_assert(!errp);
+ visit_type_str(data->ov, &string, NULL, &err);
+ g_assert(!err);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
- g_assert_cmpstr(str, ==, string);
+ if (data->human) {
+ g_assert_cmpstr(str, ==, string_human);
+ } else {
+ g_assert_cmpstr(str, ==, string);
+ }
g_free(str);
}
@@ -109,33 +170,46 @@ static void test_visitor_out_no_string(TestOutputVisitorData *data,
const void *unused)
{
char *string = NULL;
- Error *errp = NULL;
+ Error *err = NULL;
char *str;
/* A null string should return "" */
- visit_type_str(data->ov, &string, NULL, &errp);
- g_assert(!errp);
+ visit_type_str(data->ov, &string, NULL, &err);
+ g_assert(!err);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
- g_assert_cmpstr(str, ==, "");
+ if (data->human) {
+ g_assert_cmpstr(str, ==, "<null>");
+ } else {
+ g_assert_cmpstr(str, ==, "");
+ }
g_free(str);
}
static void test_visitor_out_enum(TestOutputVisitorData *data,
const void *unused)
{
- Error *errp = NULL;
+ Error *err = NULL;
char *str;
EnumOne i;
for (i = 0; i < ENUM_ONE_MAX; i++) {
- visit_type_EnumOne(data->ov, &i, "unused", &errp);
- g_assert(!errp);
+ char *str_human;
+
+ visit_type_EnumOne(data->ov, &i, "unused", &err);
+ g_assert(!err);
+
+ str_human = g_strdup_printf("\"%s\"", EnumOne_lookup[i]);
str = string_output_get_string(data->sov);
g_assert(str != NULL);
- g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
+ if (data->human) {
+ g_assert_cmpstr(str, ==, str_human);
+ } else {
+ g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
+ }
+ g_free(str_human);
g_free(str);
}
}
@@ -144,21 +218,25 @@ static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
const void *unused)
{
EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
- Error *errp;
+ Error *err;
for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
- errp = NULL;
- visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
- g_assert(errp);
- error_free(errp);
+ err = NULL;
+ visit_type_EnumOne(data->ov, &bad_values[i], "unused", &err);
+ g_assert(err);
+ error_free(err);
}
}
-static void output_visitor_test_add(const char *testpath,
- TestOutputVisitorData *data,
- void (*test_func)(TestOutputVisitorData *data, const void *user_data))
+static void
+output_visitor_test_add(const char *testpath,
+ TestOutputVisitorData *data,
+ void (*test_func)(TestOutputVisitorData *data,
+ const void *user_data),
+ bool human)
{
- g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
+ g_test_add(testpath, TestOutputVisitorData, data,
+ human ? visitor_output_setup_human : visitor_output_setup,
test_func, visitor_output_teardown);
}
@@ -169,19 +247,41 @@ int main(int argc, char **argv)
g_test_init(&argc, &argv, NULL);
output_visitor_test_add("/string-visitor/output/int",
- &out_visitor_data, test_visitor_out_int);
+ &out_visitor_data, test_visitor_out_int, false);
+ output_visitor_test_add("/string-visitor/output/int",
+ &out_visitor_data, test_visitor_out_int, true);
output_visitor_test_add("/string-visitor/output/bool",
- &out_visitor_data, test_visitor_out_bool);
+ &out_visitor_data, test_visitor_out_bool, false);
+ output_visitor_test_add("/string-visitor/output/bool",
+ &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",
- &out_visitor_data, test_visitor_out_number);
+ &out_visitor_data, test_visitor_out_number, true);
output_visitor_test_add("/string-visitor/output/string",
- &out_visitor_data, test_visitor_out_string);
+ &out_visitor_data, test_visitor_out_string, false);
+ output_visitor_test_add("/string-visitor/output/string",
+ &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",
- &out_visitor_data, test_visitor_out_no_string);
+ &out_visitor_data, test_visitor_out_no_string,
+ true);
output_visitor_test_add("/string-visitor/output/enum",
- &out_visitor_data, test_visitor_out_enum);
+ &out_visitor_data, test_visitor_out_enum, false);
+ output_visitor_test_add("/string-visitor/output/enum",
+ &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",
- &out_visitor_data, test_visitor_out_enum_errors);
+ &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",
+ &out_visitor_data, test_visitor_out_intList, true);
g_test_run();
diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c
index c1f8e13a9..f40b7fc17 100644
--- a/tests/test-thread-pool.c
+++ b/tests/test-thread-pool.c
@@ -83,7 +83,7 @@ static void co_test_cb(void *opaque)
data->ret = 0;
active--;
- /* The test continues in test_submit_co, after qemu_aio_wait_all... */
+ /* The test continues in test_submit_co, after aio_poll... */
}
static void test_submit_co(void)
@@ -98,7 +98,7 @@ static void test_submit_co(void)
g_assert_cmpint(active, ==, 1);
g_assert_cmpint(data.ret, ==, -EINPROGRESS);
- /* qemu_aio_wait_all will execute the rest of the coroutine. */
+ /* aio_poll will execute the rest of the coroutine. */
while (data.ret == -EINPROGRESS) {
aio_poll(ctx, true);
@@ -180,7 +180,7 @@ static void test_cancel(void)
/* Canceling the others will be a blocking operation. */
for (i = 0; i < 100; i++) {
- if (data[i].n != 3) {
+ if (data[i].aiocb && data[i].n != 3) {
bdrv_aio_cancel(data[i].aiocb);
}
}
diff --git a/tests/test-throttle.c b/tests/test-throttle.c
index 1d4ffd360..000ae31af 100644
--- a/tests/test-throttle.c
+++ b/tests/test-throttle.c
@@ -12,11 +12,13 @@
#include <glib.h>
#include <math.h>
+#include "block/aio.h"
#include "qemu/throttle.h"
-LeakyBucket bkt;
-ThrottleConfig cfg;
-ThrottleState ts;
+static AioContext *ctx;
+static LeakyBucket bkt;
+static ThrottleConfig cfg;
+static ThrottleState ts;
/* useful function */
static bool double_cmp(double x, double y)
@@ -104,7 +106,8 @@ static void test_init(void)
memset(&ts, 1, sizeof(ts));
/* init the structure */
- throttle_init(&ts, QEMU_CLOCK_VIRTUAL, read_timer_cb, write_timer_cb, &ts);
+ throttle_init(&ts, ctx, QEMU_CLOCK_VIRTUAL,
+ read_timer_cb, write_timer_cb, &ts);
/* check initialized fields */
g_assert(ts.clock_type == QEMU_CLOCK_VIRTUAL);
@@ -126,7 +129,8 @@ static void test_init(void)
static void test_destroy(void)
{
int i;
- throttle_init(&ts, QEMU_CLOCK_VIRTUAL, read_timer_cb, write_timer_cb, &ts);
+ throttle_init(&ts, ctx, QEMU_CLOCK_VIRTUAL,
+ read_timer_cb, write_timer_cb, &ts);
throttle_destroy(&ts);
for (i = 0; i < 2; i++) {
g_assert(!ts.timers[i]);
@@ -165,7 +169,8 @@ static void test_config_functions(void)
orig_cfg.op_size = 1;
- throttle_init(&ts, QEMU_CLOCK_VIRTUAL, read_timer_cb, write_timer_cb, &ts);
+ throttle_init(&ts, ctx, QEMU_CLOCK_VIRTUAL,
+ read_timer_cb, write_timer_cb, &ts);
/* structure reset by throttle_init previous_leak should be null */
g_assert(!ts.previous_leak);
throttle_config(&ts, &orig_cfg);
@@ -324,7 +329,8 @@ static void test_have_timer(void)
g_assert(!throttle_have_timer(&ts));
/* init the structure */
- throttle_init(&ts, QEMU_CLOCK_VIRTUAL, read_timer_cb, write_timer_cb, &ts);
+ throttle_init(&ts, ctx, QEMU_CLOCK_VIRTUAL,
+ read_timer_cb, write_timer_cb, &ts);
/* timer set by init should return true */
g_assert(throttle_have_timer(&ts));
@@ -332,6 +338,29 @@ static void test_have_timer(void)
throttle_destroy(&ts);
}
+static void test_detach_attach(void)
+{
+ /* zero the structure */
+ memset(&ts, 0, sizeof(ts));
+
+ /* init the structure */
+ throttle_init(&ts, ctx, QEMU_CLOCK_VIRTUAL,
+ read_timer_cb, write_timer_cb, &ts);
+
+ /* timer set by init should return true */
+ g_assert(throttle_have_timer(&ts));
+
+ /* timer should no longer exist after detaching */
+ throttle_detach_aio_context(&ts);
+ g_assert(!throttle_have_timer(&ts));
+
+ /* timer should exist again after attaching */
+ throttle_attach_aio_context(&ts, ctx);
+ g_assert(throttle_have_timer(&ts));
+
+ throttle_destroy(&ts);
+}
+
static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
int size, /* size of the operation to do */
double avg, /* io limit */
@@ -357,7 +386,8 @@ static bool do_test_accounting(bool is_ops, /* are we testing bps or ops */
cfg.op_size = op_size;
- throttle_init(&ts, QEMU_CLOCK_VIRTUAL, read_timer_cb, write_timer_cb, &ts);
+ throttle_init(&ts, ctx, QEMU_CLOCK_VIRTUAL,
+ read_timer_cb, write_timer_cb, &ts);
throttle_config(&ts, &cfg);
/* account a read */
@@ -461,7 +491,15 @@ static void test_accounting(void)
int main(int argc, char **argv)
{
+ GSource *src;
+
init_clocks();
+
+ ctx = aio_context_new();
+ src = aio_get_g_source(ctx);
+ g_source_attach(src, NULL);
+ g_source_unref(src);
+
do {} while (g_main_context_iteration(NULL, false));
/* tests in the same order as the header function declarations */
@@ -471,6 +509,7 @@ int main(int argc, char **argv)
g_test_add_func("/throttle/init", test_init);
g_test_add_func("/throttle/destroy", test_destroy);
g_test_add_func("/throttle/have_timer", test_have_timer);
+ g_test_add_func("/throttle/detach_attach", test_detach_attach);
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);
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index 8166cf1b0..7ad188639 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -195,13 +195,29 @@ typedef struct TestStruct
static void visit_type_TestStruct(Visitor *v, TestStruct **obj,
const char *name, Error **errp)
{
- visit_start_struct(v, (void **)obj, NULL, name, sizeof(TestStruct), errp);
+ Error *err = NULL;
- visit_type_int(v, &(*obj)->integer, "integer", errp);
- visit_type_bool(v, &(*obj)->boolean, "boolean", errp);
- visit_type_str(v, &(*obj)->string, "string", errp);
+ visit_start_struct(v, (void **)obj, NULL, name, sizeof(TestStruct), &err);
+ if (err) {
+ goto out;
+ }
- visit_end_struct(v, errp);
+ 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)
@@ -356,8 +372,8 @@ static void test_primitive_lists(gconstpointer opaque)
TestArgs *args = (TestArgs *) opaque;
const SerializeOps *ops = args->ops;
PrimitiveType *pt = args->test_data;
- PrimitiveList pl = { .value = { 0 } };
- PrimitiveList pl_copy = { .value = { 0 } };
+ PrimitiveList pl = { .value = { NULL } };
+ PrimitiveList pl_copy = { .value = { NULL } };
PrimitiveList *pl_copy_ptr = &pl_copy;
Error *err = NULL;
void *serialize_data;
@@ -755,7 +771,7 @@ static void test_nested_struct_list(gconstpointer opaque)
g_free(args);
}
-PrimitiveType pt_values[] = {
+static PrimitiveType pt_values[] = {
/* string tests */
{
.description = "string_empty",
diff --git a/tests/test-vmstate.c b/tests/test-vmstate.c
index 75cd1a1fd..d72c64c90 100644
--- a/tests/test-vmstate.c
+++ b/tests/test-vmstate.c
@@ -29,8 +29,8 @@
#include "migration/vmstate.h"
#include "block/coroutine.h"
-char temp_file[] = "/tmp/vmst.test.XXXXXX";
-int temp_fd;
+static char temp_file[] = "/tmp/vmst.test.XXXXXX";
+static int temp_fd;
/* Fake yield_until_fd_readable() implementation so we don't have to pull the
* coroutine code as dependency.
@@ -44,95 +44,245 @@ void yield_until_fd_readable(int fd)
}
/* Duplicate temp_fd and seek to the beginning of the file */
-static int dup_temp_fd(bool truncate)
+static QEMUFile *open_test_file(bool write)
{
int fd = dup(temp_fd);
lseek(fd, 0, SEEK_SET);
- if (truncate) {
+ if (write) {
g_assert_cmpint(ftruncate(fd, 0), ==, 0);
}
- return fd;
+ return qemu_fdopen(fd, write ? "wb" : "rb");
}
-typedef struct TestSruct {
- uint32_t a, b, c, e;
- uint64_t d, f;
- bool skip_c_e;
-} TestStruct;
+#define SUCCESS(val) \
+ g_assert_cmpint((val), ==, 0)
+#define FAILURE(val) \
+ g_assert_cmpint((val), !=, 0)
-static const VMStateDescription vmstate_simple = {
- .name = "test",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT32(a, TestStruct),
- VMSTATE_UINT32(b, TestStruct),
- VMSTATE_UINT32(c, TestStruct),
- VMSTATE_UINT64(d, TestStruct),
- VMSTATE_END_OF_LIST()
- }
-};
+static void save_vmstate(const VMStateDescription *desc, void *obj)
+{
+ QEMUFile *f = open_test_file(true);
+
+ /* Save file with vmstate */
+ vmstate_save_state(f, desc, obj);
+ qemu_put_byte(f, QEMU_VM_EOF);
+ g_assert(!qemu_file_get_error(f));
+ qemu_fclose(f);
+}
-static void test_simple_save(void)
+static void compare_vmstate(uint8_t *wire, size_t size)
{
- QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
- TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4 };
- vmstate_save_state(fsave, &vmstate_simple, &obj);
- g_assert(!qemu_file_get_error(fsave));
- qemu_fclose(fsave);
+ QEMUFile *f = open_test_file(false);
+ uint8_t result[size];
- QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
- uint8_t expected[] = {
- 0, 0, 0, 1, /* a */
- 0, 0, 0, 2, /* b */
- 0, 0, 0, 3, /* c */
- 0, 0, 0, 0, 0, 0, 0, 4, /* d */
- };
- uint8_t result[sizeof(expected)];
- g_assert_cmpint(qemu_get_buffer(loading, result, sizeof(result)), ==,
+ /* read back as binary */
+
+ g_assert_cmpint(qemu_get_buffer(f, result, sizeof(result)), ==,
sizeof(result));
- g_assert(!qemu_file_get_error(loading));
- g_assert_cmpint(memcmp(result, expected, sizeof(result)), ==, 0);
+ g_assert(!qemu_file_get_error(f));
+
+ /* Compare that what is on the file is the same that what we
+ expected to be there */
+ SUCCESS(memcmp(result, wire, sizeof(result)));
/* Must reach EOF */
- qemu_get_byte(loading);
- g_assert_cmpint(qemu_file_get_error(loading), ==, -EIO);
+ qemu_get_byte(f);
+ g_assert_cmpint(qemu_file_get_error(f), ==, -EIO);
- qemu_fclose(loading);
+ qemu_fclose(f);
}
-static void test_simple_load(void)
+static int load_vmstate_one(const VMStateDescription *desc, void *obj,
+ int version, uint8_t *wire, size_t size)
{
- QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
- uint8_t buf[] = {
- 0, 0, 0, 10, /* a */
- 0, 0, 0, 20, /* b */
- 0, 0, 0, 30, /* c */
- 0, 0, 0, 0, 0, 0, 0, 40, /* d */
- QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
- };
- qemu_put_buffer(fsave, buf, sizeof(buf));
- qemu_fclose(fsave);
+ QEMUFile *f;
+ int ret;
+
+ f = open_test_file(true);
+ qemu_put_buffer(f, wire, size);
+ qemu_fclose(f);
+
+ f = open_test_file(false);
+ ret = vmstate_load_state(f, desc, obj, version);
+ if (ret) {
+ g_assert(qemu_file_get_error(f));
+ } else{
+ g_assert(!qemu_file_get_error(f));
+ }
+ qemu_fclose(f);
+ return ret;
+}
- QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
- TestStruct obj;
- vmstate_load_state(loading, &vmstate_simple, &obj, 1);
- g_assert(!qemu_file_get_error(loading));
- g_assert_cmpint(obj.a, ==, 10);
- g_assert_cmpint(obj.b, ==, 20);
- g_assert_cmpint(obj.c, ==, 30);
- g_assert_cmpint(obj.d, ==, 40);
- qemu_fclose(loading);
+
+static int load_vmstate(const VMStateDescription *desc,
+ void *obj, void *obj_clone,
+ void (*obj_copy)(void *, void*),
+ int version, uint8_t *wire, size_t size)
+{
+ /* We test with zero size */
+ obj_copy(obj_clone, obj);
+ FAILURE(load_vmstate_one(desc, obj, version, wire, 0));
+
+ /* Stream ends with QEMU_EOF, so we need at least 3 bytes to be
+ * able to test in the middle */
+
+ if (size > 3) {
+
+ /* We test with size - 2. We can't test size - 1 due to EOF tricks */
+ obj_copy(obj, obj_clone);
+ FAILURE(load_vmstate_one(desc, obj, version, wire, size - 2));
+
+ /* Test with size/2, first half of real state */
+ obj_copy(obj, obj_clone);
+ FAILURE(load_vmstate_one(desc, obj, version, wire, size/2));
+
+ /* Test with size/2, second half of real state */
+ obj_copy(obj, obj_clone);
+ FAILURE(load_vmstate_one(desc, obj, version, wire + (size/2), size/2));
+
+ }
+ obj_copy(obj, obj_clone);
+ return load_vmstate_one(desc, obj, version, wire, size);
}
+/* Test struct that we are going to use for our tests */
+
+typedef struct TestSimple {
+ bool b_1, b_2;
+ uint8_t u8_1;
+ uint16_t u16_1;
+ uint32_t u32_1;
+ uint64_t u64_1;
+ int8_t i8_1, i8_2;
+ int16_t i16_1, i16_2;
+ int32_t i32_1, i32_2;
+ int64_t i64_1, i64_2;
+} TestSimple;
+
+/* Object instantiation, we are going to use it in more than one test */
+
+TestSimple obj_simple = {
+ .b_1 = true,
+ .b_2 = false,
+ .u8_1 = 130,
+ .u16_1 = 512,
+ .u32_1 = 70000,
+ .u64_1 = 12121212,
+ .i8_1 = 65,
+ .i8_2 = -65,
+ .i16_1 = 512,
+ .i16_2 = -512,
+ .i32_1 = 70000,
+ .i32_2 = -70000,
+ .i64_1 = 12121212,
+ .i64_2 = -12121212,
+};
+
+/* Description of the values. If you add a primitive type
+ you are expected to add a test here */
+
+static const VMStateDescription vmstate_simple_primitive = {
+ .name = "simple/primitive",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_BOOL(b_1, TestSimple),
+ VMSTATE_BOOL(b_2, TestSimple),
+ VMSTATE_UINT8(u8_1, TestSimple),
+ VMSTATE_UINT16(u16_1, TestSimple),
+ VMSTATE_UINT32(u32_1, TestSimple),
+ VMSTATE_UINT64(u64_1, TestSimple),
+ VMSTATE_INT8(i8_1, TestSimple),
+ VMSTATE_INT8(i8_2, TestSimple),
+ VMSTATE_INT16(i16_1, TestSimple),
+ VMSTATE_INT16(i16_2, TestSimple),
+ VMSTATE_INT32(i32_1, TestSimple),
+ VMSTATE_INT32(i32_2, TestSimple),
+ VMSTATE_INT64(i64_1, TestSimple),
+ VMSTATE_INT64(i64_2, TestSimple),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+/* It describes what goes through the wire. Our tests are basically:
+
+ * save test
+ - save a struct a vmstate to a file
+ - read that file back (binary read, no vmstate)
+ - compare it with what we expect to be on the wire
+ * load test
+ - save to the file what we expect to be on the wire
+ - read struct back with vmstate in a different
+ - compare back with the original struct
+*/
+
+uint8_t wire_simple_primitive[] = {
+ /* b_1 */ 0x01,
+ /* b_2 */ 0x00,
+ /* u8_1 */ 0x82,
+ /* u16_1 */ 0x02, 0x00,
+ /* u32_1 */ 0x00, 0x01, 0x11, 0x70,
+ /* u64_1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xf4, 0x7c,
+ /* i8_1 */ 0x41,
+ /* i8_2 */ 0xbf,
+ /* i16_1 */ 0x02, 0x00,
+ /* i16_2 */ 0xfe, 0x0,
+ /* i32_1 */ 0x00, 0x01, 0x11, 0x70,
+ /* i32_2 */ 0xff, 0xfe, 0xee, 0x90,
+ /* i64_1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xf4, 0x7c,
+ /* i64_2 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0x47, 0x0b, 0x84,
+ QEMU_VM_EOF, /* just to ensure we won't get EOF reported prematurely */
+};
+
+static void obj_simple_copy(void *target, void *source)
+{
+ memcpy(target, source, sizeof(TestSimple));
+}
+
+static void test_simple_primitive(void)
+{
+ TestSimple obj, obj_clone;
+
+ memset(&obj, 0, sizeof(obj));
+ save_vmstate(&vmstate_simple_primitive, &obj_simple);
+
+ compare_vmstate(wire_simple_primitive, sizeof(wire_simple_primitive));
+
+ SUCCESS(load_vmstate(&vmstate_simple_primitive, &obj, &obj_clone,
+ obj_simple_copy, 1, wire_simple_primitive,
+ sizeof(wire_simple_primitive)));
+
+#define FIELD_EQUAL(name) g_assert_cmpint(obj.name, ==, obj_simple.name)
+
+ FIELD_EQUAL(b_1);
+ FIELD_EQUAL(b_2);
+ FIELD_EQUAL(u8_1);
+ FIELD_EQUAL(u16_1);
+ FIELD_EQUAL(u32_1);
+ FIELD_EQUAL(u64_1);
+ FIELD_EQUAL(i8_1);
+ FIELD_EQUAL(i8_2);
+ FIELD_EQUAL(i16_1);
+ FIELD_EQUAL(i16_2);
+ FIELD_EQUAL(i32_1);
+ FIELD_EQUAL(i32_2);
+ FIELD_EQUAL(i64_1);
+ FIELD_EQUAL(i64_2);
+}
+#undef FIELD_EQUAL
+
+typedef struct TestStruct {
+ uint32_t a, b, c, e;
+ uint64_t d, f;
+ bool skip_c_e;
+} TestStruct;
+
static const VMStateDescription vmstate_versioned = {
- .name = "test",
+ .name = "test/versioned",
.version_id = 2,
.minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .fields = (VMStateField []) {
+ .fields = (VMStateField[]) {
VMSTATE_UINT32(a, TestStruct),
VMSTATE_UINT32_V(b, TestStruct, 2), /* Versioned field in the middle, so
* we catch bugs more easily.
@@ -147,7 +297,7 @@ static const VMStateDescription vmstate_versioned = {
static void test_load_v1(void)
{
- QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+ QEMUFile *fsave = open_test_file(true);
uint8_t buf[] = {
0, 0, 0, 10, /* a */
0, 0, 0, 30, /* c */
@@ -157,7 +307,7 @@ static void test_load_v1(void)
qemu_put_buffer(fsave, buf, sizeof(buf));
qemu_fclose(fsave);
- QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+ QEMUFile *loading = open_test_file(false);
TestStruct obj = { .b = 200, .e = 500, .f = 600 };
vmstate_load_state(loading, &vmstate_versioned, &obj, 1);
g_assert(!qemu_file_get_error(loading));
@@ -172,7 +322,7 @@ static void test_load_v1(void)
static void test_load_v2(void)
{
- QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+ QEMUFile *fsave = open_test_file(true);
uint8_t buf[] = {
0, 0, 0, 10, /* a */
0, 0, 0, 20, /* b */
@@ -185,7 +335,7 @@ static void test_load_v2(void)
qemu_put_buffer(fsave, buf, sizeof(buf));
qemu_fclose(fsave);
- QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+ QEMUFile *loading = open_test_file(false);
TestStruct obj;
vmstate_load_state(loading, &vmstate_versioned, &obj, 2);
g_assert_cmpint(obj.a, ==, 10);
@@ -204,11 +354,10 @@ static bool test_skip(void *opaque, int version_id)
}
static const VMStateDescription vmstate_skipping = {
- .name = "test",
+ .name = "test/skip",
.version_id = 2,
.minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .fields = (VMStateField []) {
+ .fields = (VMStateField[]) {
VMSTATE_UINT32(a, TestStruct),
VMSTATE_UINT32(b, TestStruct),
VMSTATE_UINT32_TEST(c, TestStruct, test_skip),
@@ -222,14 +371,14 @@ static const VMStateDescription vmstate_skipping = {
static void test_save_noskip(void)
{
- QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+ QEMUFile *fsave = open_test_file(true);
TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4, .e = 5, .f = 6,
.skip_c_e = false };
vmstate_save_state(fsave, &vmstate_skipping, &obj);
g_assert(!qemu_file_get_error(fsave));
qemu_fclose(fsave);
- QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+ QEMUFile *loading = open_test_file(false);
uint8_t expected[] = {
0, 0, 0, 1, /* a */
0, 0, 0, 2, /* b */
@@ -253,14 +402,14 @@ static void test_save_noskip(void)
static void test_save_skip(void)
{
- QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+ QEMUFile *fsave = open_test_file(true);
TestStruct obj = { .a = 1, .b = 2, .c = 3, .d = 4, .e = 5, .f = 6,
.skip_c_e = true };
vmstate_save_state(fsave, &vmstate_skipping, &obj);
g_assert(!qemu_file_get_error(fsave));
qemu_fclose(fsave);
- QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+ QEMUFile *loading = open_test_file(false);
uint8_t expected[] = {
0, 0, 0, 1, /* a */
0, 0, 0, 2, /* b */
@@ -283,7 +432,7 @@ static void test_save_skip(void)
static void test_load_noskip(void)
{
- QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+ QEMUFile *fsave = open_test_file(true);
uint8_t buf[] = {
0, 0, 0, 10, /* a */
0, 0, 0, 20, /* b */
@@ -296,7 +445,7 @@ static void test_load_noskip(void)
qemu_put_buffer(fsave, buf, sizeof(buf));
qemu_fclose(fsave);
- QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+ QEMUFile *loading = open_test_file(false);
TestStruct obj = { .skip_c_e = false };
vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
g_assert(!qemu_file_get_error(loading));
@@ -311,7 +460,7 @@ static void test_load_noskip(void)
static void test_load_skip(void)
{
- QEMUFile *fsave = qemu_fdopen(dup_temp_fd(true), "wb");
+ QEMUFile *fsave = open_test_file(true);
uint8_t buf[] = {
0, 0, 0, 10, /* a */
0, 0, 0, 20, /* b */
@@ -322,7 +471,7 @@ static void test_load_skip(void)
qemu_put_buffer(fsave, buf, sizeof(buf));
qemu_fclose(fsave);
- QEMUFile *loading = qemu_fdopen(dup_temp_fd(false), "rb");
+ QEMUFile *loading = open_test_file(false);
TestStruct obj = { .skip_c_e = true, .c = 300, .e = 500 };
vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
g_assert(!qemu_file_get_error(loading));
@@ -340,8 +489,7 @@ int main(int argc, char **argv)
temp_fd = mkstemp(temp_file);
g_test_init(&argc, &argv, NULL);
- g_test_add_func("/vmstate/simple/save", test_simple_save);
- g_test_add_func("/vmstate/simple/load", test_simple_load);
+ g_test_add_func("/vmstate/simple/primitive", test_simple_primitive);
g_test_add_func("/vmstate/versioned/load/v1", test_load_v1);
g_test_add_func("/vmstate/versioned/load/v2", test_load_v2);
g_test_add_func("/vmstate/field_exists/load/noskip", test_load_noskip);
diff --git a/tests/tmp105-test.c b/tests/tmp105-test.c
index 15ddaf38d..99db53819 100644
--- a/tests/tmp105-test.c
+++ b/tests/tmp105-test.c
@@ -69,7 +69,7 @@ static int qmp_tmp105_get_temperature(const char *id)
QDict *response;
int ret;
- response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': '%s', "
+ response = qmp("{ 'execute': 'qom-get', 'arguments': { 'path': %s, "
"'property': 'temperature' } }", id);
g_assert(qdict_haskey(response, "return"));
ret = qdict_get_int(response, "return");
@@ -81,7 +81,7 @@ static void qmp_tmp105_set_temperature(const char *id, int value)
{
QDict *response;
- response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': '%s', "
+ response = qmp("{ 'execute': 'qom-set', 'arguments': { 'path': %s, "
"'property': 'temperature', 'value': %d } }", id, value);
g_assert(qdict_haskey(response, "return"));
QDECREF(response);
diff --git a/tests/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c
new file mode 100644
index 000000000..bcdf62fc3
--- /dev/null
+++ b/tests/usb-hcd-ehci-test.c
@@ -0,0 +1,185 @@
+/*
+ * QTest testcase for USB EHCI
+ *
+ * Copyright (c) 2014 SUSE LINUX Products GmbH
+ *
+ * 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 <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"
+
+struct qhc {
+ QPCIDevice *dev;
+ void *base;
+};
+
+static QPCIBus *pcibus;
+static struct qhc uhci1;
+static struct qhc uhci2;
+static struct qhc uhci3;
+static struct qhc ehci1;
+
+/* helpers */
+
+static void pci_init_one(struct qhc *hc, uint32_t devfn, int bar)
+{
+ hc->dev = qpci_device_find(pcibus, devfn);
+ g_assert(hc->dev != NULL);
+ qpci_device_enable(hc->dev);
+ hc->base = qpci_iomap(hc->dev, bar);
+ g_assert(hc->base != NULL);
+}
+
+#if 0
+static void uhci_port_update(struct qhc *hc, int port,
+ uint16_t set, uint16_t clear)
+{
+ void *addr = hc->base + 0x10 + 2 * port;
+ uint16_t value;
+
+ value = qpci_io_readw(hc->dev, addr);
+ value |= set;
+ value &= ~clear;
+ qpci_io_writew(hc->dev, addr, value);
+}
+#endif
+
+static void uhci_port_test(struct qhc *hc, int port, uint16_t expect)
+{
+ void *addr = hc->base + 0x10 + 2 * port;
+ uint16_t value = qpci_io_readw(hc->dev, addr);
+ uint16_t mask = ~(UHCI_PORT_WRITE_CLEAR | UHCI_PORT_RSVD1);
+
+#if 0
+ fprintf(stderr, "%s: %d, have 0x%04x, want 0x%04x\n",
+ __func__, port, value & mask, expect & mask);
+#endif
+ g_assert((value & mask) == (expect & mask));
+}
+
+static void ehci_port_test(struct qhc *hc, int port, uint32_t expect)
+{
+ void *addr = hc->base + 0x64 + 4 * port;
+ uint32_t value = qpci_io_readl(hc->dev, addr);
+ uint16_t mask = ~(PORTSC_CSC | PORTSC_PEDC | PORTSC_OCC);
+
+#if 0
+ fprintf(stderr, "%s: %d, have 0x%08x, want 0x%08x\n",
+ __func__, port, value & mask, expect & mask);
+#endif
+ g_assert((value & mask) == (expect & mask));
+}
+
+/* tests */
+
+static void pci_init(void)
+{
+ if (pcibus) {
+ return;
+ }
+ pcibus = qpci_init_pc();
+ g_assert(pcibus != NULL);
+
+ pci_init_one(&uhci1, QPCI_DEVFN(0x1d, 0), 4);
+ pci_init_one(&uhci2, QPCI_DEVFN(0x1d, 1), 4);
+ pci_init_one(&uhci3, QPCI_DEVFN(0x1d, 2), 4);
+ pci_init_one(&ehci1, QPCI_DEVFN(0x1d, 7), 0);
+}
+
+static void pci_uhci_port_1(void)
+{
+ g_assert(pcibus != NULL);
+
+ uhci_port_test(&uhci1, 0, UHCI_PORT_CCS); /* usb-tablet */
+ uhci_port_test(&uhci1, 1, UHCI_PORT_CCS); /* usb-storage */
+ uhci_port_test(&uhci2, 0, 0);
+ uhci_port_test(&uhci2, 1, 0);
+ uhci_port_test(&uhci3, 0, 0);
+ uhci_port_test(&uhci3, 1, 0);
+}
+
+static void pci_ehci_port_1(void)
+{
+ int i;
+
+ g_assert(pcibus != NULL);
+
+ for (i = 0; i < 6; i++) {
+ ehci_port_test(&ehci1, i, PORTSC_POWNER | PORTSC_PPOWER);
+ }
+}
+
+static void pci_ehci_config(void)
+{
+ /* hands over all ports from companion uhci to ehci */
+ qpci_io_writew(ehci1.dev, ehci1.base + 0x60, 1);
+}
+
+static void pci_uhci_port_2(void)
+{
+ g_assert(pcibus != NULL);
+
+ uhci_port_test(&uhci1, 0, 0); /* usb-tablet, @ehci */
+ uhci_port_test(&uhci1, 1, 0); /* usb-storage, @ehci */
+ uhci_port_test(&uhci2, 0, 0);
+ uhci_port_test(&uhci2, 1, 0);
+ uhci_port_test(&uhci3, 0, 0);
+ uhci_port_test(&uhci3, 1, 0);
+}
+
+static void pci_ehci_port_2(void)
+{
+ static uint32_t expect[] = {
+ PORTSC_PPOWER | PORTSC_CONNECT, /* usb-tablet */
+ PORTSC_PPOWER | PORTSC_CONNECT, /* usb-storage */
+ PORTSC_PPOWER,
+ PORTSC_PPOWER,
+ PORTSC_PPOWER,
+ PORTSC_PPOWER,
+ };
+ int i;
+
+ g_assert(pcibus != NULL);
+
+ for (i = 0; i < 6; i++) {
+ ehci_port_test(&ehci1, i, expect[i]);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/ehci/pci/init", pci_init);
+ qtest_add_func("/ehci/pci/uhci-port-1", pci_uhci_port_1);
+ qtest_add_func("/ehci/pci/ehci-port-1", pci_ehci_port_1);
+ qtest_add_func("/ehci/pci/ehci-config", pci_ehci_config);
+ qtest_add_func("/ehci/pci/uhci-port-2", pci_uhci_port_2);
+ qtest_add_func("/ehci/pci/ehci-port-2", pci_ehci_port_2);
+
+ qtest_start("-machine q35 -device ich9-usb-ehci1,bus=pcie.0,addr=1d.7,"
+ "multifunction=on,id=ich9-ehci-1 "
+ "-device ich9-usb-uhci1,bus=pcie.0,addr=1d.0,"
+ "multifunction=on,masterbus=ich9-ehci-1.0,firstport=0 "
+ "-device ich9-usb-uhci2,bus=pcie.0,addr=1d.1,"
+ "multifunction=on,masterbus=ich9-ehci-1.0,firstport=2 "
+ "-device ich9-usb-uhci3,bus=pcie.0,addr=1d.2,"
+ "multifunction=on,masterbus=ich9-ehci-1.0,firstport=4 "
+ "-drive if=none,id=usbcdrom,media=cdrom "
+ "-device usb-tablet,bus=ich9-ehci-1.0,port=1,usb_version=1 "
+ "-device usb-storage,bus=ich9-ehci-1.0,port=2,drive=usbcdrom ");
+ ret = g_test_run();
+
+ qtest_end();
+
+ return ret;
+}
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
new file mode 100644
index 000000000..75fedf097
--- /dev/null
+++ b/tests/vhost-user-test.c
@@ -0,0 +1,421 @@
+/*
+ * QTest testcase for the vhost-user
+ *
+ * Copyright (c) 2014 Virtual Open Systems Sarl.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#define QEMU_GLIB_COMPAT_H
+#include <glib.h>
+
+#include "libqtest.h"
+#include "qemu/option.h"
+#include "sysemu/char.h"
+#include "sysemu/sysemu.h"
+
+#include <linux/vhost.h>
+#include <sys/mman.h>
+#include <sys/vfs.h>
+#include <qemu/sockets.h>
+
+/* GLIB version compatibility flags */
+#if !GLIB_CHECK_VERSION(2, 26, 0)
+#define G_TIME_SPAN_SECOND (G_GINT64_CONSTANT(1000000))
+#endif
+
+#if GLIB_CHECK_VERSION(2, 28, 0)
+#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,"\
+ "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 QEMU_CMD_ACCEL QEMU_CMD_MEM QEMU_CMD_CHR \
+ QEMU_CMD_NETDEV QEMU_CMD_NET QEMU_CMD_ROM
+
+#define HUGETLBFS_MAGIC 0x958458f6
+
+/*********** FROM hw/virtio/vhost-user.c *************************************/
+
+#define VHOST_MEMORY_MAX_NREGIONS 8
+
+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_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 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 {
+ uint64_t u64;
+ struct vhost_vring_state state;
+ struct vhost_vring_addr addr;
+ VhostUserMemory memory;
+ };
+} QEMU_PACKED VhostUserMsg;
+
+static VhostUserMsg m __attribute__ ((unused));
+#define VHOST_USER_HDR_SIZE (sizeof(m.request) \
+ + sizeof(m.flags) \
+ + sizeof(m.size))
+
+#define VHOST_USER_PAYLOAD_SIZE (sizeof(m) - VHOST_USER_HDR_SIZE)
+
+/* The version of the protocol we support */
+#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)
+{
+ gboolean ret = FALSE;
+#ifdef HAVE_COND_INIT
+ ret = g_cond_wait_until(cond, mutex, end_time);
+#else
+ 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 void read_guest_mem(void)
+{
+ uint32_t *guest_mem;
+ gint64 end_time;
+ int i, j;
+ size_t size;
+
+ g_mutex_lock(data_mutex);
+
+ end_time = _get_time() + 5 * G_TIME_SPAN_SECOND;
+ while (!fds_num) {
+ if (!_cond_wait_until(data_cond, data_mutex, end_time)) {
+ /* timeout has passed */
+ g_assert(fds_num);
+ break;
+ }
+ }
+
+ /* check for sanity */
+ g_assert_cmpint(fds_num, >, 0);
+ g_assert_cmpint(fds_num, ==, memory.nregions);
+
+ /* iterate all regions */
+ for (i = 0; i < fds_num; i++) {
+
+ /* We'll check only the region statring at 0x0*/
+ if (memory.regions[i].guest_phys_addr != 0x0) {
+ continue;
+ }
+
+ g_assert_cmpint(memory.regions[i].memory_size, >, 1024);
+
+ size = memory.regions[i].memory_size + memory.regions[i].mmap_offset;
+
+ guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fds[i], 0);
+
+ g_assert(guest_mem != MAP_FAILED);
+ guest_mem += (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 b = guest_mem[j];
+
+ g_assert_cmpint(a, ==, b);
+ }
+
+ munmap(guest_mem, memory.regions[i].memory_size);
+ }
+
+ g_assert_cmpint(1, ==, 1);
+ g_mutex_unlock(data_mutex);
+}
+
+static void *thread_function(void *data)
+{
+ GMainLoop *loop;
+ loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(loop);
+ return NULL;
+}
+
+static int chr_can_read(void *opaque)
+{
+ return VHOST_USER_HDR_SIZE;
+}
+
+static void chr_read(void *opaque, const uint8_t *buf, int size)
+{
+ CharDriverState *chr = opaque;
+ VhostUserMsg msg;
+ uint8_t *p = (uint8_t *) &msg;
+ int fd;
+
+ if (size != VHOST_USER_HDR_SIZE) {
+ g_test_message("Wrong message size received %d\n", size);
+ return;
+ }
+
+ g_mutex_lock(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);
+ }
+
+ 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;
+ p = (uint8_t *) &msg;
+ qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
+ break;
+
+ 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;
+ p = (uint8_t *) &msg;
+ qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
+ 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));
+
+ /* signal the test that it can continue */
+ g_cond_signal(data_cond);
+ break;
+
+ case VHOST_USER_SET_VRING_KICK:
+ case VHOST_USER_SET_VRING_CALL:
+ /* consume the fd */
+ qemu_chr_fe_get_msgfds(chr, &fd, 1);
+ /*
+ * This is a non-blocking eventfd.
+ * The receive function forces it to be blocking,
+ * so revert it back to non-blocking.
+ */
+ qemu_set_nonblock(fd);
+ break;
+ default:
+ break;
+ }
+ g_mutex_unlock(data_mutex);
+}
+
+static const char *init_hugepagefs(void)
+{
+ 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;
+ }
+
+ do {
+ ret = statfs(path, &fs);
+ } while (ret != 0 && errno == EINTR);
+
+ if (ret != 0) {
+ g_test_message("statfs on path (%s): %s\n", path, strerror(errno));
+ return NULL;
+ }
+
+ if (fs.f_type != HUGETLBFS_MAGIC) {
+ g_test_message("Warning: path not on HugeTLBFS: %s\n", path);
+ return NULL;
+ }
+
+ return path;
+}
+
+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;
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+
+ module_call_init(MODULE_INIT_QOM);
+
+ hugefs = init_hugepagefs();
+ if (!hugefs) {
+ return 0;
+ }
+
+ 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);
+
+ /* run the main loop thread so the chardev may operate */
+ data_mutex = _mutex_new();
+ data_cond = _cond_new();
+ _thread_new(NULL, thread_function, NULL);
+
+ 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);
+
+ ret = g_test_run();
+
+ if (s) {
+ qtest_quit(s);
+ }
+
+ /* cleanup */
+ unlink(socket_path);
+ g_free(socket_path);
+ _cond_free(data_cond);
+ _mutex_free(data_mutex);
+
+ return ret;
+}
diff --git a/tests/vmstate-static-checker-data/dump1.json b/tests/vmstate-static-checker-data/dump1.json
new file mode 100644
index 000000000..786ca0b48
--- /dev/null
+++ b/tests/vmstate-static-checker-data/dump1.json
@@ -0,0 +1,1163 @@
+{
+ "vmschkmachine": {
+ "Name": "pc-i440fx-2.1"
+ },
+ "fw_cfg": {
+ "Name": "fw_cfg",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "fw_cfg",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "cur_entry",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 2
+ },
+ {
+ "field": "cur_offset",
+ "version_id": 0,
+ "field_exists": true,
+ "size": 4
+ },
+ {
+ "field": "cur_offset",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 4
+ }
+ ]
+ }
+ },
+ "fusbh200-ehci-usb": {
+ "Name": "fusbh200-ehci-usb",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "ehci-sysbus",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "ehci",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 1880,
+ "Description": {
+ "name": "ehci-core",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "usbcmd",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "usbsts",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "usbsts_pending",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "usbsts_frindex",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "usbintr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "frindex",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "ctrldssegment",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "periodiclistbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "asynclistaddr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "configflag",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[0]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[1]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[2]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[3]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[4]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[5]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "frame_timer",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ },
+ {
+ "field": "last_run_ns",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ },
+ {
+ "field": "async_stepdown",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "astate",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "pstate",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "a_fetch_addr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "p_fetch_addr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "pci-serial-4x": {
+ "Name": "pci-serial-4x",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "pci-serial-multi",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "dev",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1944,
+ "Description": {
+ "name": "PCIDevice",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "version_id",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 256
+ },
+ {
+ "field": "irq_state",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 16
+ }
+ ]
+ }
+ },
+ {
+ "field": "state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 368,
+ "Description": {
+ "name": "serial",
+ "version_id": 3,
+ "minimum_version_id": 2,
+ "Fields": [
+ {
+ "field": "divider",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 2
+ },
+ {
+ "field": "rbr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "ier",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "iir",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "lcr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "mcr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "lsr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "msr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "scr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "fcr_vmstate",
+ "version_id": 3,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ },
+ {
+ "field": "level",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ }
+ ]
+ }
+ },
+ "intel-hda-generic": {
+ "Name": "intel-hda-generic",
+ "version_id": 1,
+ "minimum_version_id": 0,
+ "Description": {
+ "name": "intel-hda",
+ "version_id": 1,
+ "minimum_version_id": 0,
+ "Fields": [
+ {
+ "field": "pci",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1944,
+ "Description": {
+ "name": "PCIDevice",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "version_id",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 256
+ },
+ {
+ "field": "irq_state",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 16
+ }
+ ]
+ }
+ },
+ {
+ "field": "g_ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "wake_en",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "state_sts",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "int_ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "int_sts",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "wall_clk",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_lbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_ubase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_rp",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_wp",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_sts",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_size",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_lbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_ubase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_wp",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_cnt",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_sts",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_size",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "dp_lbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "dp_ubase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "icw",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "irr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "ics",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "st",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 56,
+ "Description": {
+ "name": "intel-hda-stream",
+ "version_id": 1,
+ "minimum_version_id": 0,
+ "Fields": [
+ {
+ "field": "ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "lpib",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "cbl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "lvi",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "fmt",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "bdlp_lbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "bdlp_ubase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ }
+ ]
+ }
+ },
+ {
+ "field": "rirb_count",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "wall_base_ns",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ }
+ ]
+ }
+ },
+ "cfi.pflash01": {
+ "Name": "cfi.pflash01",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "pflash_cfi01",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "wcycle",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "cmd",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "status",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "counter",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ }
+ ]
+ }
+ },
+ "megasas": {
+ "Name": "megasas",
+ "version_id": 0,
+ "minimum_version_id": 0,
+ "Description": {
+ "name": "megasas",
+ "version_id": 0,
+ "minimum_version_id": 0,
+ "Fields": [
+ {
+ "field": "parent_obj",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1944,
+ "Description": {
+ "name": "PCIDevice",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "version_id",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 256
+ },
+ {
+ "field": "irq_state",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 16
+ }
+ ]
+ }
+ },
+ {
+ "field": "fw_state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "intr_mask",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "doorbell",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "reply_queue_pa",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ },
+ {
+ "field": "consumer_pa",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ },
+ {
+ "field": "producer_pa",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ }
+ ]
+ }
+ },
+ "PIIX3-xen": {
+ "Name": "PIIX3-xen",
+ "version_id": 3,
+ "minimum_version_id": 2,
+ "Description": {
+ "name": "PIIX3",
+ "version_id": 1,
+ "minimum_version_id": 2,
+ "Fields": [
+ {
+ "field": "dev",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1944,
+ "Description": {
+ "name": "PCIDevice",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "version_id",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 256
+ },
+ {
+ "field": "irq_state",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 16
+ }
+ ]
+ }
+ },
+ {
+ "field": "pci_irq_levels_vmstate",
+ "version_id": 3,
+ "field_exists": false,
+ "size": 4
+ }
+ ],
+ "Subsections": [
+ {
+ "name": "PIIX3/rcr",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "rcr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ ]
+ }
+ },
+ "tpci200": {
+ "Name": "tpci200",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "tpci200",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "dev",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1944,
+ "Description": {
+ "name": "PCIDevice",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "version_id",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 256
+ },
+ {
+ "field": "irq_state",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 16
+ }
+ ]
+ }
+ },
+ {
+ "field": "big_endian",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "ctrl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "status",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 2
+ },
+ {
+ "field": "int_set",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ },
+ "SUNW,fdtwo": {
+ "Name": "SUNW,fdtwo",
+ "version_id": 2,
+ "minimum_version_id": 2,
+ "Description": {
+ "name": "fdc",
+ "version_id": 2,
+ "minimum_version_id": 2,
+ "Fields": [
+ {
+ "field": "state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 360,
+ "Description": {
+ "name": "fdc",
+ "version_id": 2,
+ "minimum_version_id": 2,
+ "Fields": [
+ {
+ "field": "sra",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "srb",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "dor_vmstate",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "tdr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "dsr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "msr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "status0",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "status1",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "status2",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "fifo",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "data_pos",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "data_len",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "data_state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "data_dir",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "eot",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "timer0",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "timer1",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "precomp_trk",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "lock",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "pwrd",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "num_floppies",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "drives",
+ "version_id": 1,
+ "field_exists": false,
+ "size": 40,
+ "Description": {
+ "name": "fdrive",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "head",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "track",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "sect",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ],
+ "Subsections": [
+ {
+ "name": "fdrive/media_changed",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "media_changed",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ },
+ {
+ "name": "fdrive/media_rate",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "media_rate",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "usb-kbd": {
+ "Name": "usb-kbd",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "usb-kbd",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "dev",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4352,
+ "Description": {
+ "name": "USBDevice",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "addr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "remote_wakeup",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "setup_state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "setup_len",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "setup_index",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "setup_buf",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ },
+ {
+ "field": "kbd.keycodes",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "head",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "n",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "kbd.modifiers",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 2
+ },
+ {
+ "field": "kbd.leds",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "kbd.key",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "kbd.keys",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "protocol",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "idle",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/vmstate-static-checker-data/dump2.json b/tests/vmstate-static-checker-data/dump2.json
new file mode 100644
index 000000000..75719f5ec
--- /dev/null
+++ b/tests/vmstate-static-checker-data/dump2.json
@@ -0,0 +1,968 @@
+{
+ "vmschkmachine": {
+ "Name": "pc-i440fx-2.2"
+ },
+ "fw_cfg2": {
+ "Name": "fw_cfg",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "fw_cfg",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "cur_entry",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 2
+ },
+ {
+ "field": "cur_offset",
+ "version_id": 0,
+ "field_exists": true,
+ "size": 4
+ },
+ {
+ "field": "cur_offset",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 4
+ }
+ ]
+ }
+ },
+ "fusbh200-ehci-usb": {
+ "Name": "fusbh200-ehci-usb",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "ehci-sysbus",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "ehci",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 1880,
+ "Description": {
+ "name": "ehci-core",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "usbcmd",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "usbsts_pending",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "usbsts_frindex",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "usbintr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "frindex",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "ctrldssegment",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "periodiclistbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "asynclistaddr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "configflag",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[0]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[1]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[2]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[3]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[4]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "portsc[5]",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "frame_timer",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ },
+ {
+ "field": "last_run_ns",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ },
+ {
+ "field": "async_stepdown",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "astate",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "pstate",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "a_fetch_addr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "p_fetch_addr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "pci-serial-4x": {
+ "Name": "pci-serial-4x",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "pci-serial-multi",
+ "version_id": 1,
+ "minimum_version_id": 1
+ }
+ },
+ "intel-hda-generic": {
+ "Name": "intel-hda-generic",
+ "version_id": 1,
+ "minimum_version_id": 0,
+ "Description": {
+ "name": "intel-hda",
+ "version_id": 1,
+ "minimum_version_id": 0,
+ "Fields": [
+ {
+ "field": "pci",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1944
+ },
+ {
+ "field": "g_ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "wake_en",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "state_sts",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "int_ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "int_sts",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "wall_clk",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_lbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_ubase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_rp",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_wp",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_sts",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "corb_size",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_lbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_ubase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_wp",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_cnt",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_sts",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "rirb_size",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "dp_lbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "dp_ubase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "icw",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "irr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "ics",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "st",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 56,
+ "Description": {
+ "name": "intel-hda-stream",
+ "version_id": 1,
+ "minimum_version_id": 0,
+ "Fields": [
+ {
+ "field": "ctl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "lpib",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "cbl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "lvi",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "fmt",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "bdlp_lbase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "bdlp_ubase",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ }
+ ]
+ }
+ },
+ {
+ "field": "rirb_count",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "wall_base_ns",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ }
+ ]
+ }
+ },
+ "cfi.pflash01": {
+ "Name": "cfi.pflash01",
+ "version_id": 1,
+ "minimum_version_id": 1
+ },
+ "megasas": {
+ "Name": "megasas",
+ "version_id": 0,
+ "minimum_version_id": 0,
+ "Description": {
+ "name": "megasas",
+ "version_id": 0,
+ "minimum_version_id": 0,
+ "Fields": [
+ {
+ "field": "parent_obj",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1944,
+ "Description": {
+ "name": "PCIDevice",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "version_id",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 256
+ }
+ ]
+ }
+ },
+ {
+ "field": "fw_state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "intr_mask",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "doorbell",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "reply_queue_pa",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ },
+ {
+ "field": "consumer_pa",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ },
+ {
+ "field": "producer_pa",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 8
+ }
+ ]
+ }
+ },
+ "PIIX3-xen": {
+ "Name": "PIIX3-xen",
+ "version_id": 3,
+ "minimum_version_id": 2,
+ "Description": {
+ "name": "PIIX3",
+ "version_id": 3,
+ "minimum_version_id": 2,
+ "Fields": [
+ {
+ "field": "dev",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1944,
+ "Description": {
+ "name": "PCIDevice",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "version_id",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 256
+ },
+ {
+ "field": "irq_state",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 16
+ }
+ ]
+ }
+ },
+ {
+ "field": "pci_irq_levels_vmstate",
+ "version_id": 3,
+ "field_exists": false,
+ "size": 4
+ }
+ ]
+ }
+ },
+ "tpci200": {
+ "Name": "tpci200",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "tpci2002",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "dev",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1944,
+ "Description": {
+ "name": "PCIDevice",
+ "version_id": 2,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "version_id",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 256
+ },
+ {
+ "field": "irq_state",
+ "version_id": 2,
+ "field_exists": false,
+ "size": 16
+ }
+ ]
+ }
+ },
+ {
+ "field": "big_endian",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "ctrl",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "status",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 2
+ },
+ {
+ "field": "int_set",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ },
+ "SUNW,fdtwo": {
+ "Name": "SUNW,fdtwo",
+ "version_id": 2,
+ "minimum_version_id": 2,
+ "Description": {
+ "name": "fdc",
+ "version_id": 1,
+ "minimum_version_id": 2,
+ "Fields": [
+ {
+ "field": "state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 360,
+ "Description": {
+ "name": "fdc",
+ "version_id": 2,
+ "minimum_version_id": 2,
+ "Fields": [
+ {
+ "field": "sra",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "srb",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "dor_vmstate",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "tdr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "dsr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "msr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "status0",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "status1",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "status2",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "fifo",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "data_pos",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "data_len",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "data_state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "data_dir",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "eot",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "timer0",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "timer1",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "precomp_trk",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "config",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "lock",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "pwrd",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "num_floppies",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "drives",
+ "version_id": 1,
+ "field_exists": false,
+ "size": 40,
+ "Description": {
+ "name": "fdrive",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "head",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "track",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "sect",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ],
+ "Subsections": [
+ {
+ "name": "fdrive/media_changed",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "media_changed",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "usb-kbd": {
+ "Name": "usb-kbd",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Description": {
+ "name": "usb-kbd",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "dev",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 5832,
+ "Description": {
+ "name": "USBDevice",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "addr",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "remote_wakeup",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "setup_state",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "setup_len",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "setup_index",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "setup_buf",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ },
+ {
+ "field": "hid",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 312,
+ "Description": {
+ "name": "HIDKeyboardDevice",
+ "version_id": 1,
+ "minimum_version_id": 1,
+ "Fields": [
+ {
+ "field": "kbd.keycodes",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 2
+ },
+ {
+ "field": "head",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "n",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "kbd.modifiers",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 2
+ },
+ {
+ "field": "kbd.leds",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "kbd.key",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ },
+ {
+ "field": "kbd.keys",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "protocol",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 4
+ },
+ {
+ "field": "idle",
+ "version_id": 0,
+ "field_exists": false,
+ "size": 1
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/wdt_ib700-test.c b/tests/wdt_ib700-test.c
new file mode 100644
index 000000000..513a53385
--- /dev/null
+++ b/tests/wdt_ib700-test.c
@@ -0,0 +1,134 @@
+/*
+ * QTest testcase for the IB700 watchdog
+ *
+ * Copyright (c) 2014 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 <glib.h>
+#include <string.h>
+#include "libqtest.h"
+#include "qemu/osdep.h"
+
+#define NS_PER_SEC 1000000000ULL
+
+static void qmp_check_no_event(void)
+{
+ QDict *resp = qmp("{'execute':'query-status'}");
+ g_assert(qdict_haskey(resp, "return"));
+ QDECREF(resp);
+}
+
+static QDict *qmp_get_event(const char *name)
+{
+ QDict *event = qmp("");
+ QDict *data;
+ g_assert(qdict_haskey(event, "event"));
+ g_assert(!strcmp(qdict_get_str(event, "event"), name));
+
+ if (qdict_haskey(event, "data")) {
+ data = qdict_get_qdict(event, "data");
+ QINCREF(data);
+ } else {
+ data = NULL;
+ }
+
+ QDECREF(event);
+ return data;
+}
+
+static QDict *ib700_program_and_wait(QTestState *s)
+{
+ clock_step(NS_PER_SEC * 40);
+ qmp_check_no_event();
+
+ /* 2 second limit */
+ outb(0x443, 14);
+
+ /* Ping */
+ clock_step(NS_PER_SEC);
+ qmp_check_no_event();
+ outb(0x443, 14);
+
+ /* Disable */
+ clock_step(NS_PER_SEC);
+ qmp_check_no_event();
+ outb(0x441, 1);
+ clock_step(3 * NS_PER_SEC);
+ qmp_check_no_event();
+
+ /* Enable and let it fire */
+ outb(0x443, 13);
+ clock_step(3 * NS_PER_SEC);
+ qmp_check_no_event();
+ clock_step(2 * NS_PER_SEC);
+ return qmp_get_event("WATCHDOG");
+}
+
+
+static void ib700_pause(void)
+{
+ QDict *d;
+ QTestState *s = qtest_start("-watchdog-action pause -device ib700");
+ qtest_irq_intercept_in(s, "ioapic");
+ d = ib700_program_and_wait(s);
+ g_assert(!strcmp(qdict_get_str(d, "action"), "pause"));
+ QDECREF(d);
+ d = qmp_get_event("STOP");
+ QDECREF(d);
+ qtest_end();
+}
+
+static void ib700_reset(void)
+{
+ QDict *d;
+ QTestState *s = qtest_start("-watchdog-action reset -device ib700");
+ qtest_irq_intercept_in(s, "ioapic");
+ d = ib700_program_and_wait(s);
+ g_assert(!strcmp(qdict_get_str(d, "action"), "reset"));
+ QDECREF(d);
+ d = qmp_get_event("RESET");
+ QDECREF(d);
+ qtest_end();
+}
+
+static void ib700_shutdown(void)
+{
+ QDict *d;
+ QTestState *s = qtest_start("-watchdog-action reset -no-reboot -device ib700");
+ qtest_irq_intercept_in(s, "ioapic");
+ d = ib700_program_and_wait(s);
+ g_assert(!strcmp(qdict_get_str(d, "action"), "reset"));
+ QDECREF(d);
+ d = qmp_get_event("SHUTDOWN");
+ QDECREF(d);
+ qtest_end();
+}
+
+static void ib700_none(void)
+{
+ QDict *d;
+ QTestState *s = qtest_start("-watchdog-action none -device ib700");
+ qtest_irq_intercept_in(s, "ioapic");
+ d = ib700_program_and_wait(s);
+ g_assert(!strcmp(qdict_get_str(d, "action"), "none"));
+ QDECREF(d);
+ qtest_end();
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/wdt_ib700/pause", ib700_pause);
+ qtest_add_func("/wdt_ib700/reset", ib700_reset);
+ qtest_add_func("/wdt_ib700/shutdown", ib700_shutdown);
+ qtest_add_func("/wdt_ib700/none", ib700_none);
+
+ ret = g_test_run();
+
+ return ret;
+}