diff options
Diffstat (limited to 'tests/qemu-iotests')
-rwxr-xr-x | tests/qemu-iotests/030 | 2 | ||||
-rwxr-xr-x | tests/qemu-iotests/125 | 44 | ||||
-rw-r--r-- | tests/qemu-iotests/125.out | 28 | ||||
-rwxr-xr-x | tests/qemu-iotests/194 | 4 | ||||
-rwxr-xr-x | tests/qemu-iotests/208 | 2 | ||||
-rwxr-xr-x | tests/qemu-iotests/222 | 2 | ||||
-rwxr-xr-x | tests/qemu-iotests/251 | 7 | ||||
-rwxr-xr-x | tests/qemu-iotests/257 | 10 | ||||
-rwxr-xr-x | tests/qemu-iotests/305 | 74 | ||||
-rw-r--r-- | tests/qemu-iotests/305.out | 16 | ||||
-rw-r--r-- | tests/qemu-iotests/group | 1 | ||||
-rw-r--r-- | tests/qemu-iotests/iotests.py | 53 |
12 files changed, 186 insertions, 57 deletions
diff --git a/tests/qemu-iotests/030 b/tests/qemu-iotests/030 index 31c028306b..dcb4b5d6a6 100755 --- a/tests/qemu-iotests/030 +++ b/tests/qemu-iotests/030 @@ -21,6 +21,7 @@ import time import os import iotests +import unittest from iotests import qemu_img, qemu_io backing_img = os.path.join(iotests.test_dir, 'backing.img') @@ -228,6 +229,7 @@ class TestParallelOps(iotests.QMPTestCase): # Test that it's possible to run several block-stream operations # in parallel in the same snapshot chain + @unittest.skipIf(os.environ.get('QEMU_CHECK_BLOCK_AUTO'), 'disabled in CI') def test_stream_parallel(self): self.assert_no_active_block_jobs() diff --git a/tests/qemu-iotests/125 b/tests/qemu-iotests/125 index 7cb1c19730..5720e86dce 100755 --- a/tests/qemu-iotests/125 +++ b/tests/qemu-iotests/125 @@ -43,6 +43,10 @@ get_image_size_on_host() _supported_fmt qcow2 _supported_proto file +# Growing a file with a backing file (without preallocation=full or +# =falloc) requires zeroing the newly added area, which is impossible +# to do quickly for v2 images, and hence is unsupported. +_unsupported_imgopts 'compat=0.10' if [ -z "$TEST_IMG_FILE" ]; then TEST_IMG_FILE=$TEST_IMG @@ -168,24 +172,28 @@ done $QEMU_IMG create -f raw "$TEST_IMG.base" 128k | _filter_img_create $QEMU_IO -c 'write -q -P 1 0 128k' -f raw "$TEST_IMG.base" for orig_size in 31k 33k; do - echo "--- Resizing image from $orig_size to 96k ---" - _make_test_img -F raw -b "$TEST_IMG.base" -o cluster_size=64k "$orig_size" - $QEMU_IMG resize -f "$IMGFMT" --preallocation=full "$TEST_IMG" 96k - # The first part of the image should contain data from the backing file - $QEMU_IO -c "read -q -P 1 0 ${orig_size}" "$TEST_IMG" - # The resized part of the image should contain zeroes - $QEMU_IO -c "read -q -P 0 ${orig_size} 63k" "$TEST_IMG" - # If the image does not have an external data file we can also verify its - # actual size. The resized image should have 7 clusters: - # header, L1 table, L2 table, refcount table, refcount block, 2 data clusters - if ! _get_data_file "$TEST_IMG" > /dev/null; then - expected_file_length=$((65536 * 7)) - file_length=$(stat -c '%s' "$TEST_IMG_FILE") - if [ "$file_length" != "$expected_file_length" ]; then - echo "ERROR: file length $file_length (expected $expected_file_length)" - fi - fi - echo + for dst_size in 96k 128k; do + for prealloc in metadata full; do + echo "--- Resizing image from $orig_size to $dst_size (preallocation=$prealloc) ---" + _make_test_img -F raw -b "$TEST_IMG.base" -o cluster_size=64k "$orig_size" + $QEMU_IMG resize -f "$IMGFMT" --preallocation="$prealloc" "$TEST_IMG" "$dst_size" + # The first part of the image should contain data from the backing file + $QEMU_IO -c "read -q -P 1 0 ${orig_size}" "$TEST_IMG" + # The resized part of the image should contain zeroes + $QEMU_IO -c "read -q -P 0 ${orig_size} 63k" "$TEST_IMG" + # If the image does not have an external data file we can also verify its + # actual size. The resized image should have 7 clusters: + # header, L1 table, L2 table, refcount table, refcount block, 2 data clusters + if ! _get_data_file "$TEST_IMG" > /dev/null; then + expected_file_length=$((65536 * 7)) + file_length=$(stat -c '%s' "$TEST_IMG_FILE") + if [ "$file_length" != "$expected_file_length" ]; then + echo "ERROR: file length $file_length (expected $expected_file_length)" + fi + fi + echo + done + done done # success, all done diff --git a/tests/qemu-iotests/125.out b/tests/qemu-iotests/125.out index 7f76f7af20..63a6e9e8a9 100644 --- a/tests/qemu-iotests/125.out +++ b/tests/qemu-iotests/125.out @@ -768,11 +768,35 @@ wrote 81920/81920 bytes at offset 2048000 80 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) Formatting 'TEST_DIR/t.IMGFMT.base', fmt=raw size=131072 ---- Resizing image from 31k to 96k --- +--- Resizing image from 31k to 96k (preallocation=metadata) --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw Image resized. ---- Resizing image from 33k to 96k --- +--- Resizing image from 31k to 96k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 31k to 128k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 31k to 128k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=31744 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 96k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 96k (preallocation=full) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 128k (preallocation=metadata) --- +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw +Image resized. + +--- Resizing image from 33k to 128k (preallocation=full) --- Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33792 backing_file=TEST_DIR/t.IMGFMT.base backing_fmt=raw Image resized. diff --git a/tests/qemu-iotests/194 b/tests/qemu-iotests/194 index da7c4265ec..7a4863ab18 100755 --- a/tests/qemu-iotests/194 +++ b/tests/qemu-iotests/194 @@ -26,8 +26,8 @@ iotests.script_initialize(supported_fmts=['qcow2', 'qed', 'raw'], with iotests.FilePath('source.img') as source_img_path, \ iotests.FilePath('dest.img') as dest_img_path, \ - iotests.FilePaths(['migration.sock', 'nbd.sock'], iotests.sock_dir) as \ - [migration_sock_path, nbd_sock_path], \ + iotests.FilePath('migration.sock', 'nbd.sock', base_dir=iotests.sock_dir) \ + as (migration_sock_path, nbd_sock_path), \ iotests.VM('source') as source_vm, \ iotests.VM('dest') as dest_vm: diff --git a/tests/qemu-iotests/208 b/tests/qemu-iotests/208 index 6cb642f821..54aa4be273 100755 --- a/tests/qemu-iotests/208 +++ b/tests/qemu-iotests/208 @@ -26,7 +26,7 @@ iotests.script_initialize(supported_fmts=['generic']) with iotests.FilePath('disk.img') as disk_img_path, \ iotests.FilePath('disk-snapshot.img') as disk_snapshot_img_path, \ - iotests.FilePath('nbd.sock', iotests.sock_dir) as nbd_sock_path, \ + iotests.FilePath('nbd.sock', base_dir=iotests.sock_dir) as nbd_sock_path, \ iotests.VM() as vm: img_size = '10M' diff --git a/tests/qemu-iotests/222 b/tests/qemu-iotests/222 index 6602f6b4ba..14d67c875b 100755 --- a/tests/qemu-iotests/222 +++ b/tests/qemu-iotests/222 @@ -49,7 +49,7 @@ remainder = [("0xd5", "0x108000", "32k"), # Right-end of partial-left [1] with iotests.FilePath('base.img') as base_img_path, \ iotests.FilePath('fleece.img') as fleece_img_path, \ - iotests.FilePath('nbd.sock', iotests.sock_dir) as nbd_sock_path, \ + iotests.FilePath('nbd.sock', base_dir=iotests.sock_dir) as nbd_sock_path, \ iotests.VM() as vm: log('--- Setting up images ---') diff --git a/tests/qemu-iotests/251 b/tests/qemu-iotests/251 index 7918ba3559..294773bdc1 100755 --- a/tests/qemu-iotests/251 +++ b/tests/qemu-iotests/251 @@ -46,8 +46,11 @@ if [ "$IMGOPTSSYNTAX" = "true" ]; then # We use json:{} filenames here, so we cannot work with additional options. _unsupported_fmt $IMGFMT else - # With VDI, the output is ordered differently. Just disable it. - _unsupported_fmt vdi + # - With VDI, the output is ordered differently. Just disable it. + # - VHDX has large clusters; because qemu-img convert tries to + # align the requests to the cluster size, the output is ordered + # differently, so disable it, too. + _unsupported_fmt vdi vhdx fi diff --git a/tests/qemu-iotests/257 b/tests/qemu-iotests/257 index e1e6077219..c80e06ae28 100755 --- a/tests/qemu-iotests/257 +++ b/tests/qemu-iotests/257 @@ -275,10 +275,9 @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None): an incomplete backup. Testing limitations prevent testing competing writes. """ - with iotests.FilePaths(['img', 'bsync1', 'bsync2', - 'fbackup0', 'fbackup1', 'fbackup2']) as \ - (img_path, bsync1, bsync2, - fbackup0, fbackup1, fbackup2), \ + with iotests.FilePath( + 'img', 'bsync1', 'bsync2', 'fbackup0', 'fbackup1', 'fbackup2') as \ + (img_path, bsync1, bsync2, fbackup0, fbackup1, fbackup2), \ iotests.VM() as vm: mode = "Mode {:s}; Bitmap Sync {:s}".format(msync_mode, bsync_mode) @@ -441,8 +440,7 @@ def test_backup_api(): """ Test malformed and prohibited invocations of the backup API. """ - with iotests.FilePaths(['img', 'bsync1']) as \ - (img_path, backup_path), \ + with iotests.FilePath('img', 'bsync1') as (img_path, backup_path), \ iotests.VM() as vm: log("\n=== API failure tests ===\n") diff --git a/tests/qemu-iotests/305 b/tests/qemu-iotests/305 new file mode 100755 index 0000000000..768818af4a --- /dev/null +++ b/tests/qemu-iotests/305 @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# +# Test the handling of errors in write requests with multiple allocations +# +# Copyright (C) 2020 Igalia, S.L. +# Author: Alberto Garcia <berto@igalia.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +# creator +owner=berto@igalia.com + +seq=`basename $0` +echo "QA output created by $seq" + +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 +_unsupported_imgopts cluster_size refcount_bits extended_l2 compat=0.10 data_file + +echo '### Create the image' +_make_test_img -o refcount_bits=64,cluster_size=1k 1M + +# The reference counts of the clusters for the first 123k of this +# write request are stored in the first refcount block. The last +# cluster (guest offset 123k) is referenced in the second refcount +# block. +echo '### Fill the first refcount block and one data cluster from the second' +$QEMU_IO -c 'write 0 124k' "$TEST_IMG" | _filter_qemu_io + +echo '### Discard two of the last data clusters, leave one in the middle' +$QEMU_IO -c 'discard 121k 1k' "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c 'discard 123k 1k' "$TEST_IMG" | _filter_qemu_io + +echo '### Corrupt the offset of the second refcount block' +refcount_table_offset=$(peek_file_be "$TEST_IMG" 48 8) +poke_file "$TEST_IMG" $(($refcount_table_offset+14)) "\x06" + +# This tries to allocate the two clusters discarded earlier (guest +# offsets 121k and 123k). Their reference counts are in the first and +# second refcount blocks respectively, but only the first one can be +# allocated correctly because the second entry of the refcount table +# is corrupted. +echo '### Try to allocate the discarded clusters again' +$QEMU_IO -c 'write 121k 3k' "$TEST_IMG" | _filter_qemu_io + +# success, all done +echo "*** done" +rm -f $seq.full +status=0 diff --git a/tests/qemu-iotests/305.out b/tests/qemu-iotests/305.out new file mode 100644 index 0000000000..538019e726 --- /dev/null +++ b/tests/qemu-iotests/305.out @@ -0,0 +1,16 @@ +QA output created by 305 +### Create the image +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 +### Fill the first refcount block and one data cluster from the second +wrote 126976/126976 bytes at offset 0 +124 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +### Discard two of the last data clusters, leave one in the middle +discard 1024/1024 bytes at offset 123904 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +discard 1024/1024 bytes at offset 125952 +1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +### Corrupt the offset of the second refcount block +### Try to allocate the discarded clusters again +qcow2: Marking image as corrupt: Refblock offset 0x20600 unaligned (reftable index: 0x1); further corruption events will be suppressed +write failed: Input/output error +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 5cad015231..ff59cfd2d4 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -313,3 +313,4 @@ 302 quick 303 rw quick 304 rw quick +305 rw quick diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index 64ccaf9061..91e4a57126 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -448,42 +448,45 @@ class Timeout: def file_pattern(name): return "{0}-{1}".format(os.getpid(), name) -class FilePaths: +class FilePath: """ - FilePaths is an auto-generated filename that cleans itself up. + Context manager generating multiple file names. The generated files are + removed when exiting the context. - Use this context manager to generate filenames and ensure that the file - gets deleted:: + Example usage: + + with FilePath('a.img', 'b.img') as (img_a, img_b): + # Use img_a and img_b here... + + # a.img and b.img are automatically removed here. + + By default images are created in iotests.test_dir. To create sockets use + iotests.sock_dir: + + with FilePath('a.sock', base_dir=iotests.sock_dir) as sock: + + For convenience, calling with one argument yields a single file instead of + a tuple with one item. - with FilePaths(['test.img']) as img_path: - qemu_img('create', img_path, '1G') - # migration_sock_path is automatically deleted """ - def __init__(self, names, base_dir=test_dir): - self.paths = [] - for name in names: - self.paths.append(os.path.join(base_dir, file_pattern(name))) + def __init__(self, *names, base_dir=test_dir): + self.paths = [os.path.join(base_dir, file_pattern(name)) + for name in names] def __enter__(self): - return self.paths + if len(self.paths) == 1: + return self.paths[0] + else: + return self.paths def __exit__(self, exc_type, exc_val, exc_tb): - try: - for path in self.paths: + for path in self.paths: + try: os.remove(path) - except OSError: - pass + except OSError: + pass return False -class FilePath(FilePaths): - """ - FilePath is a specialization of FilePaths that takes a single filename. - """ - def __init__(self, name, base_dir=test_dir): - super(FilePath, self).__init__([name], base_dir) - - def __enter__(self): - return self.paths[0] def file_path_remover(): for path in reversed(file_path_remover.paths): |