xref: /openbmc/qemu/tests/functional/qemu_test/decorators.py (revision aca2c48e4d26426c14499fd3d8a2e333ac57d267)
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