t/zbd: add test case to check zones in closed condition
[fio.git] / t / fiotestcommon.py
CommitLineData
fb551941
VF
1#!/usr/bin/env python3
2"""
3fiotestcommon.py
4
5This contains constant definitions, helpers, and a Requirements class that can
6be used to help with running fio tests.
7"""
8
9import os
ecd6d30f 10import locale
fb551941
VF
11import logging
12import platform
13import subprocess
14import multiprocessing
fb551941
VF
15
16
17SUCCESS_DEFAULT = {
18 'zero_return': True,
19 'stderr_empty': True,
20 'timeout': 600,
21 }
22SUCCESS_NONZERO = {
23 'zero_return': False,
24 'stderr_empty': False,
25 'timeout': 600,
26 }
27SUCCESS_STDERR = {
28 'zero_return': True,
29 'stderr_empty': False,
30 'timeout': 600,
31 }
32
ecd6d30f
VF
33
34def get_file(filename):
35 """Safely read a file."""
36 file_data = ''
37 success = True
38
39 try:
40 with open(filename, "r", encoding=locale.getpreferredencoding()) as output_file:
41 file_data = output_file.read()
42 except OSError:
43 success = False
44
45 return file_data, success
46
47
fb551941
VF
48class Requirements():
49 """Requirements consists of multiple run environment characteristics.
50 These are to determine if a particular test can be run"""
51
52 _linux = False
53 _libaio = False
54 _io_uring = False
55 _zbd = False
56 _root = False
57 _zoned_nullb = False
58 _not_macos = False
59 _not_windows = False
60 _unittests = False
61 _cpucount4 = False
62 _nvmecdev = False
63
64 def __init__(self, fio_root, args):
65 Requirements._not_macos = platform.system() != "Darwin"
66 Requirements._not_windows = platform.system() != "Windows"
67 Requirements._linux = platform.system() == "Linux"
68
69 if Requirements._linux:
70 config_file = os.path.join(fio_root, "config-host.h")
ecd6d30f 71 contents, success = get_file(config_file)
fb551941
VF
72 if not success:
73 print(f"Unable to open {config_file} to check requirements")
74 Requirements._zbd = True
75 else:
76 Requirements._zbd = "CONFIG_HAS_BLKZONED" in contents
77 Requirements._libaio = "CONFIG_LIBAIO" in contents
78
ecd6d30f 79 contents, success = get_file("/proc/kallsyms")
fb551941
VF
80 if not success:
81 print("Unable to open '/proc/kallsyms' to probe for io_uring support")
82 else:
83 Requirements._io_uring = "io_uring_setup" in contents
84
85 Requirements._root = os.geteuid() == 0
86 if Requirements._zbd and Requirements._root:
87 try:
88 subprocess.run(["modprobe", "null_blk"],
89 stdout=subprocess.PIPE,
90 stderr=subprocess.PIPE)
91 if os.path.exists("/sys/module/null_blk/parameters/zoned"):
92 Requirements._zoned_nullb = True
93 except Exception:
94 pass
95
96 if platform.system() == "Windows":
97 utest_exe = "unittest.exe"
98 else:
99 utest_exe = "unittest"
100 unittest_path = os.path.join(fio_root, "unittests", utest_exe)
101 Requirements._unittests = os.path.exists(unittest_path)
102
103 Requirements._cpucount4 = multiprocessing.cpu_count() >= 4
104 Requirements._nvmecdev = args.nvmecdev
105
106 req_list = [
107 Requirements.linux,
108 Requirements.libaio,
109 Requirements.io_uring,
110 Requirements.zbd,
111 Requirements.root,
112 Requirements.zoned_nullb,
113 Requirements.not_macos,
114 Requirements.not_windows,
115 Requirements.unittests,
116 Requirements.cpucount4,
117 Requirements.nvmecdev,
118 ]
119 for req in req_list:
120 value, desc = req()
121 logging.debug("Requirements: Requirement '%s' met? %s", desc, value)
122
123 @classmethod
124 def linux(cls):
125 """Are we running on Linux?"""
126 return Requirements._linux, "Linux required"
127
128 @classmethod
129 def libaio(cls):
130 """Is libaio available?"""
131 return Requirements._libaio, "libaio required"
132
133 @classmethod
134 def io_uring(cls):
135 """Is io_uring available?"""
136 return Requirements._io_uring, "io_uring required"
137
138 @classmethod
139 def zbd(cls):
140 """Is ZBD support available?"""
141 return Requirements._zbd, "Zoned block device support required"
142
143 @classmethod
144 def root(cls):
145 """Are we running as root?"""
146 return Requirements._root, "root required"
147
148 @classmethod
149 def zoned_nullb(cls):
150 """Are zoned null block devices available?"""
151 return Requirements._zoned_nullb, "Zoned null block device support required"
152
153 @classmethod
154 def not_macos(cls):
155 """Are we running on a platform other than macOS?"""
156 return Requirements._not_macos, "platform other than macOS required"
157
158 @classmethod
159 def not_windows(cls):
160 """Are we running on a platform other than Windws?"""
161 return Requirements._not_windows, "platform other than Windows required"
162
163 @classmethod
164 def unittests(cls):
165 """Were unittests built?"""
166 return Requirements._unittests, "Unittests support required"
167
168 @classmethod
169 def cpucount4(cls):
170 """Do we have at least 4 CPUs?"""
171 return Requirements._cpucount4, "4+ CPUs required"
172
173 @classmethod
174 def nvmecdev(cls):
175 """Do we have an NVMe character device to test?"""
176 return Requirements._nvmecdev, "NVMe character device test target required"