xref: /qemu/tests/functional/qemu_test/decorators.py (revision 53f3a13ac1069975ad47cf8bd05cc96b4ac09962)
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 skipIf, 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    has_cmds = True
21    for cmd in args:
22         if not which(cmd):
23             has_cmds = False
24             break
25
26    return skipUnless(has_cmds, 'required command(s) "%s" not installed' %
27                                ", ".join(args))
28
29'''
30Decorator to skip execution of a test if the current
31host operating system does match one of the prohibited
32ones.
33Example
34
35  @skipIfOperatingSystem("Linux", "Darwin")
36'''
37def skipIfOperatingSystem(*args):
38    return skipIf(platform.system() in args,
39                  'running on an OS (%s) that is not able to run this test' %
40                  ", ".join(args))
41
42'''
43Decorator to skip execution of a test if the current
44host machine does not match one of the permitted
45machines.
46Example
47
48  @skipIfNotMachine("x86_64", "aarch64")
49'''
50def skipIfNotMachine(*args):
51    return skipUnless(platform.machine() in args,
52                      'not running on one of the required machine(s) "%s"' %
53                      ", ".join(args))
54
55'''
56Decorator to skip execution of flaky tests, unless
57the $QEMU_TEST_FLAKY_TESTS environment variable is set.
58A bug URL must be provided that documents the observed
59failure behaviour, so it can be tracked & re-evaluated
60in future.
61
62Historical tests may be providing "None" as the bug_url
63but this should not be done for new test.
64
65Example:
66
67  @skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/NNN")
68'''
69def skipFlakyTest(bug_url):
70    if bug_url is None:
71        bug_url = "FIXME: reproduce flaky test and file bug report or remove"
72    return skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'),
73                      f'Test is unstable: {bug_url}')
74
75'''
76Decorator to skip execution of tests which are likely
77to execute untrusted commands on the host, or commands
78which process untrusted code, unless the
79$QEMU_TEST_ALLOW_UNTRUSTED_CODE env var is set.
80Example:
81
82  @skipUntrustedTest()
83'''
84def skipUntrustedTest():
85    return skipUnless(os.getenv('QEMU_TEST_ALLOW_UNTRUSTED_CODE'),
86                      'Test runs untrusted code / processes untrusted data')
87
88'''
89Decorator to skip execution of tests which need large
90data storage (over around 500MB-1GB mark) on the host,
91unless the $QEMU_TEST_ALLOW_LARGE_STORAGE environment
92variable is set
93
94Example:
95
96  @skipBigDataTest()
97'''
98def skipBigDataTest():
99    return skipUnless(os.getenv('QEMU_TEST_ALLOW_LARGE_STORAGE'),
100                      'Test requires large host storage space')
101
102'''
103Decorator to skip execution of tests which have a really long
104runtime (and might e.g. time out if QEMU has been compiled with
105debugging enabled) unless the $QEMU_TEST_ALLOW_SLOW
106environment variable is set
107
108Example:
109
110  @skipSlowTest()
111'''
112def skipSlowTest():
113    return skipUnless(os.getenv('QEMU_TEST_ALLOW_SLOW'),
114                      'Test has a very long runtime and might time out')
115
116'''
117Decorator to skip execution of a test if the list
118of python imports is not available.
119Example:
120
121  @skipIfMissingImports("numpy", "cv2")
122'''
123def skipIfMissingImports(*args):
124    has_imports = True
125    for impname in args:
126        try:
127            importlib.import_module(impname)
128        except ImportError:
129            has_imports = False
130            break
131
132    return skipUnless(has_imports, 'required import(s) "%s" not installed' %
133                                   ", ".join(args))
134