xref: /qemu/tests/functional/qemu_test/decorators.py (revision 4be0fce498d0a08f18b3a9accdb9ded79484d30a)
1# SPDX-License-Identifier: GPL-2.0-or-later
2#
3# Decorators useful in functional tests
4
5import os
6import platform
7from unittest import skipUnless
8
9from .cmd import which
10
11'''
12Decorator to skip execution of a test if the list
13of command binaries is not available in $PATH.
14Example:
15
16  @skipIfMissingCommands("mkisofs", "losetup")
17'''
18def skipIfMissingCommands(*args):
19    def has_cmds(cmdlist):
20        for cmd in cmdlist:
21            if not which(cmd):
22                return False
23        return True
24
25    return skipUnless(lambda: has_cmds(args),
26                      '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(lambda: 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 a test if the list
91of python imports is not available.
92Example:
93
94  @skipIfMissingImports("numpy", "cv2")
95'''
96def skipIfMissingImports(*args):
97    def has_imports(importlist):
98        for impname in importlist:
99            try:
100                import impname
101            except ImportError:
102                return False
103        return True
104
105    return skipUnless(lambda: has_imports(args),
106                      'required import(s) "%s" not installed' %
107                      ", ".join(args))
108