Skip to content

Commit

Permalink
iotests: rebase qemu_io() on top of qemu_tool()
Browse files Browse the repository at this point in the history
Rework qemu_io() to be analogous to qemu_img(); a function that requires
a return code of zero by default unless disabled explicitly.

Tests that use qemu_io():
030 040 041 044 055 056 093 124 129 132 136 148 149 151 152 163 165 205
209 219 236 245 248 254 255 257 260 264 280 298 300 302 304
image-fleecing migrate-bitmaps-postcopy-test migrate-bitmaps-test
migrate-during-backup migration-permissions

Test that use qemu_io_log():
242 245 255 274 303 307 nbd-reconnect-on-open

Copy-pastables for testing/verification:

./check -qcow2 030 040 041 044 055 056 124 129 132 151 152 163 165 209 \
               219 236 242 245 248 254 255 257 260 264 274 \
               280 298 300 302 303 304 307 image-fleecing \
               migrate-bitmaps-postcopy-test migrate-bitmaps-test \
               migrate-during-backup nbd-reconnect-on-open
./check -raw 093 136 148 migration-permissions
./check -nbd 205

# ./configure configure --disable-gnutls --enable-gcrypt
# this ALSO requires passwordless sudo.
./check -luks 149

# Just the tests that were edited in this commit:
./check -qcow2 030 040 242 245
./check -raw migration-permissions
./check -nbd 205
./check -luks 149

Signed-off-by: John Snow <[email protected]>
Message-Id: <[email protected]>
Reviewed-by: Eric Blake <[email protected]>
Signed-off-by: Hanna Reitz <[email protected]>
  • Loading branch information
jnsnow authored and XanClic committed Apr 25, 2022
1 parent b2d68a8 commit 6dede6a
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 54 deletions.
85 changes: 49 additions & 36 deletions tests/qemu-iotests/030
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,18 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
self.vm.shutdown()

self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
'image file map does not match backing file after streaming')
self.assertEqual(
qemu_io('-f', 'raw', '-c', 'map', backing_img).stdout,
qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img).stdout,
'image file map does not match backing file after streaming')

def test_stream_intermediate(self):
self.assert_no_active_block_jobs()

self.assertNotEqual(qemu_io('-f', 'raw', '-rU', '-c', 'map', backing_img),
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', mid_img),
'image file map matches backing file before streaming')
self.assertNotEqual(
qemu_io('-f', 'raw', '-rU', '-c', 'map', backing_img).stdout,
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', mid_img).stdout,
'image file map matches backing file before streaming')

result = self.vm.qmp('block-stream', device='mid', job_id='stream-mid')
self.assert_qmp(result, 'return', {})
Expand All @@ -83,9 +85,10 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
self.vm.shutdown()

self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img),
'image file map does not match backing file after streaming')
self.assertEqual(
qemu_io('-f', 'raw', '-c', 'map', backing_img).stdout,
qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img).stdout,
'image file map does not match backing file after streaming')

def test_stream_pause(self):
self.assert_no_active_block_jobs()
Expand Down Expand Up @@ -113,15 +116,17 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
self.vm.shutdown()

self.assertEqual(qemu_io('-f', 'raw', '-c', 'map', backing_img),
qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
'image file map does not match backing file after streaming')
self.assertEqual(
qemu_io('-f', 'raw', '-c', 'map', backing_img).stdout,
qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img).stdout,
'image file map does not match backing file after streaming')

def test_stream_no_op(self):
self.assert_no_active_block_jobs()

# The image map is empty before the operation
empty_map = qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', test_img)
empty_map = qemu_io(
'-f', iotests.imgfmt, '-rU', '-c', 'map', test_img).stdout

# This is a no-op: no data should ever be copied from the base image
result = self.vm.qmp('block-stream', device='drive0', base=mid_img)
Expand All @@ -132,8 +137,9 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
self.vm.shutdown()

self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
empty_map, 'image file map changed after a no-op')
self.assertEqual(
qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img).stdout,
empty_map, 'image file map changed after a no-op')

def test_stream_partial(self):
self.assert_no_active_block_jobs()
Expand All @@ -146,9 +152,10 @@ class TestSingleDrive(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
self.vm.shutdown()

self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img),
qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img),
'image file map does not match backing file after streaming')
self.assertEqual(
qemu_io('-f', iotests.imgfmt, '-c', 'map', mid_img).stdout,
qemu_io('-f', iotests.imgfmt, '-c', 'map', test_img).stdout,
'image file map does not match backing file after streaming')

