diff options
author | Anthony Liguori <aliguori@amazon.com> | 2013-11-13 11:47:44 -0800 |
---|---|---|
committer | Anthony Liguori <aliguori@amazon.com> | 2013-11-13 11:47:44 -0800 |
commit | deb0f500651317863922964c87b4fa64eecdbd73 (patch) | |
tree | f67b4c5eabb590c5a51b64796cdb19e1dce07847 /tests | |
parent | 70c4c5b5621f6d954843547bcab9db857d882e99 (diff) | |
parent | 7e382003f1bd9d8a441ecc5ac8a74bad3564d943 (diff) | |
download | qemu-deb0f500651317863922964c87b4fa64eecdbd73.tar.gz |
Merge remote-tracking branch 'stefanha/block' into staging
# By Jeff Cody (26) and others
# Via Stefan Hajnoczi
* stefanha/block: (37 commits)
block: Round up total_sectors
block: vhdx qemu-iotest - log replay of data sector
block: qemu-iotests for vhdx, add write test support
block: vhdx - update _make_test_img() to filter out vhdx options
block: vhdx - add .bdrv_create() support
block: vhdx - fix comment typos in header, fix incorrect struct fields
block: vhdx - break out code operations to functions
block: vhdx - move more endian translations to vhdx-endian.c
block: vhdx - remove BAT file offset bit shifting
block: vhdx write support
block: vhdx - add log write support
block: vhdx - add region overlap detection for image files
block: vhdx - log parsing, replay, and flush support
block: vhdx code movement - move vhdx_close() above vhdx_open()
block: vhdx - update log guid in header, and first write tracker
block: vhdx - break endian translation functions out
block: vhdx - log support struct and defines
block: vhdx code movement - VHDXMetadataEntries and BDRVVHDXState to header.
block: vhdx - add header update capability.
block: vhdx - minor comments and typo correction.
...
Message-id: 1383905551-16411-1-git-send-email-stefanha@redhat.com
Signed-off-by: Anthony Liguori <aliguori@amazon.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile | 4 | ||||
-rw-r--r-- | tests/blockdev-test.c | 59 | ||||
-rw-r--r-- | tests/boot-order-test.c | 4 | ||||
-rw-r--r-- | tests/fdc-test.c | 15 | ||||
-rw-r--r-- | tests/ide-test.c | 10 | ||||
-rw-r--r-- | tests/libqtest.c | 72 | ||||
-rw-r--r-- | tests/libqtest.h | 51 | ||||
-rw-r--r-- | tests/qdev-monitor-test.c | 81 | ||||
-rwxr-xr-x | tests/qemu-iotests/017 | 2 | ||||
-rwxr-xr-x | tests/qemu-iotests/019 | 6 | ||||
-rwxr-xr-x | tests/qemu-iotests/039 | 2 | ||||
-rwxr-xr-x | tests/qemu-iotests/051 | 8 | ||||
-rwxr-xr-x | tests/qemu-iotests/061 | 6 | ||||
-rwxr-xr-x | tests/qemu-iotests/064 | 11 | ||||
-rw-r--r-- | tests/qemu-iotests/064.out | 14 | ||||
-rwxr-xr-x | tests/qemu-iotests/067 | 2 | ||||
-rw-r--r-- | tests/qemu-iotests/067.out | 10 | ||||
-rwxr-xr-x | tests/qemu-iotests/070 | 67 | ||||
-rw-r--r-- | tests/qemu-iotests/070.out | 8 | ||||
-rw-r--r-- | tests/qemu-iotests/common | 1 | ||||
-rw-r--r-- | tests/qemu-iotests/common.pattern | 12 | ||||
-rw-r--r-- | tests/qemu-iotests/common.rc | 18 | ||||
-rw-r--r-- | tests/qemu-iotests/group | 1 | ||||
-rw-r--r-- | tests/qemu-iotests/sample_images/iotest-dirtylog-10G-4M.vhdx.bz2 | bin | 0 -> 4490 bytes |
24 files changed, 400 insertions, 64 deletions
diff --git a/tests/Makefile b/tests/Makefile index f414f2c80a..379cdd9ad1 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -68,6 +68,8 @@ 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/qom-test$(EXESUF) +check-qtest-i386-y += tests/blockdev-test$(EXESUF) +check-qtest-i386-y += tests/qdev-monitor-test$(EXESUF) check-qtest-x86_64-y = $(check-qtest-i386-y) gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y)) @@ -200,6 +202,8 @@ 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) tests/qom-test$(EXESUF): tests/qom-test.o +tests/blockdev-test$(EXESUF): tests/blockdev-test.o $(libqos-pc-obj-y) +tests/qdev-monitor-test$(EXESUF): tests/qdev-monitor-test.o $(libqos-pc-obj-y) tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o # QTest rules diff --git a/tests/blockdev-test.c b/tests/blockdev-test.c new file mode 100644 index 0000000000..c940e00690 --- /dev/null +++ b/tests/blockdev-test.c @@ -0,0 +1,59 @@ +/* + * blockdev.c test cases + * + * Copyright (C) 2013 Red Hat Inc. + * + * Authors: + * Stefan Hajnoczi <stefanha@redhat.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 <string.h> +#include "libqtest.h" + +static void test_drive_add_empty(void) +{ + QDict *response; + const char *response_return; + + /* Start with an empty drive */ + qtest_start("-drive if=none,id=drive0"); + + /* Delete the drive */ + response = qmp("{\"execute\": \"human-monitor-command\"," + " \"arguments\": {" + " \"command-line\": \"drive_del drive0\"" + "}}"); + g_assert(response); + response_return = qdict_get_try_str(response, "return"); + g_assert(response_return); + g_assert(strcmp(response_return, "") == 0); + QDECREF(response); + + /* Ensure re-adding the drive works - there should be no duplicate ID error + * because the old drive must be gone. + */ + response = qmp("{\"execute\": \"human-monitor-command\"," + " \"arguments\": {" + " \"command-line\": \"drive_add 0 if=none,id=drive0\"" + "}}"); + g_assert(response); + response_return = qdict_get_try_str(response, "return"); + g_assert(response_return); + g_assert(strcmp(response_return, "OK\r\n") == 0); + QDECREF(response); + + qtest_end(); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/qmp/drive_add_empty", test_drive_add_empty); + + return g_test_run(); +} diff --git a/tests/boot-order-test.c b/tests/boot-order-test.c index 4b233d0b24..da158c32bd 100644 --- a/tests/boot-order-test.c +++ b/tests/boot-order-test.c @@ -41,12 +41,12 @@ static void test_a_boot_order(const char *machine, qtest_start(args); actual = read_boot_order(); g_assert_cmphex(actual, ==, expected_boot); - qmp("{ 'execute': 'system_reset' }"); + qmp_discard_response("{ 'execute': 'system_reset' }"); /* * system_reset only requests reset. We get a RESET event after * the actual reset completes. Need to wait for that. */ - qmp(""); /* HACK: wait for event */ + qmp_discard_response(""); /* HACK: wait for event */ actual = read_boot_order(); g_assert_cmphex(actual, ==, expected_reboot); qtest_quit(global_qtest); diff --git a/tests/fdc-test.c b/tests/fdc-test.c index fd198dcf8b..38b5b178d0 100644 --- a/tests/fdc-test.c +++ b/tests/fdc-test.c @@ -290,10 +290,12 @@ static void test_media_insert(void) /* Insert media in drive. DSKCHK should not be reset until a step pulse * is sent. */ - qmp("{'execute':'change', 'arguments':{ 'device':'floppy0', " - "'target': '%s' }}", test_image); - qmp(""); /* ignore event (FIXME open -> open transition?!) */ - qmp(""); /* ignore event */ + qmp_discard_response("{'execute':'change', 'arguments':{" + " 'device':'floppy0', 'target': '%s' }}", + test_image); + qmp_discard_response(""); /* ignore event + (FIXME open -> open transition?!) */ + qmp_discard_response(""); /* ignore event */ dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); @@ -322,8 +324,9 @@ static void test_media_change(void) /* Eject the floppy and check that DSKCHG is set. Reading it out doesn't * reset the bit. */ - qmp("{'execute':'eject', 'arguments':{ 'device':'floppy0' }}"); - qmp(""); /* ignore event */ + qmp_discard_response("{'execute':'eject', 'arguments':{" + " 'device':'floppy0' }}"); + qmp_discard_response(""); /* ignore event */ dir = inb(FLOPPY_BASE + reg_dir); assert_bit_set(dir, DSKCHG); diff --git a/tests/ide-test.c b/tests/ide-test.c index bc824a8144..d5cec5a1fc 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -460,8 +460,9 @@ static void test_flush(void) tmp_path); /* Delay the completion of the flush request until we explicitly do it */ - qmp("{'execute':'human-monitor-command', 'arguments': { " - "'command-line': 'qemu-io ide0-hd0 \"break flush_to_os A\"'} }"); + qmp_discard_response("{'execute':'human-monitor-command', 'arguments': {" + " 'command-line':" + " 'qemu-io ide0-hd0 \"break flush_to_os A\"'} }"); /* FLUSH CACHE command on device 0*/ outb(IDE_BASE + reg_device, 0); @@ -473,8 +474,9 @@ static void test_flush(void) assert_bit_clear(data, DF | ERR | DRQ); /* Complete the command */ - qmp("{'execute':'human-monitor-command', 'arguments': { " - "'command-line': 'qemu-io ide0-hd0 \"resume A\"'} }"); + qmp_discard_response("{'execute':'human-monitor-command', 'arguments': {" + " 'command-line':" + " 'qemu-io ide0-hd0 \"resume A\"'} }"); /* Check registers */ data = inb(IDE_BASE + reg_device); diff --git a/tests/libqtest.c b/tests/libqtest.c index bb82069f5c..83424c3c6b 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -30,6 +30,8 @@ #include "qemu/compiler.h" #include "qemu/osdep.h" +#include "qapi/qmp/json-streamer.h" +#include "qapi/qmp/json-parser.h" #define MAX_IRQ 256 @@ -151,8 +153,8 @@ QTestState *qtest_init(const char *extra_args) } /* Read the QMP greeting and then do the handshake */ - qtest_qmp(s, ""); - qtest_qmp(s, "{ 'execute': 'qmp_capabilities' }"); + qtest_qmp_discard_response(s, ""); + qtest_qmp_discard_response(s, "{ 'execute': 'qmp_capabilities' }"); if (getenv("QTEST_STOP")) { kill(qtest_qemu_pid(s), SIGSTOP); @@ -291,16 +293,38 @@ redo: return words; } -void qtest_qmpv(QTestState *s, const char *fmt, va_list ap) +typedef struct { + JSONMessageParser parser; + QDict *response; +} QMPResponseParser; + +static void qmp_response(JSONMessageParser *parser, QList *tokens) +{ + QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser); + QObject *obj; + + obj = json_parser_parse(tokens, NULL); + if (!obj) { + fprintf(stderr, "QMP JSON response parsing failed\n"); + exit(1); + } + + g_assert(qobject_type(obj) == QTYPE_QDICT); + g_assert(!qmp->response); + qmp->response = (QDict *)obj; +} + +QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap) { - bool has_reply = false; - int nesting = 0; + QMPResponseParser qmp; /* Send QMP request */ socket_sendf(s->qmp_fd, fmt, ap); /* Receive reply */ - while (!has_reply || nesting > 0) { + qmp.response = NULL; + json_message_parser_init(&qmp.parser, qmp_response); + while (!qmp.response) { ssize_t len; char c; @@ -314,25 +338,39 @@ void qtest_qmpv(QTestState *s, const char *fmt, va_list ap) exit(1); } - switch (c) { - case '{': - nesting++; - has_reply = true; - break; - case '}': - nesting--; - break; - } + json_message_parser_feed(&qmp.parser, &c, 1); } + json_message_parser_destroy(&qmp.parser); + + return qmp.response; +} + +QDict *qtest_qmp(QTestState *s, const char *fmt, ...) +{ + va_list ap; + QDict *response; + + va_start(ap, fmt); + response = qtest_qmpv(s, fmt, ap); + va_end(ap); + return response; +} + +void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list ap) +{ + QDict *response = qtest_qmpv(s, fmt, ap); + QDECREF(response); } -void qtest_qmp(QTestState *s, const char *fmt, ...) +void qtest_qmp_discard_response(QTestState *s, const char *fmt, ...) { va_list ap; + QDict *response; va_start(ap, fmt); - qtest_qmpv(s, fmt, ap); + response = qtest_qmpv(s, fmt, ap); va_end(ap); + QDECREF(response); } const char *qtest_get_arch(void) diff --git a/tests/libqtest.h b/tests/libqtest.h index a6e99bd023..9deebdcdfa 100644 --- a/tests/libqtest.h +++ b/tests/libqtest.h @@ -22,6 +22,7 @@ #include <stdbool.h> #include <stdarg.h> #include <sys/types.h> +#include "qapi/qmp/qdict.h" typedef struct QTestState QTestState; @@ -44,13 +45,32 @@ QTestState *qtest_init(const char *extra_args); void qtest_quit(QTestState *s); /** + * qtest_qmp_discard_response: + * @s: #QTestState instance to operate on. + * @fmt...: QMP message to send to qemu + * + * Sends a QMP message to QEMU and consumes the response. + */ +void qtest_qmp_discard_response(QTestState *s, const char *fmt, ...); + +/** * qtest_qmp: * @s: #QTestState instance to operate on. * @fmt...: QMP message to send to qemu * - * Sends a QMP message to QEMU + * Sends a QMP message to QEMU and returns the response. + */ +QDict *qtest_qmp(QTestState *s, const char *fmt, ...); + +/** + * qtest_qmpv_discard_response: + * @s: #QTestState instance to operate on. + * @fmt: QMP message to send to QEMU + * @ap: QMP message arguments + * + * Sends a QMP message to QEMU and consumes the response. */ -void qtest_qmp(QTestState *s, const char *fmt, ...); +void qtest_qmpv_discard_response(QTestState *s, const char *fmt, va_list ap); /** * qtest_qmpv: @@ -58,9 +78,9 @@ void qtest_qmp(QTestState *s, const char *fmt, ...); * @fmt: QMP message to send to QEMU * @ap: QMP message arguments * - * Sends a QMP message to QEMU. + * Sends a QMP message to QEMU and returns the response. */ -void qtest_qmpv(QTestState *s, const char *fmt, va_list ap); +QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap); /** * qtest_get_irq: @@ -334,14 +354,31 @@ static inline void qtest_end(void) * qmp: * @fmt...: QMP message to send to qemu * - * Sends a QMP message to QEMU + * Sends a QMP message to QEMU and returns the response. + */ +static inline QDict *qmp(const char *fmt, ...) +{ + va_list ap; + QDict *response; + + va_start(ap, fmt); + response = qtest_qmpv(global_qtest, fmt, ap); + va_end(ap); + return response; +} + +/** + * qmp_discard_response: + * @fmt...: QMP message to send to qemu + * + * Sends a QMP message to QEMU and consumes the response. */ -static inline void qmp(const char *fmt, ...) +static inline void qmp_discard_response(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - qtest_qmpv(global_qtest, fmt, ap); + qtest_qmpv_discard_response(global_qtest, fmt, ap); va_end(ap); } diff --git a/tests/qdev-monitor-test.c b/tests/qdev-monitor-test.c new file mode 100644 index 0000000000..33a8ea4b9c --- /dev/null +++ b/tests/qdev-monitor-test.c @@ -0,0 +1,81 @@ +/* + * qdev-monitor.c test cases + * + * Copyright (C) 2013 Red Hat Inc. + * + * Authors: + * Stefan Hajnoczi <stefanha@redhat.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 <string.h> +#include <glib.h> +#include "libqtest.h" +#include "qapi/qmp/qjson.h" + +static void test_device_add(void) +{ + QDict *response; + QDict *error; + + qtest_start("-drive if=none,id=drive0"); + + /* Make device_add fail. If this leaks the virtio-blk-pci device then a + * reference to drive0 will also be held (via qdev properties). + */ + response = qmp("{\"execute\": \"device_add\"," + " \"arguments\": {" + " \"driver\": \"virtio-blk-pci\"," + " \"drive\": \"drive0\"" + "}}"); + g_assert(response); + error = qdict_get_qdict(response, "error"); + g_assert(!strcmp(qdict_get_try_str(error, "class") ?: "", + "GenericError")); + g_assert(!strcmp(qdict_get_try_str(error, "desc") ?: "", + "Device initialization failed.")); + QDECREF(response); + + /* Delete the drive */ + response = qmp("{\"execute\": \"human-monitor-command\"," + " \"arguments\": {" + " \"command-line\": \"drive_del drive0\"" + "}}"); + g_assert(response); + g_assert(!strcmp(qdict_get_try_str(response, "return") ?: "(null)", "")); + QDECREF(response); + + /* Try to re-add the drive. This fails with duplicate IDs if a leaked + * virtio-blk-pci exists that holds a reference to the old drive0. + */ + response = qmp("{\"execute\": \"human-monitor-command\"," + " \"arguments\": {" + " \"command-line\": \"drive_add pci-addr=auto if=none,id=drive0\"" + "}}"); + g_assert(response); + g_assert(!strcmp(qdict_get_try_str(response, "return") ?: "", + "OK\r\n")); + QDECREF(response); + + qtest_end(); +} + +int main(int argc, char **argv) +{ + const char *arch = qtest_get_arch(); + + /* Check architecture */ + if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) { + g_test_message("Skipping test for non-x86\n"); + return 0; + } + + /* Run the tests */ + g_test_init(&argc, &argv, NULL); + + qtest_add_func("/qmp/device_add", test_device_add); + + return g_test_run(); +} diff --git a/tests/qemu-iotests/017 b/tests/qemu-iotests/017 index 45f2c0b055..aba3faf712 100755 --- a/tests/qemu-iotests/017 +++ b/tests/qemu-iotests/017 @@ -66,7 +66,7 @@ echo "Creating test image with backing file" echo TEST_IMG=$TEST_IMG_SAVE -_make_test_img -b $TEST_IMG.base 6G +_make_test_img -b "$TEST_IMG.base" 6G echo "Filling test image" echo diff --git a/tests/qemu-iotests/019 b/tests/qemu-iotests/019 index cd3582cf6f..5bb18d0c0a 100755 --- a/tests/qemu-iotests/019 +++ b/tests/qemu-iotests/019 @@ -90,12 +90,12 @@ mv "$TEST_IMG" "$TEST_IMG.orig" # Test the conversion twice: One test with the old-style -B option and another # one with -o backing_file -for backing_option in "-B $TEST_IMG.base" "-o backing_file=$TEST_IMG.base"; do +for backing_option in "-B " "-o backing_file="; do echo - echo Testing conversion with $backing_option | _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.orig" "$TEST_IMG" + $QEMU_IMG convert -O $IMGFMT $backing_option"$TEST_IMG.base" "$TEST_IMG.orig" "$TEST_IMG" echo "Checking if backing clusters are allocated when they shouldn't" echo diff --git a/tests/qemu-iotests/039 b/tests/qemu-iotests/039 index f85b4ce63f..8bade92a80 100755 --- a/tests/qemu-iotests/039 +++ b/tests/qemu-iotests/039 @@ -54,7 +54,7 @@ echo "== Checking that image is clean on shutdown ==" IMGOPTS="compat=1.1,lazy_refcounts=on" _make_test_img $size -$QEMU_IO -c "write -P 0x5a 0 512" ""$TEST_IMG"" | _filter_qemu_io +$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 diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 356c3756f4..0a4971d437 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -64,9 +64,9 @@ function run_qemu() size=128M _make_test_img $size -cp $TEST_IMG $TEST_IMG.orig -mv $TEST_IMG $TEST_IMG.base -_make_test_img -b $TEST_IMG.base $size +cp "$TEST_IMG" "$TEST_IMG.orig" +mv "$TEST_IMG" "$TEST_IMG.base" +_make_test_img -b "$TEST_IMG.base" $size echo echo === Unknown option === @@ -81,7 +81,7 @@ echo echo === Overriding backing file === echo -echo "info block" | run_qemu -drive file=$TEST_IMG,driver=qcow2,backing.file.filename=$TEST_IMG.orig -nodefaults +echo "info block" | run_qemu -drive file="$TEST_IMG",driver=qcow2,backing.file.filename="$TEST_IMG.orig" -nodefaults echo echo === Enable and disable lazy refcounting on the command line, plus some invalid values === diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 index fa9319da26..e42f9bd5e8 100755 --- a/tests/qemu-iotests/061 +++ b/tests/qemu-iotests/061 @@ -163,7 +163,7 @@ echo "=== Testing zero expansion on backed image ===" echo IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M $QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io -IMGOPTS="compat=1.1,backing_file=$TEST_IMG.base" _make_test_img 64M +IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M $QEMU_IO -c "read -P 0x2a 0 128k" -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG" _check_test_img @@ -174,7 +174,7 @@ echo "=== Testing zero expansion on backed inactive clusters ===" echo IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M $QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io -IMGOPTS="compat=1.1,backing_file=$TEST_IMG.base" _make_test_img 64M +IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M $QEMU_IO -c "write -z 0 64k" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG snapshot -c foo "$TEST_IMG" $QEMU_IO -c "write -P 0x42 0 128k" "$TEST_IMG" | _filter_qemu_io @@ -190,7 +190,7 @@ echo "=== Testing zero expansion on backed image with shared L2 table ===" echo IMGOPTS="compat=1.1" TEST_IMG="$TEST_IMG.base" _make_test_img 64M $QEMU_IO -c "write -P 0x2a 0 128k" "$TEST_IMG.base" | _filter_qemu_io -IMGOPTS="compat=1.1,backing_file=$TEST_IMG.base" _make_test_img 64M +IMGOPTS="compat=1.1" _make_test_img -b "$TEST_IMG.base" 64M $QEMU_IO -c "write -z 0 128k" "$TEST_IMG" | _filter_qemu_io $QEMU_IMG snapshot -c foo "$TEST_IMG" $QEMU_IMG amend -o "compat=0.10" "$TEST_IMG" diff --git a/tests/qemu-iotests/064 b/tests/qemu-iotests/064 index 6789aa6ee4..1c74c31a1a 100755 --- a/tests/qemu-iotests/064 +++ b/tests/qemu-iotests/064 @@ -56,6 +56,17 @@ echo echo "=== Verify pattern 0x00, 66M - 1024M ===" $QEMU_IO -r -c "read -pP 0x00 66M 958M" "$TEST_IMG" | _filter_qemu_io +echo +echo "=== Verify pattern write, 0xc3 99M-157M ===" +$QEMU_IO -c "write -pP 0xc3 99M 58M" "$TEST_IMG" | _filter_qemu_io +# first verify we didn't write where we should not have +$QEMU_IO -c "read -pP 0xa5 0 33M" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "read -pP 0x96 33M 33M" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "read -pP 0x00 66M 33M" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "read -pP 0x00 157MM 867MM" "$TEST_IMG" | _filter_qemu_io +# now verify what we should have actually written +$QEMU_IO -c "read -pP 0xc3 99M 58M" "$TEST_IMG" | _filter_qemu_io + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/064.out b/tests/qemu-iotests/064.out index b9e8e4a873..5346a4e630 100644 --- a/tests/qemu-iotests/064.out +++ b/tests/qemu-iotests/064.out @@ -11,4 +11,18 @@ read 34603008/34603008 bytes at offset 34603008 === Verify pattern 0x00, 66M - 1024M === read 1004535808/1004535808 bytes at offset 69206016 958 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + +=== Verify pattern write, 0xc3 99M-157M === +wrote 60817408/60817408 bytes at offset 103809024 +58 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 34603008/34603008 bytes at offset 0 +33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 34603008/34603008 bytes at offset 34603008 +33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 34603008/34603008 bytes at offset 69206016 +33 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 909115392/909115392 bytes at offset 164626432 +867 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 60817408/60817408 bytes at offset 103809024 +58 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) *** done diff --git a/tests/qemu-iotests/067 b/tests/qemu-iotests/067 index 79dc38bc04..d025192c83 100755 --- a/tests/qemu-iotests/067 +++ b/tests/qemu-iotests/067 @@ -45,7 +45,7 @@ function do_run_qemu() function run_qemu() { - do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp + do_run_qemu "$@" 2>&1 | _filter_testdir | _filter_qmp | sed -e 's/\("actual-size":\s*\)[0-9]\+/\1SIZE/g' } size=128M diff --git a/tests/qemu-iotests/067.out b/tests/qemu-iotests/067.out index 4bb9ff9652..8d271cc41a 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": 139264, "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, "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": 139264, "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, "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": 139264, "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, "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": 139264, "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, "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": 139264, "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, "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 new file mode 100755 index 0000000000..41bf100701 --- /dev/null +++ b/tests/qemu-iotests/070 @@ -0,0 +1,67 @@ +#!/bin/bash +# +# Test VHDX log replay from an image with a journal that needs to be +# replayed +# +# Copyright (C) 2013 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` +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 vhdx +_supported_proto generic +_supported_os Linux + +# With the log replayed, the pattern 0xa5 extends to 0xc025000 +# If the log was not replayed, it would only extend to 0xc000000 +# +# This image is a 10G dynamic image, with 4M block size, and 1 unplayed +# data sector in the log +# +# This image was created with qemu-img, however it was verified using +# Hyper-V to properly replay the logs and give the same post-replay +# image as qemu. +_use_sample_img iotest-dirtylog-10G-4M.vhdx.bz2 + +echo +echo "=== Verify open image read-only fails, due to dirty log ===" +$QEMU_IO -r -c "read -pP 0xa5 0 18M" "$TEST_IMG" 2>&1 | grep -o "Permission denied" + +echo "=== Verify open image replays log ===" +$QEMU_IO -c "read -pP 0xa5 0 18M" "$TEST_IMG" | _filter_qemu_io + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/070.out b/tests/qemu-iotests/070.out new file mode 100644 index 0000000000..9db8ff2650 --- /dev/null +++ b/tests/qemu-iotests/070.out @@ -0,0 +1,8 @@ +QA output created by 070 + +=== Verify open image read-only fails, due to dirty log === +Permission denied +=== Verify open image replays log === +read 18874368/18874368 bytes at offset 0 +18 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +*** done diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common index 2932e14e73..8cde7f11fa 100644 --- a/tests/qemu-iotests/common +++ b/tests/qemu-iotests/common @@ -200,7 +200,6 @@ testlist options -vhdx) IMGFMT=vhdx xpand=false - IMGFMT_GENERIC=false ;; -rbd) diff --git a/tests/qemu-iotests/common.pattern b/tests/qemu-iotests/common.pattern index 00e0f605fd..ddfbca1b76 100644 --- a/tests/qemu-iotests/common.pattern +++ b/tests/qemu-iotests/common.pattern @@ -28,7 +28,7 @@ function do_is_allocated() { } function is_allocated() { - do_is_allocated "$@" | $QEMU_IO $TEST_IMG | _filter_qemu_io + do_is_allocated "$@" | $QEMU_IO "$TEST_IMG" | _filter_qemu_io } function do_io() { @@ -46,18 +46,18 @@ function do_io() { } function io_pattern() { - do_io "$@" | $QEMU_IO $TEST_IMG | _filter_qemu_io + do_io "$@" | $QEMU_IO "$TEST_IMG" | _filter_qemu_io } function io() { local start=$2 local pattern=$(( (start >> 9) % 256 )) - do_io "$@" $pattern | $QEMU_IO $TEST_IMG | _filter_qemu_io + do_io "$@" $pattern | $QEMU_IO "$TEST_IMG" | _filter_qemu_io } function io_zero() { - do_io "$@" 0 | $QEMU_IO $TEST_IMG | _filter_qemu_io + do_io "$@" 0 | $QEMU_IO "$TEST_IMG" | _filter_qemu_io } function io_test() { @@ -117,8 +117,8 @@ function io_test2() { echo === Clusters to be compressed [3] io_pattern writev $((offset + 8 * $cluster_size)) $cluster_size $((9 * $cluster_size)) $num 165 - mv $TEST_IMG $TEST_IMG.orig - $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -c $TEST_IMG.orig $TEST_IMG + mv "$TEST_IMG" "$TEST_IMG.orig" + $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -c "$TEST_IMG.orig" "$TEST_IMG" # Write the used clusters echo === Used clusters [1] diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 4e826040d4..7f6245770a 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -111,6 +111,8 @@ _make_test_img() local image_size=$* local optstr="" local img_name="" + local use_backing=0 + local backing_file="" if [ -n "$TEST_IMG_FILE" ]; then img_name=$TEST_IMG_FILE @@ -123,7 +125,8 @@ _make_test_img() fi if [ "$1" = "-b" ]; then - extra_img_options="$1 $2" + use_backing=1 + backing_file=$2 image_size=$3 fi if [ \( "$IMGFMT" = "qcow2" -o "$IMGFMT" = "qed" \) -a -n "$CLUSTER_SIZE" ]; then @@ -135,7 +138,13 @@ _make_test_img() fi # XXX(hch): have global image options? - $QEMU_IMG create -f $IMGFMT $extra_img_options $img_name $image_size 2>&1 | \ + ( + if [ $use_backing = 1 ]; then + $QEMU_IMG create -f $IMGFMT $extra_img_options -b "$backing_file" "$img_name" $image_size 2>&1 + else + $QEMU_IMG create -f $IMGFMT $extra_img_options "$img_name" $image_size 2>&1 + fi + ) | \ sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ -e "s#$TEST_DIR#TEST_DIR#g" \ -e "s#$IMGFMT#IMGFMT#g" \ @@ -148,7 +157,10 @@ _make_test_img() -e "s# zeroed_grain=\\(on\\|off\\)##g" \ -e "s# subformat='[^']*'##g" \ -e "s# adapter_type='[^']*'##g" \ - -e "s# lazy_refcounts=\\(on\\|off\\)##g" + -e "s# lazy_refcounts=\\(on\\|off\\)##g" \ + -e "s# block_size=[0-9]\\+##g" \ + -e "s# block_state_zero=\\(on\\|off\\)##g" \ + -e "s# log_size=[0-9]\\+##g" # Start an NBD server on the image file, which is what we'll be talking to if [ $IMGPROTO = "nbd" ]; then diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index c57ff35843..b18b241f8d 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -75,3 +75,4 @@ 067 rw auto 068 rw auto 069 rw auto +070 rw auto diff --git a/tests/qemu-iotests/sample_images/iotest-dirtylog-10G-4M.vhdx.bz2 b/tests/qemu-iotests/sample_images/iotest-dirtylog-10G-4M.vhdx.bz2 Binary files differnew file mode 100644 index 0000000000..4b91cfc654 --- /dev/null +++ b/tests/qemu-iotests/sample_images/iotest-dirtylog-10G-4M.vhdx.bz2 |