* Fix spurious EOFError messages from the device-crash-test script

* Fix various issues in the functional tests that pylint complained about
 * Improve logging information in the functional tests
 * Fix issue in the s390x clock-comparator code
 * Use address generation for register branch targets on s390x
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCgAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmkIincRHHRodXRoQHJl
 ZGhhdC5jb20ACgkQLtnXdP5wLbUpBg/+KQsh+JNxymwft6ohIiyUqP1vNFYbWMty
 MPRLhInAfT55Hkf6wBX0+WbhqePXvVcThjahh8+2ZlX7/9RVKA5xYn2zLe+tZc8P
 YayVfw0ferJkDoY5UjtQS2RxSpKvs+DaSEpnKzCXA5T5ytth70wM4doQ5h65qz45
 31dLyBhkYLATF00otT62iKzcudpZosxdkC1nPd5FZDM5nXjzeA8CfdsWTW/wa7Kq
 OuMM9a9f7jp3i4OCsyOaPoHhZisP+RK/26m+cMFk2JR41anK4SZ5neunFYre5blg
 W1JkVI+JSLunPfNpKqAKPMPiJ4mKu0vxTeFsY6NMzeRINnr4ctoJf2zED1eMk+R5
 qEJWZfcjXAfMHF0VGvmMHbISCygJXBUMjK0I58N2hJbQPinGiQvQMM8M8S+S3bUm
 0bQxYJPB9ipIz2N3j/xcgQV60df7ut9qp1buVC9XyRiozkUadjFJBCFtB9+Fum+6
 MmXwW94LZbKBYiB7gtEjnLdaqCyua5pnFqQG3BbWgpEpXbNlNVTw9cajKhqTD+H+
 R63wPSojo0jc2idmdJCVeUxxQFW/tpWdBXQ0fDRAqIkTTZhF4e+vM82aPd61jpDO
 M4gFsddTXNDhElAw14/RK+wtIZQHliaSQSxRrzpb8n0tKR+41XvBKIsqYBQUDN3o
 7xe3j9SzpU4=
 =fyHW
 -----END PGP SIGNATURE-----

Merge tag 'pull-request-2025-11-03' of https://gitlab.com/thuth/qemu into staging

* Fix spurious EOFError messages from the device-crash-test script
* Fix various issues in the functional tests that pylint complained about
* Improve logging information in the functional tests
* Fix issue in the s390x clock-comparator code
* Use address generation for register branch targets on s390x

# -----BEGIN PGP SIGNATURE-----
#
# iQJFBAABCgAvFiEEJ7iIR+7gJQEY8+q5LtnXdP5wLbUFAmkIincRHHRodXRoQHJl
# ZGhhdC5jb20ACgkQLtnXdP5wLbUpBg/+KQsh+JNxymwft6ohIiyUqP1vNFYbWMty
# MPRLhInAfT55Hkf6wBX0+WbhqePXvVcThjahh8+2ZlX7/9RVKA5xYn2zLe+tZc8P
# YayVfw0ferJkDoY5UjtQS2RxSpKvs+DaSEpnKzCXA5T5ytth70wM4doQ5h65qz45
# 31dLyBhkYLATF00otT62iKzcudpZosxdkC1nPd5FZDM5nXjzeA8CfdsWTW/wa7Kq
# OuMM9a9f7jp3i4OCsyOaPoHhZisP+RK/26m+cMFk2JR41anK4SZ5neunFYre5blg
# W1JkVI+JSLunPfNpKqAKPMPiJ4mKu0vxTeFsY6NMzeRINnr4ctoJf2zED1eMk+R5
# qEJWZfcjXAfMHF0VGvmMHbISCygJXBUMjK0I58N2hJbQPinGiQvQMM8M8S+S3bUm
# 0bQxYJPB9ipIz2N3j/xcgQV60df7ut9qp1buVC9XyRiozkUadjFJBCFtB9+Fum+6
# MmXwW94LZbKBYiB7gtEjnLdaqCyua5pnFqQG3BbWgpEpXbNlNVTw9cajKhqTD+H+
# R63wPSojo0jc2idmdJCVeUxxQFW/tpWdBXQ0fDRAqIkTTZhF4e+vM82aPd61jpDO
# M4gFsddTXNDhElAw14/RK+wtIZQHliaSQSxRrzpb8n0tKR+41XvBKIsqYBQUDN3o
# 7xe3j9SzpU4=
# =fyHW
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 03 Nov 2025 11:56:55 AM CET
# gpg:                using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg:                issuer "thuth@redhat.com"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [unknown]
# gpg:                 aka "Thomas Huth <thuth@redhat.com>" [unknown]
# gpg:                 aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# gpg:                 aka "Thomas Huth <huth@tuxfamily.org>" [unknown]
# gpg: WARNING: The key's User ID is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3  EAB9 2ED9 D774 FE70 2DB5

