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