def test_device_not_found(self):
result = self.vm.qmp('block-stream', device='nonexistent')
Expand Down Expand Up @@ -236,9 +243,10 @@ class TestParallelOps(iotests.QMPTestCase):

# Check that the maps don't match before the streaming operations
for i in range(2, self.num_imgs, 2):
self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i]),
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i-1]),
'image file map matches backing file before streaming')
self.assertNotEqual(
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i]).stdout,
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[i-1]).stdout,
'image file map matches backing file before streaming')

# Create all streaming jobs
pending_jobs = []
Expand Down Expand Up @@ -278,9 +286,10 @@ class TestParallelOps(iotests.QMPTestCase):

# Check that all maps match now
for i in range(2, self.num_imgs, 2):
self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i]),
qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i-1]),
'image file map does not match backing file after streaming')
self.assertEqual(
qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i]).stdout,
qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[i-1]).stdout,
'image file map does not match backing file after streaming')

# Test that it's not possible to perform two block-stream
# operations if there are nodes involved in both.
Expand Down Expand Up @@ -514,9 +523,10 @@ class TestParallelOps(iotests.QMPTestCase):
def test_stream_base_node_name(self):
self.assert_no_active_block_jobs()

self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[4]),
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[3]),
'image file map matches backing file before streaming')
self.assertNotEqual(
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[4]).stdout,
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.imgs[3]).stdout,
'image file map matches backing file before streaming')

# Error: the base node does not exist
result = self.vm.qmp('block-stream', device='node4', base_node='none', job_id='stream')
Expand Down Expand Up @@ -547,9 +557,10 @@ class TestParallelOps(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
self.vm.shutdown()

self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[4]),
qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[3]),
'image file map matches backing file after streaming')
self.assertEqual(
qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[4]).stdout,
qemu_io('-f', iotests.imgfmt, '-c', 'map', self.imgs[3]).stdout,
'image file map matches backing file after streaming')

class TestQuorum(iotests.QMPTestCase):
num_children = 3
Expand Down Expand Up @@ -588,9 +599,10 @@ class TestQuorum(iotests.QMPTestCase):
os.remove(img)

def test_stream_quorum(self):
self.assertNotEqual(qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.children[0]),
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.backing[0]),
'image file map matches backing file before streaming')
self.assertNotEqual(
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.children[0]).stdout,
qemu_io('-f', iotests.imgfmt, '-rU', '-c', 'map', self.backing[0]).stdout,
'image file map matches backing file before streaming')

self.assert_no_active_block_jobs()

Expand All @@ -602,9 +614,10 @@ class TestQuorum(iotests.QMPTestCase):
self.assert_no_active_block_jobs()
self.vm.shutdown()

self.assertEqual(qemu_io('-f', iotests.imgfmt, '-c', 'map', self.children[0]),
qemu_io('-f', iotests.imgfmt, '-c', 'map', self.backing[0]),
'image file map does not match backing file after streaming')
self.assertEqual(
qemu_io('-f', iotests.imgfmt, '-c', 'map', self.children[0]).stdout,
qemu_io('-f', iotests.imgfmt, '-c', 'map', self.backing[0]).stdout,
'image file map does not match backing file after streaming')