* tag 'pull-request-2025-11-03' of https://gitlab.com/thuth/qemu: (22 commits)
  tests/tcg/s390x: Test SET CLOCK COMPARATOR
  target/s390x: Use address generation for register branch targets
  target/s390x: Fix missing clock-comparator interrupts after reset
  target/s390x: Fix missing interrupts for small CKC values
  hw/s390x: Use memory_region_size()
  tests/functional: include the lower level QMP log messages
  tests/functional: include logger name and function in messages
  tests/functional/ppc64: Fix class names to silence pylint warnings
  tests/functional/x86_64/test_virtio_balloon: Fix cosmetic issues from pylint
  tests/functional/x86_64/test_acpi_bits: Silence warnings reported by pylint
  tests/functional/rx/test_gdbsim: Remove unused variables
  tests/functional/ppc64/test_mac99: Fix style issues reported by pylint
  tests/functional/migration: Fix bad indentation
  MAINTAINERS: fix functional tests section
  tests/functional/.../testcase.py: better socketdir cleanup
  tests/functional/arm/test_aspeed_ast1030: Remove unused import
  tests/functional: Fix problems in utils.py reported by pylint
  tests/functional: Fix problems in uncompress.py reported by pylint
  tests/functional: Fix problems in linuxkernel.py reported by pylint
  tests/functional: Fix problems in decorators.py reported by pylint
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-11-04 13:01:16 +01:00
commit 7ae004869a
25 changed files with 262 additions and 179 deletions

View file

@ -4423,6 +4423,7 @@ Functional testing framework
M: Thomas Huth <thuth@redhat.com>
R: Philippe Mathieu-Daudé <philmd@linaro.org>
R: Daniel P. Berrange <berrange@redhat.com>
S: Maintained
F: docs/devel/testing/functional.rst
F: scripts/clean_functional_cache.py
F: tests/functional/qemu_test/

View file

@ -396,7 +396,7 @@ static MemoryRegion *s390_get_subregion(MemoryRegion *mr, uint64_t offset,
uint64_t subregion_size;
QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) {
subregion_size = int128_get64(subregion->size);
subregion_size = memory_region_size(subregion);
if ((offset >= subregion->addr) &&
(offset + len) <= (subregion->addr + subregion_size)) {
mr = subregion;

View file

@ -527,7 +527,7 @@ def main():
# Async QMP, when in use, is chatty about connection failures.
# This script knowingly generates a ton of connection errors.
# Silence this logger.
logging.getLogger('qemu.qmp.qmp_client').setLevel(logging.CRITICAL)
logging.getLogger('qemu.qmp.protocol').setLevel(logging.CRITICAL)
fatal_failures = []
wl_stats = {}

View file

@ -1959,6 +1959,10 @@ void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
if (env->cregs[i] != val && i >= 9 && i <= 11) {
PERchanged = true;
}
if (i == 0 && !(env->cregs[i] & CR0_CKC_SC) && (val & CR0_CKC_SC)) {
BQL_LOCK_GUARD();
tcg_s390_tod_updated(env_cpu(env), RUN_ON_CPU_NULL);
}
env->cregs[i] = val;
HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%" PRIx64 "\n",
i, src, val);
@ -1989,10 +1993,15 @@ void HELPER(lctl)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
for (i = r1;; i = (i + 1) % 16) {
uint32_t val = cpu_ldl_data_ra(env, src, ra);
uint64_t val64 = deposit64(env->cregs[i], 0, 32, val);
if ((uint32_t)env->cregs[i] != val && i >= 9 && i <= 11) {
PERchanged = true;
}
env->cregs[i] = deposit64(env->cregs[i], 0, 32, val);
if (i == 0 && !(env->cregs[i] & CR0_CKC_SC) && (val64 & CR0_CKC_SC)) {
BQL_LOCK_GUARD();
tcg_s390_tod_updated(env_cpu(env), RUN_ON_CPU_NULL);
}
env->cregs[i] = val64;
HELPER_LOG("load ctl %d from 0x%" PRIx64 " == 0x%x\n", i, src, val);
src += sizeof(uint32_t);

View file

@ -199,11 +199,15 @@ static void update_ckc_timer(CPUS390XState *env)
return;
}
/* difference between origins */
time = env->ckc - td->base.low;
if (env->ckc < td->base.low) {
time = 0;
} else {
/* difference between origins */
time = env->ckc - td->base.low;
/* nanoseconds */
time = tod2time(time);
/* nanoseconds */
time = tod2time(time);
}
timer_mod(env->tod_timer, time);
}

