mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/ehabkost/tags/python-next-pull-request' into staging
Python queue, 2018-10-30 * Makefile rule for running acceptance tests (make check-acceptance) (Cleber Rosa) * Make iotests compatible with Python 3 (Max Reitz) * device-crash-test whitelist update (Thomas Huth) * Misc cleanups (Cleber Rosa) # gpg: Signature made Wed 31 Oct 2018 00:28:39 GMT # gpg: using RSA key 2807936F984DC5A6 # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/python-next-pull-request: scripts/qemu.py: use a more consistent docstring style scripts/decodetree.py: fix reference to attributes Travis support for the acceptance tests Acceptance tests: add make rule for running them Bootstrap Python venv for tests iotests: Unify log outputs between Python 2 and 3 iotests: Modify imports for Python 3 iotests: 'new' module replacement in 169 iotests: Explicitly bequeath FDs in Python iotests: Different iterator behavior in Python 3 iotests: Use // for Python integer division iotests: Use Python byte strings where appropriate iotests: Flush in iotests.py's QemuIoInteractive iotests: Make nbd-fault-injector flush scripts/device-crash-test: Remove devices that are not user_creatable anymore Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -117,6 +117,14 @@ matrix:
|
||||
- env: CONFIG="--target-list=x86_64-softmmu"
|
||||
python:
|
||||
- "3.6"
|
||||
# Acceptance (Functional) tests
|
||||
- env: CONFIG="--python=/usr/bin/python3 --target-list=x86_64-softmmu"
|
||||
TEST_CMD="make AVOCADO_SHOW=app check-acceptance"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- python3-pip
|
||||
- python3.4-venv
|
||||
# Using newer GCC with sanitizers
|
||||
- addons:
|
||||
apt:
|
||||
|
||||
+38
-5
@@ -545,10 +545,39 @@ Tests based on ``avocado_qemu.Test`` can easily:
|
||||
- http://avocado-framework.readthedocs.io/en/latest/api/test/avocado.html#avocado.Test
|
||||
- http://avocado-framework.readthedocs.io/en/latest/api/utils/avocado.utils.html
|
||||
|
||||
Installation
|
||||
------------
|
||||
Running tests
|
||||
-------------
|
||||
|
||||
To install Avocado and its dependencies, run:
|
||||
You can run the acceptance tests simply by executing:
|
||||
|
||||
.. code::
|
||||
|
||||
make check-acceptance
|
||||
|
||||
This involves the automatic creation of Python virtual environment
|
||||
within the build tree (at ``tests/venv``) which will have all the
|
||||
right dependencies, and will save tests results also within the
|
||||
build tree (at ``tests/results``).
|
||||
|
||||
Note: the build environment must be using a Python 3 stack, and have
|
||||
the ``venv`` and ``pip`` packages installed. If necessary, make sure
|
||||
``configure`` is called with ``--python=`` and that those modules are
|
||||
available. On Debian and Ubuntu based systems, depending on the
|
||||
specific version, they may be on packages named ``python3-venv`` and
|
||||
``python3-pip``.
|
||||
|
||||
The scripts installed inside the virtual environment may be used
|
||||
without an "activation". For instance, the Avocado test runner
|
||||
may be invoked by running:
|
||||
|
||||
.. code::
|
||||
|
||||
tests/venv/bin/avocado run $OPTION1 $OPTION2 tests/acceptance/
|
||||
|
||||
Manual Installation
|
||||
-------------------
|
||||
|
||||
To manually install Avocado and its dependencies, run:
|
||||
|
||||
.. code::
|
||||
|
||||
@@ -689,11 +718,15 @@ The exact QEMU binary to be used on QEMUMachine.
|
||||
Uninstalling Avocado
|
||||
--------------------
|
||||
|
||||
If you've followed the installation instructions above, you can easily
|
||||
uninstall Avocado. Start by listing the packages you have installed::
|
||||
If you've followed the manual installation instructions above, you can
|
||||
easily uninstall Avocado. Start by listing the packages you have
|
||||
installed::
|
||||
|
||||
pip list --user
|
||||
|
||||
And remove any package you want with::
|
||||
|
||||
pip uninstall <package_name>
|
||||
|
||||
If you've used ``make check-acceptance``, the Python virtual environment where
|
||||
Avocado is installed will be cleaned up as part of ``make check-clean``.
|
||||
|
||||
@@ -298,7 +298,7 @@ class Field:
|
||||
s = 's'
|
||||
else:
|
||||
s = ''
|
||||
return str(pos) + ':' + s + str(len)
|
||||
return str(self.pos) + ':' + s + str(self.len)
|
||||
|
||||
def str_extract(self):
|
||||
if self.sign:
|
||||
|
||||
@@ -72,21 +72,6 @@ ERROR_WHITELIST = [
|
||||
# devices that don't work out of the box because they require extra options to "-device DEV":
|
||||
# DEVICE | ERROR MESSAGE
|
||||
{'device':'.*-(i386|x86_64)-cpu', 'expected':True}, # CPU socket-id is not set
|
||||
{'device':'ARM,bitband-memory', 'expected':True}, # source-memory property not set
|
||||
{'device':'arm.cortex-a9-global-timer', 'expected':True}, # a9_gtimer_realize: num-cpu must be between 1 and 4
|
||||
{'device':'arm_mptimer', 'expected':True}, # num-cpu must be between 1 and 4
|
||||
{'device':'armv7m', 'expected':True}, # memory property was not set
|
||||
{'device':'aspeed.scu', 'expected':True}, # Unknown silicon revision: 0x0
|
||||
{'device':'aspeed.sdmc', 'expected':True}, # Unknown silicon revision: 0x0
|
||||
{'device':'bcm2835-dma', 'expected':True}, # bcm2835_dma_realize: required dma-mr link not found: Property '.dma-mr' not found
|
||||
{'device':'bcm2835-fb', 'expected':True}, # bcm2835_fb_realize: required vcram-base property not set
|
||||
{'device':'bcm2835-mbox', 'expected':True}, # bcm2835_mbox_realize: required mbox-mr link not found: Property '.mbox-mr' not found
|
||||
{'device':'bcm2835-peripherals', 'expected':True}, # bcm2835_peripherals_realize: required ram link not found: Property '.ram' not found
|
||||
{'device':'bcm2835-property', 'expected':True}, # bcm2835_property_realize: required fb link not found: Property '.fb' not found
|
||||
{'device':'bcm2835_gpio', 'expected':True}, # bcm2835_gpio_realize: required sdhci link not found: Property '.sdbus-sdhci' not found
|
||||
{'device':'bcm2836', 'expected':True}, # bcm2836_realize: required ram link not found: Property '.ram' not found
|
||||
{'device':'cfi.pflash01', 'expected':True}, # attribute "sector-length" not specified or zero.
|
||||
{'device':'cfi.pflash02', 'expected':True}, # attribute "sector-length" not specified or zero.
|
||||
{'device':'icp', 'expected':True}, # icp_realize: required link 'xics' not found: Property '.xics' not found
|
||||
{'device':'ics', 'expected':True}, # ics_base_realize: required link 'xics' not found: Property '.xics' not found
|
||||
# "-device ide-cd" does work on more recent QEMU versions, so it doesn't have expected=True
|
||||
@@ -108,7 +93,6 @@ ERROR_WHITELIST = [
|
||||
{'device':'pc-dimm', 'expected':True}, # 'memdev' property is not set
|
||||
{'device':'pci-bridge', 'expected':True}, # Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0.
|
||||
{'device':'pci-bridge-seat', 'expected':True}, # Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0.
|
||||
{'device':'pxa2xx-dma', 'expected':True}, # channels value invalid
|
||||
{'device':'pxb', 'expected':True}, # Bridge chassis not specified. Each bridge is required to be assigned a unique chassis id > 0.
|
||||
{'device':'scsi-block', 'expected':True}, # drive property not set
|
||||
{'device':'scsi-disk', 'expected':True}, # drive property not set
|
||||
@@ -145,7 +129,6 @@ ERROR_WHITELIST = [
|
||||
{'device':'virtio-input-host-pci', 'expected':True}, # evdev property is required
|
||||
{'device':'xen-pvdevice', 'expected':True}, # Device ID invalid, it must always be supplied
|
||||
{'device':'vhost-vsock-ccw', 'expected':True}, # guest-cid property must be greater than 2
|
||||
{'device':'ALTR.timer', 'expected':True}, # "clock-frequency" property must be provided
|
||||
{'device':'zpci', 'expected':True}, # target must be defined
|
||||
{'device':'pnv-(occ|icp|lpc)', 'expected':True}, # required link 'xics' not found: Property '.xics' not found
|
||||
{'device':'powernv-cpu-.*', 'expected':True}, # pnv_core_realize: required link 'xics' not found: Property '.xics' not found
|
||||
|
||||
+70
-29
@@ -59,9 +59,9 @@ class QEMUMachineAddDeviceError(QEMUMachineError):
|
||||
"""
|
||||
|
||||
class MonitorResponseError(qmp.qmp.QMPError):
|
||||
'''
|
||||
"""
|
||||
Represents erroneous QMP monitor reply
|
||||
'''
|
||||
"""
|
||||
def __init__(self, reply):
|
||||
try:
|
||||
desc = reply["error"]["desc"]
|
||||
@@ -72,14 +72,15 @@ class MonitorResponseError(qmp.qmp.QMPError):
|
||||
|
||||
|
||||
class QEMUMachine(object):
|
||||
'''A QEMU VM
|
||||
"""
|
||||
A QEMU VM
|
||||
|
||||
Use this object as a context manager to ensure the QEMU process terminates::
|
||||
|
||||
with VM(binary) as vm:
|
||||
...
|
||||
# vm is guaranteed to be shut down here
|
||||
'''
|
||||
"""
|
||||
|
||||
def __init__(self, binary, args=None, wrapper=None, name=None,
|
||||
test_dir="/var/tmp", monitor_address=None,
|
||||
@@ -141,18 +142,28 @@ class QEMUMachine(object):
|
||||
self._args.append(args)
|
||||
|
||||
def add_fd(self, fd, fdset, opaque, opts=''):
|
||||
'''Pass a file descriptor to the VM'''
|
||||
"""
|
||||
Pass a file descriptor to the VM
|
||||
"""
|
||||
options = ['fd=%d' % fd,
|
||||
'set=%d' % fdset,
|
||||
'opaque=%s' % opaque]
|
||||
if opts:
|
||||
options.append(opts)
|
||||
|
||||
# This did not exist before 3.4, but since then it is
|
||||
# mandatory for our purpose
|
||||
if hasattr(os, 'set_inheritable'):
|
||||
os.set_inheritable(fd, True)
|
||||
|
||||
self._args.append('-add-fd')
|
||||
self._args.append(','.join(options))
|
||||
return self
|
||||
|
||||
def send_fd_scm(self, fd_file_path):
|
||||
# Exactly one of fd and file_path must be given.
|
||||
# (If it is file_path, the helper will open that file and pass its
|
||||
# own fd)
|
||||
def send_fd_scm(self, fd=None, file_path=None):
|
||||
# In iotest.py, the qmp should always use unix socket.
|
||||
assert self._qmp.is_scm_available()
|
||||
if self._socket_scm_helper is None:
|
||||
@@ -160,12 +171,27 @@ class QEMUMachine(object):
|
||||
if not os.path.exists(self._socket_scm_helper):
|
||||
raise QEMUMachineError("%s does not exist" %
|
||||
self._socket_scm_helper)
|
||||
|
||||
# This did not exist before 3.4, but since then it is
|
||||
# mandatory for our purpose
|
||||
if hasattr(os, 'set_inheritable'):
|
||||
os.set_inheritable(self._qmp.get_sock_fd(), True)
|
||||
if fd is not None:
|
||||
os.set_inheritable(fd, True)
|
||||
|
||||
fd_param = ["%s" % self._socket_scm_helper,
|
||||
"%d" % self._qmp.get_sock_fd(),
|
||||
"%s" % fd_file_path]
|
||||
"%d" % self._qmp.get_sock_fd()]
|
||||
|
||||
if file_path is not None:
|
||||
assert fd is None
|
||||
fd_param.append(file_path)
|
||||
else:
|
||||
assert fd is not None
|
||||
fd_param.append(str(fd))
|
||||
|
||||
devnull = open(os.path.devnull, 'rb')
|
||||
proc = subprocess.Popen(fd_param, stdin=devnull, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
stderr=subprocess.STDOUT, close_fds=False)
|
||||
output = proc.communicate()[0]
|
||||
if output:
|
||||
LOG.debug(output)
|
||||
@@ -174,7 +200,9 @@ class QEMUMachine(object):
|
||||
|
||||
@staticmethod
|
||||
def _remove_if_exists(path):
|
||||
'''Remove file object at path if it exists'''
|
||||
"""
|
||||
Remove file object at path if it exists
|
||||
"""
|
||||
try:
|
||||
os.remove(path)
|
||||
except OSError as exception:
|
||||
@@ -277,7 +305,9 @@ class QEMUMachine(object):
|
||||
raise
|
||||
|
||||
def _launch(self):
|
||||
'''Launch the VM and establish a QMP connection'''
|
||||
"""
|
||||
Launch the VM and establish a QMP connection
|
||||
"""
|
||||
devnull = open(os.path.devnull, 'rb')
|
||||
self._pre_launch()
|
||||
self._qemu_full_args = (self._wrapper + [self._binary] +
|
||||
@@ -286,18 +316,23 @@ class QEMUMachine(object):
|
||||
stdin=devnull,
|
||||
stdout=self._qemu_log_file,
|
||||
stderr=subprocess.STDOUT,
|
||||
shell=False)
|
||||
shell=False,
|
||||
close_fds=False)
|
||||
self._post_launch()
|
||||
|
||||
def wait(self):
|
||||
'''Wait for the VM to power off'''
|
||||
"""
|
||||
Wait for the VM to power off
|
||||
"""
|
||||
self._popen.wait()
|
||||
self._qmp.close()
|
||||
self._load_io_log()
|
||||
self._post_shutdown()
|
||||
|
||||
def shutdown(self):
|
||||
'''Terminate the VM and clean up'''
|
||||
"""
|
||||
Terminate the VM and clean up
|
||||
"""
|
||||
if self.is_running():
|
||||
try:
|
||||
self._qmp.cmd('quit')
|
||||
@@ -321,7 +356,9 @@ class QEMUMachine(object):
|
||||
self._launched = False
|
||||
|
||||
def qmp(self, cmd, conv_keys=True, **args):
|
||||
'''Invoke a QMP command and return the response dict'''
|
||||
"""
|
||||
Invoke a QMP command and return the response dict
|
||||
"""
|
||||
qmp_args = dict()
|
||||
for key, value in args.items():
|
||||
if conv_keys:
|
||||
@@ -332,11 +369,11 @@ class QEMUMachine(object):
|
||||
return self._qmp.cmd(cmd, args=qmp_args)
|
||||
|
||||
def command(self, cmd, conv_keys=True, **args):
|
||||
'''
|
||||
"""
|
||||
Invoke a QMP command.
|
||||
On success return the response dict.
|
||||
On failure raise an exception.
|
||||
'''
|
||||
"""
|
||||
reply = self.qmp(cmd, conv_keys, **args)
|
||||
if reply is None:
|
||||
raise qmp.qmp.QMPError("Monitor is closed")
|
||||
@@ -345,13 +382,17 @@ class QEMUMachine(object):
|
||||
return reply["return"]
|
||||
|
||||
def get_qmp_event(self, wait=False):
|
||||
'''Poll for one queued QMP events and return it'''
|
||||
"""
|
||||
Poll for one queued QMP events and return it
|
||||
"""
|
||||
if len(self._events) > 0:
|
||||
return self._events.pop(0)
|
||||
return self._qmp.pull_event(wait=wait)
|
||||
|
||||
def get_qmp_events(self, wait=False):
|
||||
'''Poll for queued QMP events and return a list of dicts'''
|
||||
"""
|
||||
Poll for queued QMP events and return a list of dicts
|
||||
"""
|
||||
events = self._qmp.get_events(wait=wait)
|
||||
events.extend(self._events)
|
||||
del self._events[:]
|
||||
@@ -359,7 +400,7 @@ class QEMUMachine(object):
|
||||
return events
|
||||
|
||||
def event_wait(self, name, timeout=60.0, match=None):
|
||||
'''
|
||||
"""
|
||||
Wait for specified timeout on named event in QMP; optionally filter
|
||||
results by match.
|
||||
|
||||
@@ -367,7 +408,7 @@ class QEMUMachine(object):
|
||||
branch processing on match's value None
|
||||
{"foo": {"bar": 1}} matches {"foo": None}
|
||||
{"foo": {"bar": 1}} does not matches {"foo": {"baz": None}}
|
||||
'''
|
||||
"""
|
||||
def event_match(event, match=None):
|
||||
if match is None:
|
||||
return True
|
||||
@@ -400,29 +441,29 @@ class QEMUMachine(object):
|
||||
return None
|
||||
|
||||
def get_log(self):
|
||||
'''
|
||||
"""
|
||||
After self.shutdown or failed qemu execution, this returns the output
|
||||
of the qemu process.
|
||||
'''
|
||||
"""
|
||||
return self._iolog
|
||||
|
||||
def add_args(self, *args):
|
||||
'''
|
||||
"""
|
||||
Adds to the list of extra arguments to be given to the QEMU binary
|
||||
'''
|
||||
"""
|
||||
self._args.extend(args)
|
||||
|
||||
def set_machine(self, machine_type):
|
||||
'''
|
||||
"""
|
||||
Sets the machine type
|
||||
|
||||
If set, the machine type will be added to the base arguments
|
||||
of the resulting QEMU command line.
|
||||
'''
|
||||
"""
|
||||
self._machine = machine_type
|
||||
|
||||
def set_console(self, device_type=None):
|
||||
'''
|
||||
"""
|
||||
Sets the device type for a console device
|
||||
|
||||
If set, the console device and a backing character device will
|
||||
@@ -440,7 +481,7 @@ class QEMUMachine(object):
|
||||
@param device_type: the device type, such as "isa-serial"
|
||||
@raises: QEMUMachineAddDeviceError if the device type is not given
|
||||
and can not be determined.
|
||||
'''
|
||||
"""
|
||||
if device_type is None:
|
||||
if self._machine is None:
|
||||
raise QEMUMachineAddDeviceError("Can not add a console device:"
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ class QEMUQtestProtocol(object):
|
||||
|
||||
@param qtest_cmd: qtest command text to be sent
|
||||
"""
|
||||
self._sock.sendall(qtest_cmd + "\n")
|
||||
self._sock.sendall((qtest_cmd + "\n").encode('utf-8'))
|
||||
|
||||
def close(self):
|
||||
self._sock.close()
|
||||
|
||||
@@ -11,7 +11,9 @@ check-help:
|
||||
@echo " $(MAKE) check-qapi-schema Run QAPI schema tests"
|
||||
@echo " $(MAKE) check-block Run block tests"
|
||||
@echo " $(MAKE) check-tcg Run TCG tests"
|
||||
@echo " $(MAKE) check-acceptance Run all acceptance (functional) tests"
|
||||
@echo " $(MAKE) check-report.html Generates an HTML test report"
|
||||
@echo " $(MAKE) check-venv Creates a Python venv for tests"
|
||||
@echo " $(MAKE) check-clean Clean the tests"
|
||||
@echo
|
||||
@echo "Please note that HTML reports do not regenerate if the unit tests"
|
||||
@@ -899,6 +901,46 @@ check-decodetree:
|
||||
./check.sh "$(PYTHON)" "$(SRC_PATH)/scripts/decodetree.py", \
|
||||
TEST, decodetree.py)
|
||||
|
||||
# Python venv for running tests
|
||||
|
||||
.PHONY: check-venv check-acceptance
|
||||
|
||||
TESTS_VENV_DIR=$(BUILD_DIR)/tests/venv
|
||||
TESTS_VENV_REQ=$(SRC_PATH)/tests/requirements.txt
|
||||
TESTS_RESULTS_DIR=$(BUILD_DIR)/tests/results
|
||||
# Controls the output generated by Avocado when running tests.
|
||||
# Any number of command separated loggers are accepted. For more
|
||||
# information please refer to "avocado --help".
|
||||
AVOCADO_SHOW=none
|
||||
|
||||
$(shell $(PYTHON) -c 'import sys; assert sys.version_info >= (3,0)' >/dev/null 2>&1)
|
||||
ifeq ($(.SHELLSTATUS),0)
|
||||
$(TESTS_VENV_DIR): $(TESTS_VENV_REQ)
|
||||
$(call quiet-command, \
|
||||
$(PYTHON) -m venv --system-site-packages $@, \
|
||||
VENV, $@)
|
||||
$(call quiet-command, \
|
||||
$(TESTS_VENV_DIR)/bin/python -m pip -q install -r $(TESTS_VENV_REQ), \
|
||||
PIP, $(TESTS_VENV_REQ))
|
||||
$(call quiet-command, touch $@)
|
||||
else
|
||||
$(TESTS_VENV_DIR):
|
||||
$(error "venv directory for tests requires Python 3")
|
||||
endif
|
||||
|
||||
$(TESTS_RESULTS_DIR):
|
||||
$(call quiet-command, mkdir -p $@, \
|
||||
MKDIR, $@)
|
||||
|
||||
check-venv: $(TESTS_VENV_DIR)
|
||||
|
||||
check-acceptance: check-venv $(TESTS_RESULTS_DIR)
|
||||
$(call quiet-command, \
|
||||
$(TESTS_VENV_DIR)/bin/python -m avocado \
|
||||
--show=$(AVOCADO_SHOW) run --job-results-dir=$(TESTS_RESULTS_DIR) \
|
||||
--failfast=on $(SRC_PATH)/tests/acceptance, \
|
||||
"AVOCADO", "tests/acceptance")
|
||||
|
||||
# Consolidated targets
|
||||
|
||||
.PHONY: check-qapi-schema check-qtest check-unit check check-clean
|
||||
@@ -912,6 +954,7 @@ check-clean:
|
||||
rm -rf $(check-unit-y) tests/*.o $(QEMU_IOTESTS_HELPERS-y)
|
||||
rm -rf $(sort $(foreach target,$(SYSEMU_TARGET_LIST), $(check-qtest-$(target)-y)) $(check-qtest-generic-y))
|
||||
rm -f tests/test-qapi-gen-timestamp
|
||||
rm -rf $(TESTS_VENV_DIR) $(TESTS_RESULTS_DIR)
|
||||
|
||||
clean: check-clean
|
||||
|
||||
|
||||
@@ -521,7 +521,7 @@ new_state = "2"
|
||||
state = "2"
|
||||
event = "%s"
|
||||
new_state = "1"
|
||||
''' % (event, errno, self.STREAM_BUFFER_SIZE / 512, event, event))
|
||||
''' % (event, errno, self.STREAM_BUFFER_SIZE // 512, event, event))
|
||||
file.close()
|
||||
|
||||
class TestEIO(TestErrors):
|
||||
|
||||
@@ -195,7 +195,7 @@ class TestSingleDrive(ImageCommitTestCase):
|
||||
|
||||
self.assert_no_active_block_jobs()
|
||||
result = self.vm.qmp('block-commit', device='drive0', top=mid_img,
|
||||
base=backing_img, speed=(self.image_len / 4))
|
||||
base=backing_img, speed=(self.image_len // 4))
|
||||
self.assert_qmp(result, 'return', {})
|
||||
result = self.vm.qmp('device_del', id='scsi0')
|
||||
self.assert_qmp(result, 'return', {})
|
||||
@@ -225,7 +225,7 @@ class TestSingleDrive(ImageCommitTestCase):
|
||||
|
||||
self.assert_no_active_block_jobs()
|
||||
result = self.vm.qmp('block-commit', device='drive0', top=mid_img,
|
||||
base=backing_img, speed=(self.image_len / 4))
|
||||
base=backing_img, speed=(self.image_len // 4))
|
||||
self.assert_qmp(result, 'return', {})
|
||||
|
||||
result = self.vm.qmp('query-block')
|
||||
|
||||
@@ -404,7 +404,7 @@ new_state = "2"
|
||||
state = "2"
|
||||
event = "%s"
|
||||
new_state = "1"
|
||||
''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event))
|
||||
''' % (event, errno, self.MIRROR_GRANULARITY // 512, event, event))
|
||||
file.close()
|
||||
|
||||
def setUp(self):
|
||||
@@ -569,7 +569,7 @@ new_state = "2"
|
||||
state = "2"
|
||||
event = "%s"
|
||||
new_state = "1"
|
||||
''' % (event, errno, self.MIRROR_GRANULARITY / 512, event, event))
|
||||
''' % (event, errno, self.MIRROR_GRANULARITY // 512, event, event))
|
||||
file.close()
|
||||
|
||||
def setUp(self):
|
||||
|
||||
+14
-10
@@ -26,6 +26,10 @@ import iotests
|
||||
from iotests import qemu_img, qemu_img_verbose, qemu_io
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
if sys.version_info.major == 2:
|
||||
range = xrange
|
||||
|
||||
test_img = os.path.join(iotests.test_dir, 'test.img')
|
||||
|
||||
@@ -52,23 +56,23 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
|
||||
# Write a refcount table
|
||||
fd.seek(off_reftable)
|
||||
|
||||
for i in xrange(0, h.refcount_table_clusters):
|
||||
sector = ''.join(struct.pack('>Q',
|
||||
for i in range(0, h.refcount_table_clusters):
|
||||
sector = b''.join(struct.pack('>Q',
|
||||
off_refblock + i * 64 * 512 + j * 512)
|
||||
for j in xrange(0, 64))
|
||||
for j in range(0, 64))
|
||||
fd.write(sector)
|
||||
|
||||
# Write the refcount blocks
|
||||
assert(fd.tell() == off_refblock)
|
||||
sector = ''.join(struct.pack('>H', 1) for j in xrange(0, 64 * 256))
|
||||
for block in xrange(0, h.refcount_table_clusters):
|
||||
sector = b''.join(struct.pack('>H', 1) for j in range(0, 64 * 256))
|
||||
for block in range(0, h.refcount_table_clusters):
|
||||
fd.write(sector)
|
||||
|
||||
# Write the L1 table
|
||||
assert(fd.tell() == off_l1)
|
||||
assert(off_l2 + 512 * h.l1_size == off_data)
|
||||
table = ''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j)
|
||||
for j in xrange(0, h.l1_size))
|
||||
table = b''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j)
|
||||
for j in range(0, h.l1_size))
|
||||
fd.write(table)
|
||||
|
||||
# Write the L2 tables
|
||||
@@ -79,14 +83,14 @@ class TestRefcountTableGrowth(iotests.QMPTestCase):
|
||||
off = off_data
|
||||
while remaining > 1024 * 512:
|
||||
pytable = list((1 << 63) | off + 512 * j
|
||||
for j in xrange(0, 1024))
|
||||
for j in range(0, 1024))
|
||||
table = struct.pack('>1024Q', *pytable)
|
||||
fd.write(table)
|
||||
remaining = remaining - 1024 * 512
|
||||
off = off + 1024 * 512
|
||||
|
||||
table = ''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
|
||||
for j in xrange(0, remaining / 512))
|
||||
table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j)
|
||||
for j in range(0, remaining // 512))
|
||||
fd.write(table)
|
||||
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ class TestSCMFd(iotests.QMPTestCase):
|
||||
os.remove(image0)
|
||||
|
||||
def _send_fd_by_SCM(self):
|
||||
ret = self.vm.send_fd_scm(image0)
|
||||
ret = self.vm.send_fd_scm(file_path=image0)
|
||||
self.assertEqual(ret, 0, 'Failed to send fd with UNIX SCM')
|
||||
|
||||
def test_add_fd(self):
|
||||
|
||||
@@ -32,7 +32,7 @@ target_img = os.path.join(iotests.test_dir, 'target.img')
|
||||
def img_create(img, fmt=iotests.imgfmt, size='64M', **kwargs):
|
||||
fullname = os.path.join(iotests.test_dir, '%s.%s' % (img, fmt))
|
||||
optargs = []
|
||||
for k,v in kwargs.iteritems():
|
||||
for k,v in kwargs.items():
|
||||
optargs = optargs + ['-o', '%s=%s' % (k,v)]
|
||||
args = ['create', '-f', fmt] + optargs + [fullname, size]
|
||||
iotests.qemu_img(*args)
|
||||
|
||||
@@ -59,7 +59,7 @@ class TestQemuImgInfo(TestImageInfoSpecific):
|
||||
:data.index('')]
|
||||
for field in data:
|
||||
self.assertTrue(re.match('^ {4}[^ ]', field) is not None)
|
||||
data = map(lambda line: line.strip(), data)
|
||||
data = [line.strip() for line in data]
|
||||
self.assertEqual(data, self.human_compare)
|
||||
|
||||
class TestQMP(TestImageInfoSpecific):
|
||||
@@ -80,7 +80,7 @@ class TestQMP(TestImageInfoSpecific):
|
||||
|
||||
def test_qmp(self):
|
||||
result = self.vm.qmp('query-block')['return']
|
||||
drive = filter(lambda drive: drive['device'] == 'drive0', result)[0]
|
||||
drive = next(drive for drive in result if drive['device'] == 'drive0')
|
||||
data = drive['inserted']['image']['format-specific']
|
||||
self.assertEqual(data['type'], iotests.imgfmt)
|
||||
self.assertEqual(data['data'], self.compare)
|
||||
|
||||
@@ -41,6 +41,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/foo
|
||||
|
||||
=== Check disconnect after neg2 ===
|
||||
|
||||
Unable to read from socket: Connection reset by peer
|
||||
Connection closed
|
||||
read failed: Input/output error
|
||||
|
||||
@@ -54,6 +55,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/foo
|
||||
|
||||
=== Check disconnect before request ===
|
||||
|
||||
Unable to read from socket: Connection reset by peer
|
||||
Connection closed
|
||||
read failed: Input/output error
|
||||
|
||||
@@ -116,6 +118,7 @@ can't open device nbd+tcp://127.0.0.1:PORT/
|
||||
|
||||
=== Check disconnect after neg-classic ===
|
||||
|
||||
Unable to read from socket: Connection reset by peer
|
||||
Connection closed
|
||||
read failed: Input/output error
|
||||
|
||||
@@ -161,6 +164,8 @@ can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
|
||||
|
||||
=== Check disconnect after neg2 ===
|
||||
|
||||
Unable to read from socket: Connection reset by peer
|
||||
Connection closed
|
||||
read failed: Input/output error
|
||||
|
||||
=== Check disconnect 8 neg2 ===
|
||||
@@ -173,6 +178,8 @@ can't open device nbd+unix:///foo?socket=TEST_DIR/nbd.sock
|
||||
|
||||
=== Check disconnect before request ===
|
||||
|
||||
Unable to read from socket: Connection reset by peer
|
||||
Connection closed
|
||||
read failed: Input/output error
|
||||
|
||||
=== Check disconnect after request ===
|
||||
@@ -234,6 +241,8 @@ can't open device nbd+unix:///?socket=TEST_DIR/nbd.sock
|
||||
|
||||
=== Check disconnect after neg-classic ===
|
||||
|
||||
Unable to read from socket: Connection reset by peer
|
||||
Connection closed
|
||||
read failed: Input/output error
|
||||
|
||||
*** done
|
||||
|
||||
@@ -69,18 +69,18 @@ class ThrottleTestCase(iotests.QMPTestCase):
|
||||
# in. The throttled requests won't be executed until we
|
||||
# advance the virtual clock.
|
||||
rq_size = 512
|
||||
rd_nr = max(params['bps'] / rq_size / 2,
|
||||
params['bps_rd'] / rq_size,
|
||||
params['iops'] / 2,
|
||||
rd_nr = max(params['bps'] // rq_size // 2,
|
||||
params['bps_rd'] // rq_size,
|
||||
params['iops'] // 2,
|
||||
params['iops_rd'])
|
||||
rd_nr *= seconds * 2
|
||||
rd_nr /= ndrives
|
||||
wr_nr = max(params['bps'] / rq_size / 2,
|
||||
params['bps_wr'] / rq_size,
|
||||
params['iops'] / 2,
|
||||
rd_nr //= ndrives
|
||||
wr_nr = max(params['bps'] // rq_size // 2,
|
||||
params['bps_wr'] // rq_size,
|
||||
params['iops'] // 2,
|
||||
params['iops_wr'])
|
||||
wr_nr *= seconds * 2
|
||||
wr_nr /= ndrives
|
||||
wr_nr //= ndrives
|
||||
|
||||
# Send I/O requests to all drives
|
||||
for i in range(rd_nr):
|
||||
@@ -196,7 +196,7 @@ class ThrottleTestCase(iotests.QMPTestCase):
|
||||
self.configure_throttle(ndrives, settings)
|
||||
|
||||
# Wait for the bucket to empty so we can do bursts
|
||||
wait_ns = nsec_per_sec * burst_length * burst_rate / rate
|
||||
wait_ns = nsec_per_sec * burst_length * burst_rate // rate
|
||||
self.vm.qtest("clock_step %d" % wait_ns)
|
||||
|
||||
# Test I/O at the max burst rate
|
||||
|
||||
@@ -39,7 +39,7 @@ def try_remove(img):
|
||||
def transaction_action(action, **kwargs):
|
||||
return {
|
||||
'type': action,
|
||||
'data': dict((k.replace('_', '-'), v) for k, v in kwargs.iteritems())
|
||||
'data': dict((k.replace('_', '-'), v) for k, v in kwargs.items())
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ class TestIncrementalBackupBase(iotests.QMPTestCase):
|
||||
def img_create(self, img, fmt=iotests.imgfmt, size='64M',
|
||||
parent=None, parentFormat=None, **kwargs):
|
||||
optargs = []
|
||||
for k,v in kwargs.iteritems():
|
||||
for k,v in kwargs.items():
|
||||
optargs = optargs + ['-o', '%s=%s' % (k,v)]
|
||||
args = ['create', '-f', fmt] + optargs + [img, size]
|
||||
if parent:
|
||||
|
||||
@@ -24,7 +24,7 @@ import os
|
||||
|
||||
interval_length = 10
|
||||
nsec_per_sec = 1000000000
|
||||
op_latency = nsec_per_sec / 1000 # See qtest_latency_ns in accounting.c
|
||||
op_latency = nsec_per_sec // 1000 # See qtest_latency_ns in accounting.c
|
||||
bad_sector = 8192
|
||||
bad_offset = bad_sector * 512
|
||||
blkdebug_file = os.path.join(iotests.test_dir, 'blkdebug.conf')
|
||||
|
||||
@@ -51,7 +51,7 @@ class TestBlockdevDel(iotests.QMPTestCase):
|
||||
# Check whether a BlockDriverState exists
|
||||
def checkBlockDriverState(self, node, must_exist = True):
|
||||
result = self.vm.qmp('query-named-block-nodes')
|
||||
nodes = filter(lambda x: x['node-name'] == node, result['return'])
|
||||
nodes = [x for x in result['return'] if x['node-name'] == node]
|
||||
self.assertLessEqual(len(nodes), 1)
|
||||
self.assertEqual(must_exist, len(nodes) == 1)
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ class BuiltinNBD(NBDBlockdevAddBase):
|
||||
sockfd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
sockfd.connect(unix_socket)
|
||||
|
||||
result = self.vm.send_fd_scm(str(sockfd.fileno()))
|
||||
result = self.vm.send_fd_scm(fd=sockfd.fileno())
|
||||
self.assertEqual(result, 0, 'Failed to send socket FD')
|
||||
|
||||
result = self.vm.qmp('getfd', fdname='nbd-fifo')
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user