diff options
Diffstat (limited to 'tests')
36 files changed, 1427 insertions, 60 deletions
diff --git a/tests/Makefile b/tests/Makefile index ba93e8a1d4..361bb7b6e3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -60,6 +60,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 @@ -152,6 +154,8 @@ 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-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)) @@ -317,8 +321,9 @@ 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 +tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-pc-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 # QTest rules diff --git a/tests/check-qdict.c b/tests/check-qdict.c index 2ad0f7827e..a9296f0833 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/libqos/pci.c b/tests/libqos/pci.c index 7e0907b514..c9a0b9134a 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/qemu-iotests/030 b/tests/qemu-iotests/030 index 8cb61fd7ec..8ce2373cf5 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): diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039 index b9cbe99560..27fe4bdacc 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 @@ -67,10 +72,7 @@ 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 @@ -103,10 +105,7 @@ 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 @@ -122,10 +121,7 @@ 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 diff --git a/tests/qemu-iotests/039.out b/tests/qemu-iotests/039.out index fb31ae0624..67e774430f 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/067.out b/tests/qemu-iotests/067.out index 8d271cc41a..7e090b95ab 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 ce71fa4a22..ea0dae7e9c 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 922d62cb51..15f1fc1471 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/089 b/tests/qemu-iotests/089 new file mode 100755 index 0000000000..dffc977e1c --- /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 0000000000..4ca2f88e6a --- /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/091 b/tests/qemu-iotests/091 index 384b3ace54..32bbd56975 100755 --- a/tests/qemu-iotests/091 +++ b/tests/qemu-iotests/091 @@ -47,6 +47,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 _supported_fmt qcow2 _supported_proto file _supported_os Linux +_default_cache_mode "none" +_supported_cache_modes "writethrough" "none" "writeback" size=1G @@ -59,13 +61,13 @@ echo === Starting QEMU VM1 === echo qemu_comm_method="monitor" -_launch_qemu -drive file="${TEST_IMG}",cache=none,id=disk +_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=none,id=disk \ +_launch_qemu -drive file="${TEST_IMG}",cache=${CACHEMODE},id=disk \ -incoming "exec: cat '${MIG_FIFO}'" h2=$QEMU_HANDLE diff --git a/tests/qemu-iotests/092 b/tests/qemu-iotests/092 new file mode 100755 index 0000000000..a8c0c9ca2b --- /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 0000000000..496d8f0a63 --- /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/common.filter b/tests/qemu-iotests/common.filter index 776985d15e..a04df7f6dc 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/group b/tests/qemu-iotests/group index cd3e4d2c27..0f074403ae 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -95,5 +95,7 @@ 086 rw auto quick 087 rw auto 088 rw auto +089 rw auto quick 090 rw auto quick 091 rw auto +092 rw auto quick 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 0000000000..2891c9a6d6 --- /dev/null +++ b/tests/qemu-iotests/sample_images/test-disk2vhd.vhdx.bz2 Binary files differdiff --git a/tests/qom-test.c b/tests/qom-test.c index 6d9a00b448..d8d1d8d9ff 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; @@ -56,14 +56,21 @@ static void test_properties(const char *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"); @@ -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/lm32/Makefile b/tests/tcg/lm32/Makefile index 8e5d405459..57e7363b2c 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 5f9cfd95d3..fc437a3de1 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 0000000000..3351d41e84 --- /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 367c7c50d8..360ad53c9f 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 f84d21ead9..d677eea4c4 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 4c1786ad71..dc5d5f67d3 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 e57d9e35cf..397996bddd 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 e648775d94..8de7c52560 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 f8c919d2b8..996e5f8c88 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 89e39d621d..b15a89d342 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 b442e32374..46032f841d 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 ea8b3f2067..bba10224f6 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 d1fdadce61..2b1c017e7b 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/xtensa/test_mmu.S b/tests/tcg/xtensa/test_mmu.S index 099031fd14..58c5bca30e 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-qemu-opts.c b/tests/test-qemu-opts.c new file mode 100644 index 0000000000..3653507f56 --- /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 */ } + }, +}; + +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-output-visitor.c b/tests/test-qmp-output-visitor.c index 9c154581d7..74020de5e7 100644 --- a/tests/test-qmp-output-visitor.c +++ b/tests/test-qmp-output-visitor.c @@ -507,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; @@ -859,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-thread-pool.c b/tests/test-thread-pool.c index c1f8e13a9f..aa156bcd32 100644 --- a/tests/test-thread-pool.c +++ b/tests/test-thread-pool.c @@ -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/usb-hcd-ehci-test.c b/tests/usb-hcd-ehci-test.c index bc56ba7707..bcdf62fc3b 100644 --- a/tests/usb-hcd-ehci-test.c +++ b/tests/usb-hcd-ehci-test.c @@ -9,12 +9,149 @@ #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" -/* Tests only initialization so far. TODO: Replace with functional tests */ -static void pci_nop(void) +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) @@ -22,7 +159,12 @@ int main(int argc, char **argv) int ret; g_test_init(&argc, &argv, NULL); - qtest_add_func("/ehci/pci/nop", pci_nop); + 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 " @@ -31,7 +173,10 @@ int main(int argc, char **argv) "-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"); + "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(); |