View file

@ -5613,6 +5613,7 @@ static void in2_r2_nz(DisasContext *s, DisasOps *o)
int r2 = get_field(s, r2);
if (r2 != 0) {
o->in2 = load_reg(r2);
gen_addi_and_wrap_i64(s, o->in2, o->in2, 0);
}
}
#define SPEC_in2_r2_nz 0
@ -6379,10 +6380,12 @@ static void s390x_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
/* 31-bit mode */
if (!(dc->base.tb->flags & FLAG_MASK_64)) {
dc->base.pc_first &= 0x7fffffff;
dc->base.pc_next = dc->base.pc_first;
if (dc->base.tb->flags & FLAG_MASK_32) {
if (!(dc->base.tb->flags & FLAG_MASK_64)) {
assert(!(dc->base.pc_first & ~((1ULL << 31) - 1)));
}
} else {
assert(!(dc->base.pc_first & ~((1ULL << 24) - 1)));
}
dc->cc_op = CC_OP_DYNAMIC;

View file

@ -6,9 +6,8 @@
#
# SPDX-License-Identifier: GPL-2.0-or-later
from qemu_test import LinuxKernelTest, Asset
from aspeed import AspeedTest
from qemu_test import exec_command_and_wait_for_pattern
from qemu_test import Asset, exec_command_and_wait_for_pattern
class AST1030Machine(AspeedTest):

View file

@ -30,11 +30,11 @@ class MigrationTest(QemuSystemTest):
end = time.monotonic() + self.timeout
while time.monotonic() < end and not self.migration_finished(src_vm):
time.sleep(0.1)
time.sleep(0.1)
end = time.monotonic() + self.timeout
while time.monotonic() < end and not self.migration_finished(dst_vm):
time.sleep(0.1)
time.sleep(0.1)
self.assertEqual(src_vm.cmd('query-migrate')['status'], 'completed')
self.assertEqual(dst_vm.cmd('query-migrate')['status'], 'completed')

View file

@ -10,7 +10,7 @@
from qemu_test import QemuSystemTest
from qemu_test import wait_for_console_pattern
class ppc74xxCpu(QemuSystemTest):
class Ppc74xxCpu(QemuSystemTest):
timeout = 5

View file

@ -8,10 +8,11 @@ from qemu_test import LinuxKernelTest, Asset
from qemu_test import exec_command_and_wait_for_pattern
class sam460exTest(LinuxKernelTest):
class Sam460exTest(LinuxKernelTest):
ASSET_BR2_SAM460EX_LINUX = Asset(
'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/buildroot/qemu_ppc_sam460ex-2023.11-8-gdcd9f0f6eb-20240105/vmlinux',
('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main'
'/buildroot/qemu_ppc_sam460ex-2023.11-8-gdcd9f0f6eb-20240105/vmlinux'),
'6f46346f3e20e8b5fc050ff363f350f8b9d76a051b9e0bd7ea470cc680c14df2')
def test_ppc_sam460ex_buildroot(self):

View file

@ -7,14 +7,16 @@
from qemu_test import LinuxKernelTest, Asset
from qemu_test import exec_command_and_wait_for_pattern
class mac99Test(LinuxKernelTest):
class Mac99Test(LinuxKernelTest):
ASSET_BR2_MAC99_LINUX = Asset(
'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main/buildroot/qemu_ppc64_mac99-2023.11-8-gdcd9f0f6eb-20240105/vmlinux',
('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main'
'/buildroot/qemu_ppc64_mac99-2023.11-8-gdcd9f0f6eb-20240105/vmlinux'),
'd59307437e4365f2cced0bbd1b04949f7397b282ef349b7cafd894d74aadfbff')
ASSET_BR2_MAC99_ROOTFS = Asset(
'https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main//buildroot/qemu_ppc64_mac99-2023.11-8-gdcd9f0f6eb-20240105/rootfs.ext2',
('https://github.com/legoater/qemu-ppc-boot/raw/refs/heads/main'
'/buildroot/qemu_ppc64_mac99-2023.11-8-gdcd9f0f6eb-20240105/rootfs.ext2'),
'bbd5fd8af62f580bc4e585f326fe584e22856572633a8333178ea6d4ed4955a4')
def test_ppc64_mac99_buildroot(self):

View file

@ -10,7 +10,7 @@
from qemu_test import LinuxKernelTest, Asset
from qemu_test import wait_for_console_pattern
class powernvMachine(LinuxKernelTest):
class PowernvMachine(LinuxKernelTest):
timeout = 90
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 '

View file

@ -10,7 +10,7 @@
from qemu_test import QemuSystemTest, Asset
from qemu_test import wait_for_console_pattern
class pseriesMachine(QemuSystemTest):
class PseriesMachine(QemuSystemTest):
timeout = 90
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 console=hvc0 '

View file

@ -18,7 +18,7 @@ from qemu_test import skipFlakyTest
from reverse_debugging import ReverseDebugging
class ReverseDebugging_ppc64(ReverseDebugging):
class ReverseDebuggingPpc64(ReverseDebugging):
@skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/1992")
def test_ppc64_pseries(self):

View file

@ -112,7 +112,7 @@ class Asset:
return False
self.log.debug("Time out while waiting for %s!", tmp_cache_file)
raise
raise TimeoutError(f"Time out while waiting for {tmp_cache_file}")
def _save_time_stamp(self):
'''
@ -141,7 +141,7 @@ class Asset:
self.log.info("Downloading %s to %s...", self.url, self.cache_file)
tmp_cache_file = self.cache_file.with_suffix(".download")
for retries in range(3):
for _retries in range(3):
try:
with tmp_cache_file.open("xb") as dst:
with urllib.request.urlopen(self.url) as resp:
@ -181,7 +181,7 @@ class Asset:
# server or networking problem
if e.code == 404:
raise AssetError(self, "Unable to download: "
"HTTP error %d" % e.code)
"HTTP error %d" % e.code) from e
continue
except URLError as e:
# This is typically a network/service level error
@ -190,7 +190,7 @@ class Asset:
self.log.error("Unable to download %s: URL error %s",
self.url, e.reason)
raise AssetError(self, "Unable to download: URL error %s" %
e.reason, transient=True)
e.reason, transient=True) from e
except ConnectionError as e:
# A socket connection failure, such as dropped conn
# or refused conn
@ -201,7 +201,7 @@ class Asset:
except Exception as e:
tmp_cache_file.unlink()
raise AssetError(self, "Unable to download: %s" % e,
transient=True)
transient=True) from e
if not os.path.exists(tmp_cache_file):
raise AssetError(self, "Download retries exceeded", transient=True)
@ -214,7 +214,6 @@ class Asset:
self.hash.encode('utf8'))
except Exception as e:
self.log.debug("Unable to set xattr on %s: %s", tmp_cache_file, e)
pass
if not self._check(tmp_cache_file):
tmp_cache_file.unlink()
@ -224,9 +223,10 @@ class Asset:
# Remove write perms to stop tests accidentally modifying them
os.chmod(self.cache_file, stat.S_IRUSR | stat.S_IRGRP)
self.log.info("Cached %s at %s" % (self.url, self.cache_file))
self.log.info("Cached %s at %s", self.url, self.cache_file)
return str(self.cache_file)
@staticmethod
def precache_test(test):
log = logging.getLogger('qemu-test')
log.setLevel(logging.DEBUG)
@ -237,16 +237,17 @@ class Asset:
handler.setFormatter(formatter)
log.addHandler(handler)
for name, asset in vars(test.__class__).items():
if name.startswith("ASSET_") and type(asset) == Asset:
if name.startswith("ASSET_") and isinstance(asset, Asset):
try:
asset.fetch()
except AssetError as e:
if not e.transient:
raise
log.error("%s: skipping asset precache" % e)
log.error("%s: skipping asset precache", e)
log.removeHandler(handler)
@staticmethod
def precache_suite(suite):
for test in suite:
if isinstance(test, unittest.TestSuite):
@ -254,9 +255,10 @@ class Asset:
elif isinstance(test, unittest.TestCase):
Asset.precache_test(test)
def precache_suites(path, cacheTstamp):
@staticmethod
def precache_suites(path, cache_tstamp):
loader = unittest.loader.defaultTestLoader
tests = loader.loadTestsFromNames([path], None)
with open(cacheTstamp, "w") as fh:
with open(cache_tstamp, "w", encoding='utf-8'):
Asset.precache_suite(tests)

View file

@ -10,136 +10,134 @@ from unittest import skipIf, skipUnless
from .cmd import which
'''
Decorator to skip execution of a test if the provided
environment variables are not set.
Example:
@skipIfMissingEnv("QEMU_ENV_VAR0", "QEMU_ENV_VAR1")
'''
def skipIfMissingEnv(*vars_):
'''
Decorator to skip execution of a test if the provided
environment variables are not set.
Example:
@skipIfMissingEnv("QEMU_ENV_VAR0", "QEMU_ENV_VAR1")
'''
missing_vars = []
for var in vars_:
if os.getenv(var) == None:
if os.getenv(var) is None:
missing_vars.append(var)
has_vars = True if len(missing_vars) == 0 else False
has_vars = len(missing_vars) == 0
return skipUnless(has_vars, f"Missing env var(s): {', '.join(missing_vars)}")
'''
Decorator to skip execution of a test if the list
of command binaries is not available in $PATH.
Example:
@skipIfMissingCommands("mkisofs", "losetup")
'''
def skipIfMissingCommands(*args):
'''
Decorator to skip execution of a test if the list
of command binaries is not available in $PATH.
Example:
@skipIfMissingCommands("mkisofs", "losetup")
'''
has_cmds = True
for cmd in args:
if not which(cmd):
has_cmds = False
break
if not which(cmd):
has_cmds = False
break
return skipUnless(has_cmds, 'required command(s) "%s" not installed' %
", ".join(args))
'''
Decorator to skip execution of a test if the current
host operating system does match one of the prohibited
ones.
Example
@skipIfOperatingSystem("Linux", "Darwin")
'''
def skipIfOperatingSystem(*args):
'''
Decorator to skip execution of a test if the current host
operating system does match one of the prohibited ones.
Example:
@skipIfOperatingSystem("Linux", "Darwin")
'''
return skipIf(platform.system() in args,
'running on an OS (%s) that is not able to run this test' %
", ".join(args))
'''
Decorator to skip execution of a test if the current
host machine does not match one of the permitted
machines.
Example
@skipIfNotMachine("x86_64", "aarch64")
'''
def skipIfNotMachine(*args):
'''
Decorator to skip execution of a test if the current
host machine does not match one of the permitted machines.
Example:
@skipIfNotMachine("x86_64", "aarch64")
'''
return skipUnless(platform.machine() in args,
'not running on one of the required machine(s) "%s"' %
", ".join(args))
'''
Decorator to skip execution of flaky tests, unless
the $QEMU_TEST_FLAKY_TESTS environment variable is set.
A bug URL must be provided that documents the observed
failure behaviour, so it can be tracked & re-evaluated
in future.
Historical tests may be providing "None" as the bug_url
but this should not be done for new test.
Example:
@skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/NNN")
'''
def skipFlakyTest(bug_url):
'''
Decorator to skip execution of flaky tests, unless
the $QEMU_TEST_FLAKY_TESTS environment variable is set.
A bug URL must be provided that documents the observed
failure behaviour, so it can be tracked & re-evaluated
in future.
Historical tests may be providing "None" as the bug_url
but this should not be done for new test.
Example:
@skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/NNN")
'''
if bug_url is None:
bug_url = "FIXME: reproduce flaky test and file bug report or remove"
return skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'),
f'Test is unstable: {bug_url}')
'''
Decorator to skip execution of tests which are likely
to execute untrusted commands on the host, or commands
which process untrusted code, unless the
$QEMU_TEST_ALLOW_UNTRUSTED_CODE env var is set.
Example:
@skipUntrustedTest()
'''
def skipUntrustedTest():
'''
Decorator to skip execution of tests which are likely
to execute untrusted commands on the host, or commands
which process untrusted code, unless the
$QEMU_TEST_ALLOW_UNTRUSTED_CODE env var is set.
Example:
@skipUntrustedTest()
'''
return skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'),
'Test runs untrusted code / processes untrusted data')
'''
Decorator to skip execution of tests which need large
data storage (over around 500MB-1GB mark) on the host,
unless the $QEMU_TEST_ALLOW_LARGE_STORAGE environment
variable is set
Example:
@skipBigDataTest()
'''
def skipBigDataTest():
'''
Decorator to skip execution of tests which need large
data storage (over around 500MB-1GB mark) on the host,
unless the $QEMU_TEST_ALLOW_LARGE_STORAGE environment
variable is set
Example:
@skipBigDataTest()
'''
return skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'),
'Test requires large host storage space')
'''
Decorator to skip execution of tests which have a really long
runtime (and might e.g. time out if QEMU has been compiled with
debugging enabled) unless the $QEMU_TEST_ALLOW_SLOW
environment variable is set
Example:
@skipSlowTest()
'''
def skipSlowTest():
'''
Decorator to skip execution of tests which have a really long
runtime (and might e.g. time out if QEMU has been compiled with
debugging enabled) unless the $QEMU_TEST_ALLOW_SLOW
environment variable is set
Example:
@skipSlowTest()
'''
return skipUnless(os.getenv('QEMU_TEST_ALLOW_SLOW'),
'Test has a very long runtime and might time out')
'''
Decorator to skip execution of a test if the list
of python imports is not available.
Example:
@skipIfMissingImports("numpy", "cv2")
'''
def skipIfMissingImports(*args):
'''
Decorator to skip execution of a test if the list
of python imports is not available.
Example:
@skipIfMissingImports("numpy", "cv2")
'''
has_imports = True
for impname in args:
try:
@ -151,15 +149,15 @@ def skipIfMissingImports(*args):
return skipUnless(has_imports, 'required import(s) "%s" not installed' %
", ".join(args))
'''
Decorator to skip execution of a test if the system's
locked memory limit is below the required threshold.
Takes required locked memory threshold in kB.
Example:
@skipLockedMemoryTest(2_097_152)
'''
def skipLockedMemoryTest(locked_memory):
'''
Decorator to skip execution of a test if the system's
locked memory limit is below the required threshold.
Takes required locked memory threshold in kB.
Example:
@skipLockedMemoryTest(2_097_152)
'''
# get memlock hard limit in bytes
_, ulimit_memory = resource.getrlimit(resource.RLIMIT_MEMLOCK)

View file

@ -83,12 +83,12 @@ class LinuxKernelTest(QemuSystemTest):
self.vm.set_console(console_index=console_index)
self.vm.add_args('-kernel', kernel)
if initrd:
self.vm.add_args('-initrd', initrd)
self.vm.add_args('-initrd', initrd)
if dtb:
self.vm.add_args('-dtb', dtb)
self.vm.add_args('-dtb', dtb)
self.vm.launch()
if wait_for:
self.wait_for_console_pattern(wait_for)
self.wait_for_console_pattern(wait_for)
def check_http_download(self, filename, hashsum, guestport=8080,
pythoncmd='python3 -m http.server'):

View file

@ -217,7 +217,7 @@ class QemuBaseTest(unittest.TestCase):
self._log_fh = logging.FileHandler(self.log_filename, mode='w')
self._log_fh.setLevel(logging.DEBUG)
fileFormatter = logging.Formatter(
'%(asctime)s - %(levelname)s: %(message)s')
'%(asctime)s - %(levelname)s: %(name)s.%(funcName)s %(message)s')
self._log_fh.setFormatter(fileFormatter)
self.log.addHandler(self._log_fh)
@ -225,6 +225,9 @@ class QemuBaseTest(unittest.TestCase):
self.machinelog = logging.getLogger('qemu.machine')
self.machinelog.setLevel(logging.DEBUG)
self.machinelog.addHandler(self._log_fh)
self.qmplog = logging.getLogger('qemu.qmp')
self.qmplog.setLevel(logging.DEBUG)
self.qmplog.addHandler(self._log_fh)
if not self.assets_available():
self.skipTest('One or more assets is not available')
@ -233,8 +236,9 @@ class QemuBaseTest(unittest.TestCase):
if "QEMU_TEST_KEEP_SCRATCH" not in os.environ:
shutil.rmtree(self.workdir)
if self.socketdir is not None:
shutil.rmtree(self.socketdir.name)
self.socketdir.cleanup()
self.socketdir = None
self.qmplog.removeHandler(self._log_fh)
self.machinelog.removeHandler(self._log_fh)
self.log.removeHandler(self._log_fh)
self._log_fh.close()

View file

@ -58,20 +58,20 @@ def zstd_uncompress(zstd_path, output_path):
os.chmod(output_path, stat.S_IRUSR | stat.S_IWUSR)
'''
@params compressed: filename, Asset, or file-like object to uncompress
@params uncompressed: filename to uncompress into
@params format: optional compression format (gzip, lzma)
Uncompresses @compressed into @uncompressed
If @format is None, heuristics will be applied to guess the format
from the filename or Asset URL. @format must be non-None if @uncompressed
is a file-like object.
Returns the fully qualified path to the uncompessed file
'''
def uncompress(compressed, uncompressed, format=None):
'''
@params compressed: filename, Asset, or file-like object to uncompress
@params uncompressed: filename to uncompress into
@params format: optional compression format (gzip, lzma)
Uncompresses @compressed into @uncompressed
If @format is None, heuristics will be applied to guess the
format from the filename or Asset URL. @format must be non-None
if @uncompressed is a file-like object.
Returns the fully qualified path to the uncompessed file
'''
if format is None:
format = guess_uncompress_format(compressed)
@ -84,19 +84,19 @@ def uncompress(compressed, uncompressed, format=None):
else:
raise Exception(f"Unknown compression format {format}")
'''
@params compressed: filename, Asset, or file-like object to guess
Guess the format of @compressed, raising an exception if
no format can be determined
'''
def guess_uncompress_format(compressed):
if type(compressed) == Asset:
'''
@params compressed: filename, Asset, or file-like object to guess
Guess the format of @compressed, raising an exception if
no format can be determined
'''
if isinstance(compressed, Asset):
compressed = urlparse(compressed.url).path
elif type(compressed) != str:
elif not isinstance(compressed, str):
raise Exception(f"Unable to guess compression cformat for {compressed}")
(name, ext) = os.path.splitext(compressed)
(_name, ext) = os.path.splitext(compressed)
if ext == ".xz":
return "xz"
elif ext == ".gz":

View file

@ -17,10 +17,10 @@ def get_usernet_hostfwd_port(vm):
res = vm.cmd('human-monitor-command', command_line='info usernet')
return get_info_usernet_hostfwd_port(res)
"""
Round up to next power of 2
"""
def pow2ceil(x):
"""
Round up to next power of 2
"""
return 1 if x == 0 else 2**(x - 1).bit_length()
def file_truncate(path, size):
@ -28,12 +28,12 @@ def file_truncate(path, size):
with open(path, 'ab+') as fd:
fd.truncate(size)
"""
Expand file size to next power of 2
"""
def image_pow2ceil_expand(path):
size = os.path.getsize(path)
size_aligned = pow2ceil(size)
if size != size_aligned:
with open(path, 'ab+') as fd:
fd.truncate(size_aligned)
"""
Expand file size to next power of 2
"""
size = os.path.getsize(path)
size_aligned = pow2ceil(size)
if size != size_aligned:
with open(path, 'ab+') as fd:
fd.truncate(size_aligned)

View file

@ -17,9 +17,6 @@ from qemu_test import wait_for_console_pattern, skipFlakyTest
class RxGdbSimMachine(QemuSystemTest):
timeout = 30
KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 '
ASSET_UBOOT = Asset(
('https://github.com/philmd/qemu-testing-blob/raw/rx-gdbsim/rx/gdbsim/'
'u-boot.bin'),
@ -47,7 +44,7 @@ class RxGdbSimMachine(QemuSystemTest):
self.vm.launch()
uboot_version = 'U-Boot 2016.05-rc3-23705-ga1ef3c71cb-dirty'
wait_for_console_pattern(self, uboot_version)
gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)'
#gcc_version = 'rx-unknown-linux-gcc (GCC) 9.0.0 20181105 (experimental)'
# FIXME limit baudrate on chardev, else we type too fast
# https://gitlab.com/qemu-project/qemu/-/issues/2691
#exec_command_and_wait_for_pattern(self, 'version', gcc_version)
@ -63,7 +60,6 @@ class RxGdbSimMachine(QemuSystemTest):
kernel_path = self.ASSET_KERNEL.fetch()
self.vm.set_console()
kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE + 'earlycon'
self.vm.add_args('-kernel', kernel_path,
'-dtb', dtb_path,
'-no-reboot')

View file

@ -57,6 +57,7 @@ class QEMUBitsMachine(QEMUMachine): # pylint: disable=too-few-public-methods
"""
def __init__(self,
binary: str,
*,
args: Sequence[str] = (),
wrapper: Sequence[str] = (),
name: Optional[str] = None,
@ -225,7 +226,7 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=True)
self.log.info("grub-mkrescue output %s" % proc.stdout)
self.log.info("grub-mkrescue output %s", proc.stdout)
else:
subprocess.check_call([mkrescue_script, '-o',
iso_file, bits_dir],
@ -287,9 +288,8 @@ class AcpiBitsTest(QemuSystemTest): #pylint: disable=too-many-instance-attribute
except AssertionError as e:
self._print_log(log)
raise e
else:
if os.getenv('V') or os.getenv('BITS_DEBUG'):
self._print_log(log)
if os.getenv('V') or os.getenv('BITS_DEBUG'):
self._print_log(log)
def tearDown(self):
"""

View file

@ -66,7 +66,7 @@ class VirtioBalloonx86(QemuSystemTest):
when = ret.get('last-update')
assert when == 0
stats = ret.get('stats')
for name, val in stats.items():
for _name, val in stats.items():
assert val == UNSET_STATS_VALUE
def assert_running_stats(self, then):
@ -87,10 +87,10 @@ class VirtioBalloonx86(QemuSystemTest):
now = time.time()
assert when > then and when < now
assert now > when > then
stats = ret.get('stats')
# Stat we expect this particular Kernel to have set
expectData = [
expect_data = [
"stat-available-memory",
"stat-disk-caches",
"stat-free-memory",
@ -103,7 +103,7 @@ class VirtioBalloonx86(QemuSystemTest):
"stat-total-memory",
]
for name, val in stats.items():
if name in expectData:
if name in expect_data:
assert val != UNSET_STATS_VALUE
else:
assert val == UNSET_STATS_VALUE

View file

@ -28,6 +28,7 @@ ASM_TESTS = \
mc \
per \
precise-smc-softmmu \
sckc \
ssm-early \
stosm-early \
stpq \

63
tests/tcg/s390x/sckc.S Normal file
View file

@ -0,0 +1,63 @@
/*
* Test clock comparator.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
.org 0x130
ext_old_psw:
.org 0x1b0
ext_new_psw:
.quad 0x180000000, _ext /* 64-bit mode */
.org 0x1d0
pgm_new_psw:
.quad 0x2000000000000,0 /* disabled wait */
.org 0x200 /* lowcore padding */
.globl _start
_start:
lpswe start31_psw
_start31:
stctg %c0,%c0,c0
oi c0+6,8 /* set clock-comparator subclass mask */
lctlg %c0,%c0,c0
0:
brasl %r14,_f /* %r14's most significant bit is 1 */
jg 0b
_f:
br %r14 /* it must not end up in ext_old_psw */
_ext:
stg %r0,ext_saved_r0
lg %r0,ext_counter
aghi %r0,1
stg %r0,ext_counter
cgfi %r0,0x1000
jnz 0f
lpswe success_psw
0:
stck clock
lg %r0,clock
agfi %r0,0x40000 /* 64us * 0x1000 =~ 0.25s */
stg %r0,clock
sckc clock
lg %r0,ext_saved_r0
lpswe ext_old_psw
.align 8
start31_psw:
.quad 0x100000080000000,_start31 /* EX, 31-bit mode */
success_psw:
.quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
c0:
.skip 8
clock:
.quad 0
ext_counter:
.quad 0
ext_saved_r0:
.skip 8