diff --git a/MAINTAINERS b/MAINTAINERS index ee058e2fef..93cef88f46 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4423,6 +4423,7 @@ Functional testing framework M: Thomas Huth R: Philippe Mathieu-Daudé R: Daniel P. Berrange +S: Maintained F: docs/devel/testing/functional.rst F: scripts/clean_functional_cache.py F: tests/functional/qemu_test/ diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index a3bb5aa221..5841dfc4fe 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -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; diff --git a/scripts/device-crash-test b/scripts/device-crash-test index 1ecb9663ae..c1576e8b96 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -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 = {} diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index f1acb1618f..24675fc818 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -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); diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c index 6d9d601d29..215b5b9d93 100644 --- a/target/s390x/tcg/misc_helper.c +++ b/target/s390x/tcg/misc_helper.c @@ -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); } diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index ec9e5a0751..4d2b8c5e2b 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -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; diff --git a/tests/functional/arm/test_aspeed_ast1030.py b/tests/functional/arm/test_aspeed_ast1030.py index 60e2b0251c..d1822edd8f 100755 --- a/tests/functional/arm/test_aspeed_ast1030.py +++ b/tests/functional/arm/test_aspeed_ast1030.py @@ -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): diff --git a/tests/functional/migration.py b/tests/functional/migration.py index 0739554483..2bfb1f7790 100644 --- a/tests/functional/migration.py +++ b/tests/functional/migration.py @@ -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') diff --git a/tests/functional/ppc/test_74xx.py b/tests/functional/ppc/test_74xx.py index 5386016f26..219c7991ac 100755 --- a/tests/functional/ppc/test_74xx.py +++ b/tests/functional/ppc/test_74xx.py @@ -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 diff --git a/tests/functional/ppc/test_sam460ex.py b/tests/functional/ppc/test_sam460ex.py index 31cf9dd6de..024406d155 100755 --- a/tests/functional/ppc/test_sam460ex.py +++ b/tests/functional/ppc/test_sam460ex.py @@ -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): diff --git a/tests/functional/ppc64/test_mac99.py b/tests/functional/ppc64/test_mac99.py index dfd9c01371..a3261a8330 100755 --- a/tests/functional/ppc64/test_mac99.py +++ b/tests/functional/ppc64/test_mac99.py @@ -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): diff --git a/tests/functional/ppc64/test_powernv.py b/tests/functional/ppc64/test_powernv.py index 9ada832b78..0ea6c93e42 100755 --- a/tests/functional/ppc64/test_powernv.py +++ b/tests/functional/ppc64/test_powernv.py @@ -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 ' diff --git a/tests/functional/ppc64/test_pseries.py b/tests/functional/ppc64/test_pseries.py index 67057934e8..7840c4e3ff 100755 --- a/tests/functional/ppc64/test_pseries.py +++ b/tests/functional/ppc64/test_pseries.py @@ -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 ' diff --git a/tests/functional/ppc64/test_reverse_debug.py b/tests/functional/ppc64/test_reverse_debug.py index 69551fb84d..4eef779936 100755 --- a/tests/functional/ppc64/test_reverse_debug.py +++ b/tests/functional/ppc64/test_reverse_debug.py @@ -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): diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py index ab3a7bb591..bae40765ce 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -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) diff --git a/tests/functional/qemu_test/decorators.py b/tests/functional/qemu_test/decorators.py index b239295804..807418359a 100644 --- a/tests/functional/qemu_test/decorators.py +++ b/tests/functional/qemu_test/decorators.py @@ -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) diff --git a/tests/functional/qemu_test/linuxkernel.py b/tests/functional/qemu_test/linuxkernel.py index c4767527da..eb10a81335 100644 --- a/tests/functional/qemu_test/linuxkernel.py +++ b/tests/functional/qemu_test/linuxkernel.py @@ -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'): diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py index 2c0abde395..1d773dd697 100644 --- a/tests/functional/qemu_test/testcase.py +++ b/tests/functional/qemu_test/testcase.py @@ -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() diff --git a/tests/functional/qemu_test/uncompress.py b/tests/functional/qemu_test/uncompress.py index b7ef8f759b..5bbdf8fe32 100644 --- a/tests/functional/qemu_test/uncompress.py +++ b/tests/functional/qemu_test/uncompress.py @@ -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": diff --git a/tests/functional/qemu_test/utils.py b/tests/functional/qemu_test/utils.py index e7c8de8165..826c267785 100644 --- a/tests/functional/qemu_test/utils.py +++ b/tests/functional/qemu_test/utils.py @@ -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) diff --git a/tests/functional/rx/test_gdbsim.py b/tests/functional/rx/test_gdbsim.py index 49245793e1..d31f9a42d6 100755 --- a/tests/functional/rx/test_gdbsim.py +++ b/tests/functional/rx/test_gdbsim.py @@ -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') diff --git a/tests/functional/x86_64/test_acpi_bits.py b/tests/functional/x86_64/test_acpi_bits.py index 9a2816533d..ec716d643b 100755 --- a/tests/functional/x86_64/test_acpi_bits.py +++ b/tests/functional/x86_64/test_acpi_bits.py @@ -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): """ diff --git a/tests/functional/x86_64/test_virtio_balloon.py b/tests/functional/x86_64/test_virtio_balloon.py index 5877b6c408..7a579e0d69 100755 --- a/tests/functional/x86_64/test_virtio_balloon.py +++ b/tests/functional/x86_64/test_virtio_balloon.py @@ -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 diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target index 8cd4667c63..a4425d3184 100644 --- a/tests/tcg/s390x/Makefile.softmmu-target +++ b/tests/tcg/s390x/Makefile.softmmu-target @@ -28,6 +28,7 @@ ASM_TESTS = \ mc \ per \ precise-smc-softmmu \ + sckc \ ssm-early \ stosm-early \ stpq \ diff --git a/tests/tcg/s390x/sckc.S b/tests/tcg/s390x/sckc.S new file mode 100644 index 0000000000..ecd64a3059 --- /dev/null +++ b/tests/tcg/s390x/sckc.S @@ -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