1# SPDX-License-Identifier: GPL-2.0-or-later 2# 3# Decorators useful in functional tests 4 5import importlib 6import os 7import platform 8from unittest import skipUnless 9 10from .cmd import which 11 12''' 13Decorator to skip execution of a test if the list 14of command binaries is not available in $PATH. 15Example: 16 17 @skipIfMissingCommands("mkisofs", "losetup") 18''' 19def skipIfMissingCommands(*args): 20 def has_cmds(cmdlist): 21 for cmd in cmdlist: 22 if not which(cmd): 23 return False 24 return True 25 26 return skipUnless(lambda: has_cmds(args), 27 'required command(s) "%s" not installed' % 28 ", ".join(args)) 29 30''' 31Decorator to skip execution of a test if the current 32host machine does not match one of the permitted 33machines. 34Example 35 36 @skipIfNotMachine("x86_64", "aarch64") 37''' 38def skipIfNotMachine(*args): 39 return skipUnless(lambda: platform.machine() in args, 40 'not running on one of the required machine(s) "%s"' % 41 ", ".join(args)) 42 43''' 44Decorator to skip execution of flaky tests, unless 45the $QEMU_TEST_FLAKY_TESTS environment variable is set. 46A bug URL must be provided that documents the observed 47failure behaviour, so it can be tracked & re-evaluated 48in future. 49 50Historical tests may be providing "None" as the bug_url 51but this should not be done for new test. 52 53Example: 54 55 @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/NNN") 56''' 57def skipFlakyTest(bug_url): 58 if bug_url is None: 59 bug_url = "FIXME: reproduce flaky test and file bug report or remove" 60 return skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 61 f'Test is unstable: {bug_url}') 62 63''' 64Decorator to skip execution of tests which are likely 65to execute untrusted commands on the host, or commands 66which process untrusted code, unless the 67$QEMU_TEST_ALLOW_UNTRUSTED_CODE env var is set. 68Example: 69 70 @skipUntrustedTest() 71''' 72def skipUntrustedTest(): 73 return skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'), 74 'Test runs untrusted code / processes untrusted data') 75 76''' 77Decorator to skip execution of tests which need large 78data storage (over around 500MB-1GB mark) on the host, 79unless the $QEMU_TEST_ALLOW_LARGE_STORAGE environment 80variable is set 81 82Example: 83 84 @skipBigDataTest() 85''' 86def skipBigDataTest(): 87 return skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'), 88 'Test requires large host storage space') 89 90''' 91Decorator to skip execution of a test if the list 92of python imports is not available. 93Example: 94 95 @skipIfMissingImports("numpy", "cv2") 96''' 97def skipIfMissingImports(*args): 98 def has_imports(importlist): 99 for impname in importlist: 100 try: 101 importlib.import_module(impname) 102 except ImportError: 103 return False 104 return True 105 106 return skipUnless(lambda: has_imports(args), 107 'required import(s) "%s" not installed' % 108 ", ".join(args)) 109