class TestSmallerBackingFile(iotests.QMPTestCase):
backing_len = 1 * 1024 * 1024 # MB
Expand Down
6 changes: 4 additions & 2 deletions tests/qemu-iotests/149
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ def qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False):
args = ["-c", "write -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
args.extend(qemu_io_image_args(config, dev))
iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
iotests.log(check_cipher_support(config, iotests.qemu_io(*args)),
output = iotests.qemu_io(*args, check=False).stdout
iotests.log(check_cipher_support(config, output),
filters=[iotests.filter_test_dir, iotests.filter_qemu_io])


Expand All @@ -307,7 +308,8 @@ def qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False):
args = ["-c", "read -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)]
args.extend(qemu_io_image_args(config, dev))
iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir])
iotests.log(check_cipher_support(config, iotests.qemu_io(*args)),
output = iotests.qemu_io(*args, check=False).stdout
iotests.log(check_cipher_support(config, output),
filters=[iotests.filter_test_dir, iotests.filter_qemu_io])


Expand Down
4 changes: 2 additions & 2 deletions tests/qemu-iotests/205
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ class TestNbdServerRemove(iotests.QMPTestCase):

def do_test_connect_after_remove(self, mode=None):
args = ('-r', '-f', 'raw', '-c', 'read 0 512', nbd_uri)
self.assertReadOk(qemu_io(*args))
self.assertReadOk(qemu_io(*args).stdout)

result = self.remove_export('exp', mode)
self.assert_qmp(result, 'return', {})

self.assertExportNotFound('exp')
self.assertConnectFailed(qemu_io(*args))
self.assertConnectFailed(qemu_io(*args, check=False).stdout)

def test_connect_after_remove_default(self):
self.do_test_connect_after_remove()
Expand Down
17 changes: 11 additions & 6 deletions tests/qemu-iotests/245
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

import copy
import json
import os
import re
from subprocess import CalledProcessError

import iotests
import copy
import json
from iotests import qemu_img, qemu_io

hd_path = [
Expand Down Expand Up @@ -216,11 +218,14 @@ class TestBlockdevReopen(iotests.QMPTestCase):

# Reopen an image several times changing some of its options
def test_reopen(self):
# Check whether the filesystem supports O_DIRECT
if 'O_DIRECT' in qemu_io('-f', 'raw', '-t', 'none', '-c', 'quit', hd_path[0]):
supports_direct = False
else:
try:
qemu_io('-f', 'raw', '-t', 'none', '-c', 'quit', hd_path[0])
supports_direct = True
except CalledProcessError as exc:
if 'O_DIRECT' in exc.stdout:
supports_direct = False
else:
raise

# Open the hd1 image passing all backing options
opts = hd_opts(1)
Expand Down
19 changes: 13 additions & 6 deletions tests/qemu-iotests/iotests.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,16 +353,23 @@ def qemu_io_wrap_args(args: Sequence[str]) -> List[str]:
def qemu_io_popen(*args):
return qemu_tool_popen(qemu_io_wrap_args(args))

def qemu_io(*args):
'''Run qemu-io and return the stdout data'''
return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))[0]
def qemu_io(*args: str, check: bool = True, combine_stdio: bool = True
) -> 'subprocess.CompletedProcess[str]':
"""
Run QEMU_IO_PROG and return the status code and console output.
This function always prepends either QEMU_IO_OPTIONS or
QEMU_IO_OPTIONS_NO_FMT.
"""
return qemu_tool(*qemu_io_wrap_args(args),
check=check, combine_stdio=combine_stdio)

def qemu_io_pipe_and_status(*args):
return qemu_tool_pipe_and_status('qemu-io', qemu_io_wrap_args(args))

def qemu_io_log(*args):
result = qemu_io(*args)
log(result, filters=[filter_testfiles, filter_qemu_io])
def qemu_io_log(*args: str) -> 'subprocess.CompletedProcess[str]':
result = qemu_io(*args, check=False)
log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
return result

def qemu_io_silent(*args):
Expand Down
4 changes: 2 additions & 2 deletions tests/qemu-iotests/tests/migration-permissions
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class TestMigrationPermissions(iotests.QMPTestCase):
def test_post_migration_permissions(self):
# Try to access the image R/W, which should fail because virtio-blk
# has not been configured with share-rw=on
log = qemu_io('-f', imgfmt, '-c', 'quit', test_img)
log = qemu_io('-f', imgfmt, '-c', 'quit', test_img, check=False).stdout
if not log.strip():
print('ERROR (pre-migration): qemu-io should not be able to '
'access this image, but it reported no error')
Expand All @@ -84,7 +84,7 @@ class TestMigrationPermissions(iotests.QMPTestCase):

# Try the same qemu-io access again, verifying that the WRITE
# permission remains unshared
log = qemu_io('-f', imgfmt, '-c', 'quit', test_img)
log = qemu_io('-f', imgfmt, '-c', 'quit', test_img, check=False).stdout
if not log.strip():
print('ERROR (post-migration): qemu-io should not be able to '
'access this image, but it reported no error')
Expand Down

0 comments on commit 6dede6a

Please sign in to comment.