diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.include | 3 | ||||
-rw-r--r-- | tests/functional/meson.build | 33 | ||||
-rw-r--r-- | tests/functional/qemu_test/asset.py | 34 | ||||
-rw-r--r-- | tests/functional/qemu_test/testcase.py | 7 |
4 files changed, 74 insertions, 3 deletions
diff --git a/tests/Makefile.include b/tests/Makefile.include index 66c8cc3..010369b 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -161,7 +161,8 @@ $(FUNCTIONAL_TARGETS): .PHONY: check-functional check-functional: - @$(MAKE) SPEED=thorough check-func check-func-quick + @$(NINJA) precache-functional + @QEMU_TEST_NO_DOWNLOAD=1 $(MAKE) SPEED=thorough check-func check-func-quick # Consolidated targets diff --git a/tests/functional/meson.build b/tests/functional/meson.build index f1f344f..df79775 100644 --- a/tests/functional/meson.build +++ b/tests/functional/meson.build @@ -39,6 +39,7 @@ tests_x86_64_system_quick = [ tests_x86_64_system_thorough = [ ] +precache_all = [] foreach speed : ['quick', 'thorough'] foreach dir : target_dirs @@ -78,11 +79,35 @@ foreach speed : ['quick', 'thorough'] meson.current_source_dir()) foreach test : target_tests - test('func-@0@/@1@'.format(target_base, test), + testname = '@0@-@1@'.format(target_base, test) + testfile = 'test_' + test + '.py' + testpath = meson.current_source_dir() / testfile + teststamp = testname + '.tstamp' + test_precache_env = environment() + test_precache_env.set('QEMU_TEST_PRECACHE', meson.current_build_dir() / teststamp) + test_precache_env.set('PYTHONPATH', meson.project_source_root() / 'python:' + + meson.current_source_dir()) + precache = custom_target('func-precache-' + testname, + output: teststamp, + command: [python, testpath], + depend_files: files(testpath), + build_by_default: false, + env: test_precache_env) + precache_all += precache + + # Ideally we would add 'precache' to 'depends' here, such that + # 'build_by_default: false' lets the pre-caching automatically + # run immediately before the test runs. In practice this is + # broken in meson, with it running the pre-caching in the normal + # compile phase https://github.com/mesonbuild/meson/issues/2518 + # If the above bug ever gets fixed, when QEMU changes the min + # meson version, add the 'depends' and remove the custom + # 'run_target' logic below & in Makefile.include + test('func-' + testname, python, depends: [test_deps, test_emulator, emulator_modules], env: test_env, - args: [meson.current_source_dir() / 'test_' + test + '.py'], + args: [testpath], protocol: 'tap', timeout: test_timeouts.get(test, 60), priority: test_timeouts.get(test, 60), @@ -90,3 +115,7 @@ foreach speed : ['quick', 'thorough'] endforeach endforeach endforeach + +run_target('precache-functional', + depends: precache_all, + command: ['true']) diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py index c0e675d..b329ab7 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -9,6 +9,8 @@ import hashlib import logging import os import subprocess +import sys +import unittest import urllib.request from pathlib import Path from shutil import copyfileobj @@ -62,6 +64,9 @@ class Asset: self.cache_file, self.url) return str(self.cache_file) + if os.environ.get("QEMU_TEST_NO_DOWNLOAD", False): + raise Exception("Asset cache is invalid and downloads disabled") + self.log.info("Downloading %s to %s...", self.url, self.cache_file) tmp_cache_file = self.cache_file.with_suffix(".download") @@ -95,3 +100,32 @@ class Asset: self.log.info("Cached %s at %s" % (self.url, self.cache_file)) return str(self.cache_file) + + def precache_test(test): + log = logging.getLogger('qemu-test') + log.setLevel(logging.DEBUG) + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(logging.DEBUG) + formatter = logging.Formatter( + '%(asctime)s - %(name)s - %(levelname)s - %(message)s') + handler.setFormatter(formatter) + log.addHandler(handler) + for name, asset in vars(test.__class__).items(): + if name.startswith("ASSET_") and type(asset) == Asset: + log.info("Attempting to cache '%s'" % asset) + asset.fetch() + log.removeHandler(handler) + + def precache_suite(suite): + for test in suite: + if isinstance(test, unittest.TestSuite): + Asset.precache_suite(test) + elif isinstance(test, unittest.TestCase): + Asset.precache_test(test) + + def precache_suites(path, cacheTstamp): + loader = unittest.loader.defaultTestLoader + tests = loader.loadTestsFromNames([path], None) + + with open(cacheTstamp, "w") as fh: + Asset.precache_suite(tests) diff --git a/tests/functional/qemu_test/testcase.py b/tests/functional/qemu_test/testcase.py index b2dd863..18314be 100644 --- a/tests/functional/qemu_test/testcase.py +++ b/tests/functional/qemu_test/testcase.py @@ -21,6 +21,7 @@ import uuid from qemu.machine import QEMUMachine from qemu.utils import kvm_available, tcg_available +from .asset import Asset from .cmd import run_cmd from .config import BUILD_DIR @@ -58,6 +59,12 @@ class QemuBaseTest(unittest.TestCase): def main(): path = os.path.basename(sys.argv[0])[:-3] + + cache = os.environ.get("QEMU_TEST_PRECACHE", None) + if cache is not None: + Asset.precache_suites(path, cache) + return + tr = pycotap.TAPTestRunner(message_log = pycotap.LogMode.LogToError, test_output_log = pycotap.LogMode.LogToError) unittest.main(module = None, testRunner = tr, argv=["__dummy__", path]) |