Commit | Line | Data |
---|---|---|
df1eaa36 VF |
1 | #!/usr/bin/env python3 |
2 | # SPDX-License-Identifier: GPL-2.0-only | |
3 | # | |
4 | # Copyright (c) 2019 Western Digital Corporation or its affiliates. | |
5 | # | |
6 | """ | |
7 | # run-fio-tests.py | |
8 | # | |
9 | # Automate running of fio tests | |
10 | # | |
11 | # USAGE | |
12 | # python3 run-fio-tests.py [-r fio-root] [-f fio-path] [-a artifact-root] | |
13 | # [--skip # # #...] [--run-only # # #...] | |
14 | # | |
15 | # | |
16 | # EXAMPLE | |
b048455f | 17 | # # git clone git://git.kernel.dk/fio.git |
df1eaa36 VF |
18 | # # cd fio |
19 | # # make -j | |
20 | # # python3 t/run-fio-tests.py | |
21 | # | |
22 | # | |
23 | # REQUIREMENTS | |
b1bc705e | 24 | # - Python 3.5 (subprocess.run) |
df1eaa36 VF |
25 | # - Linux (libaio ioengine, zbd tests, etc) |
26 | # - The artifact directory must be on a file system that accepts 512-byte IO | |
27 | # (t0002, t0003, t0004). | |
28 | # - The artifact directory needs to be on an SSD. Otherwise tests that carry | |
29 | # out file-based IO will trigger a timeout (t0006). | |
30 | # - 4 CPUs (t0009) | |
31 | # - SciPy (steadystate_tests.py) | |
32 | # - libzbc (zbd tests) | |
33 | # - root privileges (zbd test) | |
34 | # - kernel 4.19 or later for zoned null block devices (zbd tests) | |
35 | # - CUnit support (unittests) | |
36 | # | |
37 | """ | |
38 | ||
39 | # | |
40 | # TODO run multiple tests simultaneously | |
41 | # TODO Add sgunmap tests (requires SAS SSD) | |
df1eaa36 VF |
42 | # |
43 | ||
44 | import os | |
45 | import sys | |
df1eaa36 | 46 | import time |
6d5470c3 | 47 | import shutil |
df1eaa36 VF |
48 | import logging |
49 | import argparse | |
df1eaa36 | 50 | from pathlib import Path |
888dbd62 | 51 | from statsmodels.sandbox.stats.runs import runstest_1samp |
0dc6e911 | 52 | from fiotestlib import FioExeTest, FioJobFileTest, run_fio_tests |
fb551941 | 53 | from fiotestcommon import * |
df1eaa36 VF |
54 | |
55 | ||
0dc6e911 | 56 | class FioJobFileTest_t0005(FioJobFileTest): |
df1eaa36 VF |
57 | """Test consists of fio test job t0005 |
58 | Confirm that read['io_kbytes'] == write['io_kbytes'] == 102400""" | |
59 | ||
60 | def check_result(self): | |
1b4ba547 | 61 | super().check_result() |
df1eaa36 VF |
62 | |
63 | if not self.passed: | |
64 | return | |
65 | ||
66 | if self.json_data['jobs'][0]['read']['io_kbytes'] != 102400: | |
1b4ba547 | 67 | self.failure_reason = f"{self.failure_reason} bytes read mismatch," |
df1eaa36 VF |
68 | self.passed = False |
69 | if self.json_data['jobs'][0]['write']['io_kbytes'] != 102400: | |
1b4ba547 | 70 | self.failure_reason = f"{self.failure_reason} bytes written mismatch," |
df1eaa36 VF |
71 | self.passed = False |
72 | ||
73 | ||
0dc6e911 | 74 | class FioJobFileTest_t0006(FioJobFileTest): |
df1eaa36 VF |
75 | """Test consists of fio test job t0006 |
76 | Confirm that read['io_kbytes'] ~ 2*write['io_kbytes']""" | |
77 | ||
78 | def check_result(self): | |
1b4ba547 | 79 | super().check_result() |
df1eaa36 VF |
80 | |
81 | if not self.passed: | |
82 | return | |
83 | ||
84 | ratio = self.json_data['jobs'][0]['read']['io_kbytes'] \ | |
85 | / self.json_data['jobs'][0]['write']['io_kbytes'] | |
704cc4df | 86 | logging.debug("Test %d: ratio: %f", self.testnum, ratio) |
df1eaa36 | 87 | if ratio < 1.99 or ratio > 2.01: |
1b4ba547 | 88 | self.failure_reason = f"{self.failure_reason} read/write ratio mismatch," |
df1eaa36 VF |
89 | self.passed = False |
90 | ||
91 | ||
0dc6e911 | 92 | class FioJobFileTest_t0007(FioJobFileTest): |
df1eaa36 VF |
93 | """Test consists of fio test job t0007 |
94 | Confirm that read['io_kbytes'] = 87040""" | |
95 | ||
96 | def check_result(self): | |
1b4ba547 | 97 | super().check_result() |
df1eaa36 VF |
98 | |
99 | if not self.passed: | |
100 | return | |
101 | ||
102 | if self.json_data['jobs'][0]['read']['io_kbytes'] != 87040: | |
1b4ba547 | 103 | self.failure_reason = f"{self.failure_reason} bytes read mismatch," |
df1eaa36 VF |
104 | self.passed = False |
105 | ||
106 | ||
0dc6e911 | 107 | class FioJobFileTest_t0008(FioJobFileTest): |
df1eaa36 VF |
108 | """Test consists of fio test job t0008 |
109 | Confirm that read['io_kbytes'] = 32768 and that | |
77c758db | 110 | write['io_kbytes'] ~ 16384 |
df1eaa36 | 111 | |
77c758db VF |
112 | This is a 50/50 seq read/write workload. Since fio flips a coin to |
113 | determine whether to issue a read or a write, total bytes written will not | |
114 | be exactly 16384K. But total bytes read will be exactly 32768K because | |
115 | reads will include the initial phase as well as the verify phase where all | |
116 | the blocks originally written will be read.""" | |
df1eaa36 VF |
117 | |
118 | def check_result(self): | |
1b4ba547 | 119 | super().check_result() |
df1eaa36 VF |
120 | |
121 | if not self.passed: | |
122 | return | |
123 | ||
77c758db | 124 | ratio = self.json_data['jobs'][0]['write']['io_kbytes'] / 16384 |
704cc4df | 125 | logging.debug("Test %d: ratio: %f", self.testnum, ratio) |
df1eaa36 | 126 | |
77c758db | 127 | if ratio < 0.97 or ratio > 1.03: |
1b4ba547 | 128 | self.failure_reason = f"{self.failure_reason} bytes written mismatch," |
df1eaa36 VF |
129 | self.passed = False |
130 | if self.json_data['jobs'][0]['read']['io_kbytes'] != 32768: | |
1b4ba547 | 131 | self.failure_reason = f"{self.failure_reason} bytes read mismatch," |
df1eaa36 VF |
132 | self.passed = False |
133 | ||
134 | ||
0dc6e911 | 135 | class FioJobFileTest_t0009(FioJobFileTest): |
df1eaa36 VF |
136 | """Test consists of fio test job t0009 |
137 | Confirm that runtime >= 60s""" | |
138 | ||
139 | def check_result(self): | |
1b4ba547 | 140 | super().check_result() |
df1eaa36 VF |
141 | |
142 | if not self.passed: | |
143 | return | |
144 | ||
704cc4df | 145 | logging.debug('Test %d: elapsed: %d', self.testnum, self.json_data['jobs'][0]['elapsed']) |
df1eaa36 VF |
146 | |
147 | if self.json_data['jobs'][0]['elapsed'] < 60: | |
1b4ba547 | 148 | self.failure_reason = f"{self.failure_reason} elapsed time mismatch," |
df1eaa36 VF |
149 | self.passed = False |
150 | ||
151 | ||
0dc6e911 | 152 | class FioJobFileTest_t0012(FioJobFileTest): |
d4e74fda DB |
153 | """Test consists of fio test job t0012 |
154 | Confirm ratios of job iops are 1:5:10 | |
155 | job1,job2,job3 respectively""" | |
156 | ||
157 | def check_result(self): | |
1b4ba547 | 158 | super().check_result() |
d4e74fda DB |
159 | |
160 | if not self.passed: | |
161 | return | |
162 | ||
163 | iops_files = [] | |
114eadb2 | 164 | for i in range(1, 4): |
68b3a741 | 165 | filename = os.path.join(self.paths['test_dir'], "{0}_iops.{1}.log".format(os.path.basename( |
114eadb2 | 166 | self.fio_job), i)) |
0f5234b4 VF |
167 | file_data = self.get_file_fail(filename) |
168 | if not file_data: | |
d4e74fda DB |
169 | return |
170 | ||
171 | iops_files.append(file_data.splitlines()) | |
172 | ||
173 | # there are 9 samples for job1 and job2, 4 samples for job3 | |
174 | iops1 = 0.0 | |
175 | iops2 = 0.0 | |
176 | iops3 = 0.0 | |
177 | for i in range(9): | |
178 | iops1 = iops1 + float(iops_files[0][i].split(',')[1]) | |
179 | iops2 = iops2 + float(iops_files[1][i].split(',')[1]) | |
180 | iops3 = iops3 + float(iops_files[2][i].split(',')[1]) | |
181 | ||
182 | ratio1 = iops3/iops2 | |
183 | ratio2 = iops3/iops1 | |
114eadb2 VF |
184 | logging.debug("sample {0}: job1 iops={1} job2 iops={2} job3 iops={3} " \ |
185 | "job3/job2={4:.3f} job3/job1={5:.3f}".format(i, iops1, iops2, iops3, ratio1, | |
186 | ratio2)) | |
d4e74fda DB |
187 | |
188 | # test job1 and job2 succeeded to recalibrate | |
189 | if ratio1 < 1 or ratio1 > 3 or ratio2 < 7 or ratio2 > 13: | |
114eadb2 VF |
190 | self.failure_reason += " iops ratio mismatch iops1={0} iops2={1} iops3={2} " \ |
191 | "expected r1~2 r2~10 got r1={3:.3f} r2={4:.3f},".format(iops1, iops2, iops3, | |
192 | ratio1, ratio2) | |
d4e74fda DB |
193 | self.passed = False |
194 | return | |
195 | ||
196 | ||
0dc6e911 | 197 | class FioJobFileTest_t0014(FioJobFileTest): |
d4e74fda DB |
198 | """Test consists of fio test job t0014 |
199 | Confirm that job1_iops / job2_iops ~ 1:2 for entire duration | |
200 | and that job1_iops / job3_iops ~ 1:3 for first half of duration. | |
201 | ||
202 | The test is about making sure the flow feature can | |
203 | re-calibrate the activity dynamically""" | |
204 | ||
205 | def check_result(self): | |
1b4ba547 | 206 | super().check_result() |
d4e74fda DB |
207 | |
208 | if not self.passed: | |
209 | return | |
210 | ||
211 | iops_files = [] | |
114eadb2 | 212 | for i in range(1, 4): |
68b3a741 | 213 | filename = os.path.join(self.paths['test_dir'], "{0}_iops.{1}.log".format(os.path.basename( |
114eadb2 | 214 | self.fio_job), i)) |
0f5234b4 VF |
215 | file_data = self.get_file_fail(filename) |
216 | if not file_data: | |
d4e74fda DB |
217 | return |
218 | ||
219 | iops_files.append(file_data.splitlines()) | |
220 | ||
221 | # there are 9 samples for job1 and job2, 4 samples for job3 | |
222 | iops1 = 0.0 | |
223 | iops2 = 0.0 | |
224 | iops3 = 0.0 | |
225 | for i in range(9): | |
226 | if i < 4: | |
227 | iops3 = iops3 + float(iops_files[2][i].split(',')[1]) | |
228 | elif i == 4: | |
229 | ratio1 = iops1 / iops2 | |
230 | ratio2 = iops1 / iops3 | |
231 | ||
232 | ||
233 | if ratio1 < 0.43 or ratio1 > 0.57 or ratio2 < 0.21 or ratio2 > 0.45: | |
114eadb2 VF |
234 | self.failure_reason += " iops ratio mismatch iops1={0} iops2={1} iops3={2} " \ |
235 | "expected r1~0.5 r2~0.33 got r1={3:.3f} r2={4:.3f},".format( | |
236 | iops1, iops2, iops3, ratio1, ratio2) | |
d4e74fda DB |
237 | self.passed = False |
238 | ||
239 | iops1 = iops1 + float(iops_files[0][i].split(',')[1]) | |
240 | iops2 = iops2 + float(iops_files[1][i].split(',')[1]) | |
241 | ||
242 | ratio1 = iops1/iops2 | |
243 | ratio2 = iops1/iops3 | |
114eadb2 VF |
244 | logging.debug("sample {0}: job1 iops={1} job2 iops={2} job3 iops={3} " \ |
245 | "job1/job2={4:.3f} job1/job3={5:.3f}".format(i, iops1, iops2, iops3, | |
246 | ratio1, ratio2)) | |
d4e74fda DB |
247 | |
248 | # test job1 and job2 succeeded to recalibrate | |
249 | if ratio1 < 0.43 or ratio1 > 0.57: | |
114eadb2 VF |
250 | self.failure_reason += " iops ratio mismatch iops1={0} iops2={1} expected ratio~0.5 " \ |
251 | "got ratio={2:.3f},".format(iops1, iops2, ratio1) | |
d4e74fda DB |
252 | self.passed = False |
253 | return | |
254 | ||
255 | ||
0dc6e911 | 256 | class FioJobFileTest_t0015(FioJobFileTest): |
de31fe9a | 257 | """Test consists of fio test jobs t0015 and t0016 |
60ebb939 VF |
258 | Confirm that mean(slat) + mean(clat) = mean(tlat)""" |
259 | ||
260 | def check_result(self): | |
1b4ba547 | 261 | super().check_result() |
60ebb939 VF |
262 | |
263 | if not self.passed: | |
264 | return | |
265 | ||
266 | slat = self.json_data['jobs'][0]['read']['slat_ns']['mean'] | |
267 | clat = self.json_data['jobs'][0]['read']['clat_ns']['mean'] | |
268 | tlat = self.json_data['jobs'][0]['read']['lat_ns']['mean'] | |
269 | logging.debug('Test %d: slat %f, clat %f, tlat %f', self.testnum, slat, clat, tlat) | |
270 | ||
271 | if abs(slat + clat - tlat) > 1: | |
272 | self.failure_reason = "{0} slat {1} + clat {2} = {3} != tlat {4},".format( | |
273 | self.failure_reason, slat, clat, slat+clat, tlat) | |
274 | self.passed = False | |
275 | ||
276 | ||
0dc6e911 | 277 | class FioJobFileTest_t0019(FioJobFileTest): |
ef54f290 VF |
278 | """Test consists of fio test job t0019 |
279 | Confirm that all offsets were touched sequentially""" | |
280 | ||
281 | def check_result(self): | |
1b4ba547 | 282 | super().check_result() |
ef54f290 | 283 | |
68b3a741 | 284 | bw_log_filename = os.path.join(self.paths['test_dir'], "test_bw.log") |
0f5234b4 VF |
285 | file_data = self.get_file_fail(bw_log_filename) |
286 | if not file_data: | |
114eadb2 VF |
287 | return |
288 | ||
ef54f290 VF |
289 | log_lines = file_data.split('\n') |
290 | ||
291 | prev = -4096 | |
292 | for line in log_lines: | |
293 | if len(line.strip()) == 0: | |
294 | continue | |
295 | cur = int(line.split(',')[4]) | |
296 | if cur - prev != 4096: | |
297 | self.passed = False | |
1b4ba547 | 298 | self.failure_reason = f"offsets {prev}, {cur} not sequential" |
ef54f290 VF |
299 | return |
300 | prev = cur | |
301 | ||
302 | if cur/4096 != 255: | |
303 | self.passed = False | |
1b4ba547 | 304 | self.failure_reason = f"unexpected last offset {cur}" |
ef54f290 VF |
305 | |
306 | ||
0dc6e911 | 307 | class FioJobFileTest_t0020(FioJobFileTest): |
eb40b275 | 308 | """Test consists of fio test jobs t0020 and t0021 |
ef54f290 VF |
309 | Confirm that almost all offsets were touched non-sequentially""" |
310 | ||
311 | def check_result(self): | |
1b4ba547 | 312 | super().check_result() |
ef54f290 | 313 | |
68b3a741 | 314 | bw_log_filename = os.path.join(self.paths['test_dir'], "test_bw.log") |
0f5234b4 VF |
315 | file_data = self.get_file_fail(bw_log_filename) |
316 | if not file_data: | |
114eadb2 VF |
317 | return |
318 | ||
ef54f290 VF |
319 | log_lines = file_data.split('\n') |
320 | ||
888dbd62 | 321 | offsets = [] |
ef54f290 VF |
322 | |
323 | prev = int(log_lines[0].split(',')[4]) | |
324 | for line in log_lines[1:]: | |
888dbd62 | 325 | offsets.append(prev/4096) |
ef54f290 VF |
326 | if len(line.strip()) == 0: |
327 | continue | |
328 | cur = int(line.split(',')[4]) | |
ef54f290 VF |
329 | prev = cur |
330 | ||
ef54f290 VF |
331 | if len(offsets) != 256: |
332 | self.passed = False | |
1b4ba547 | 333 | self.failure_reason += f" number of offsets is {len(offsets)} instead of 256" |
ef54f290 VF |
334 | |
335 | for i in range(256): | |
336 | if not i in offsets: | |
337 | self.passed = False | |
1b4ba547 | 338 | self.failure_reason += f" missing offset {i * 4096}" |
ef54f290 | 339 | |
1b4ba547 | 340 | (_, p) = runstest_1samp(list(offsets)) |
888dbd62 VF |
341 | if p < 0.05: |
342 | self.passed = False | |
343 | self.failure_reason += f" runs test failed with p = {p}" | |
344 | ||
ef54f290 | 345 | |
0dc6e911 | 346 | class FioJobFileTest_t0022(FioJobFileTest): |
eb40b275 VF |
347 | """Test consists of fio test job t0022""" |
348 | ||
349 | def check_result(self): | |
1b4ba547 | 350 | super().check_result() |
eb40b275 | 351 | |
68b3a741 | 352 | bw_log_filename = os.path.join(self.paths['test_dir'], "test_bw.log") |
0f5234b4 VF |
353 | file_data = self.get_file_fail(bw_log_filename) |
354 | if not file_data: | |
114eadb2 VF |
355 | return |
356 | ||
eb40b275 VF |
357 | log_lines = file_data.split('\n') |
358 | ||
359 | filesize = 1024*1024 | |
360 | bs = 4096 | |
361 | seq_count = 0 | |
362 | offsets = set() | |
363 | ||
364 | prev = int(log_lines[0].split(',')[4]) | |
365 | for line in log_lines[1:]: | |
366 | offsets.add(prev/bs) | |
367 | if len(line.strip()) == 0: | |
368 | continue | |
369 | cur = int(line.split(',')[4]) | |
370 | if cur - prev == bs: | |
371 | seq_count += 1 | |
372 | prev = cur | |
373 | ||
374 | # 10 is an arbitrary threshold | |
375 | if seq_count > 10: | |
376 | self.passed = False | |
1b4ba547 | 377 | self.failure_reason = f"too many ({seq_count}) consecutive offsets" |
eb40b275 VF |
378 | |
379 | if len(offsets) == filesize/bs: | |
380 | self.passed = False | |
114eadb2 | 381 | self.failure_reason += " no duplicate offsets found with norandommap=1" |
eb40b275 VF |
382 | |
383 | ||
0dc6e911 | 384 | class FioJobFileTest_t0023(FioJobFileTest): |
21a20229 | 385 | """Test consists of fio test job t0023 randtrimwrite test.""" |
c37183f8 | 386 | |
1fb78294 VF |
387 | def check_trimwrite(self, filename): |
388 | """Make sure that trims are followed by writes of the same size at the same offset.""" | |
389 | ||
68b3a741 | 390 | bw_log_filename = os.path.join(self.paths['test_dir'], filename) |
0f5234b4 VF |
391 | file_data = self.get_file_fail(bw_log_filename) |
392 | if not file_data: | |
114eadb2 VF |
393 | return |
394 | ||
c37183f8 VF |
395 | log_lines = file_data.split('\n') |
396 | ||
397 | prev_ddir = 1 | |
398 | for line in log_lines: | |
399 | if len(line.strip()) == 0: | |
400 | continue | |
401 | vals = line.split(',') | |
402 | ddir = int(vals[2]) | |
403 | bs = int(vals[3]) | |
404 | offset = int(vals[4]) | |
405 | if prev_ddir == 1: | |
406 | if ddir != 2: | |
407 | self.passed = False | |
21a20229 VF |
408 | self.failure_reason += " {0}: write not preceeded by trim: {1}".format( |
409 | bw_log_filename, line) | |
c37183f8 VF |
410 | break |
411 | else: | |
1b4ba547 | 412 | if ddir != 1: # pylint: disable=no-else-break |
c37183f8 | 413 | self.passed = False |
21a20229 VF |
414 | self.failure_reason += " {0}: trim not preceeded by write: {1}".format( |
415 | bw_log_filename, line) | |
c37183f8 VF |
416 | break |
417 | else: | |
418 | if prev_bs != bs: | |
419 | self.passed = False | |
21a20229 VF |
420 | self.failure_reason += " {0}: block size does not match: {1}".format( |
421 | bw_log_filename, line) | |
c37183f8 | 422 | break |
1b4ba547 | 423 | |
c37183f8 VF |
424 | if prev_offset != offset: |
425 | self.passed = False | |
21a20229 VF |
426 | self.failure_reason += " {0}: offset does not match: {1}".format( |
427 | bw_log_filename, line) | |
c37183f8 | 428 | break |
1b4ba547 | 429 | |
c37183f8 VF |
430 | prev_ddir = ddir |
431 | prev_bs = bs | |
432 | prev_offset = offset | |
433 | ||
434 | ||
9e83aa16 | 435 | def check_all_offsets(self, filename, sectorsize, filesize): |
21a20229 VF |
436 | """Make sure all offsets were touched.""" |
437 | ||
68b3a741 | 438 | file_data = self.get_file_fail(os.path.join(self.paths['test_dir'], filename)) |
0f5234b4 | 439 | if not file_data: |
9e83aa16 VF |
440 | return |
441 | ||
442 | log_lines = file_data.split('\n') | |
443 | ||
444 | offsets = set() | |
445 | ||
446 | for line in log_lines: | |
447 | if len(line.strip()) == 0: | |
448 | continue | |
449 | vals = line.split(',') | |
450 | bs = int(vals[3]) | |
451 | offset = int(vals[4]) | |
452 | if offset % sectorsize != 0: | |
453 | self.passed = False | |
21a20229 VF |
454 | self.failure_reason += " {0}: offset {1} not a multiple of sector size {2}".format( |
455 | filename, offset, sectorsize) | |
456 | break | |
9e83aa16 VF |
457 | if bs % sectorsize != 0: |
458 | self.passed = False | |
21a20229 VF |
459 | self.failure_reason += " {0}: block size {1} not a multiple of sector size " \ |
460 | "{2}".format(filename, bs, sectorsize) | |
461 | break | |
9e83aa16 VF |
462 | for i in range(int(bs/sectorsize)): |
463 | offsets.add(offset/sectorsize + i) | |
464 | ||
465 | if len(offsets) != filesize/sectorsize: | |
466 | self.passed = False | |
21a20229 VF |
467 | self.failure_reason += " {0}: only {1} offsets touched; expected {2}".format( |
468 | filename, len(offsets), filesize/sectorsize) | |
9e83aa16 | 469 | else: |
21a20229 | 470 | logging.debug("%s: %d sectors touched", filename, len(offsets)) |
9e83aa16 VF |
471 | |
472 | ||
c37183f8 | 473 | def check_result(self): |
1b4ba547 | 474 | super().check_result() |
c37183f8 | 475 | |
9e83aa16 VF |
476 | filesize = 1024*1024 |
477 | ||
1fb78294 VF |
478 | self.check_trimwrite("basic_bw.log") |
479 | self.check_trimwrite("bs_bw.log") | |
480 | self.check_trimwrite("bsrange_bw.log") | |
481 | self.check_trimwrite("bssplit_bw.log") | |
482 | self.check_trimwrite("basic_no_rm_bw.log") | |
483 | self.check_trimwrite("bs_no_rm_bw.log") | |
484 | self.check_trimwrite("bsrange_no_rm_bw.log") | |
485 | self.check_trimwrite("bssplit_no_rm_bw.log") | |
c37183f8 | 486 | |
9e83aa16 VF |
487 | self.check_all_offsets("basic_bw.log", 4096, filesize) |
488 | self.check_all_offsets("bs_bw.log", 8192, filesize) | |
489 | self.check_all_offsets("bsrange_bw.log", 512, filesize) | |
490 | self.check_all_offsets("bssplit_bw.log", 512, filesize) | |
c37183f8 VF |
491 | |
492 | ||
0dc6e911 | 493 | class FioJobFileTest_t0024(FioJobFileTest_t0023): |
2d5c4600 VF |
494 | """Test consists of fio test job t0024 trimwrite test.""" |
495 | ||
496 | def check_result(self): | |
0dc6e911 VF |
497 | # call FioJobFileTest_t0023's parent to skip checks done by t0023 |
498 | super(FioJobFileTest_t0023, self).check_result() | |
2d5c4600 VF |
499 | |
500 | filesize = 1024*1024 | |
501 | ||
502 | self.check_trimwrite("basic_bw.log") | |
503 | self.check_trimwrite("bs_bw.log") | |
504 | self.check_trimwrite("bsrange_bw.log") | |
505 | self.check_trimwrite("bssplit_bw.log") | |
506 | ||
507 | self.check_all_offsets("basic_bw.log", 4096, filesize) | |
508 | self.check_all_offsets("bs_bw.log", 8192, filesize) | |
509 | self.check_all_offsets("bsrange_bw.log", 512, filesize) | |
510 | self.check_all_offsets("bssplit_bw.log", 512, filesize) | |
511 | ||
512 | ||
0dc6e911 | 513 | class FioJobFileTest_t0025(FioJobFileTest): |
d661fb18 SK |
514 | """Test experimental verify read backs written data pattern.""" |
515 | def check_result(self): | |
1b4ba547 | 516 | super().check_result() |
d661fb18 SK |
517 | |
518 | if not self.passed: | |
519 | return | |
520 | ||
521 | if self.json_data['jobs'][0]['read']['io_kbytes'] != 128: | |
522 | self.passed = False | |
523 | ||
0dc6e911 | 524 | class FioJobFileTest_t0027(FioJobFileTest): |
ede04c27 | 525 | def setup(self, *args, **kws): |
1b4ba547 | 526 | super().setup(*args, **kws) |
68b3a741 VF |
527 | self.pattern_file = os.path.join(self.paths['test_dir'], "t0027.pattern") |
528 | self.output_file = os.path.join(self.paths['test_dir'], "t0027file") | |
ede04c27 LG |
529 | self.pattern = os.urandom(16 << 10) |
530 | with open(self.pattern_file, "wb") as f: | |
531 | f.write(self.pattern) | |
532 | ||
533 | def check_result(self): | |
1b4ba547 | 534 | super().check_result() |
ede04c27 LG |
535 | |
536 | if not self.passed: | |
537 | return | |
538 | ||
539 | with open(self.output_file, "rb") as f: | |
540 | data = f.read() | |
541 | ||
542 | if data != self.pattern: | |
543 | self.passed = False | |
d661fb18 | 544 | |
0dc6e911 | 545 | class FioJobFileTest_iops_rate(FioJobFileTest): |
12b609b5 | 546 | """Test consists of fio test job t0011 |
df1eaa36 VF |
547 | Confirm that job0 iops == 1000 |
548 | and that job1_iops / job0_iops ~ 8 | |
549 | With two runs of fio-3.16 I observed a ratio of 8.3""" | |
550 | ||
551 | def check_result(self): | |
1b4ba547 | 552 | super().check_result() |
df1eaa36 VF |
553 | |
554 | if not self.passed: | |
555 | return | |
556 | ||
557 | iops1 = self.json_data['jobs'][0]['read']['iops'] | |
7ddc4ed1 | 558 | logging.debug("Test %d: iops1: %f", self.testnum, iops1) |
df1eaa36 | 559 | iops2 = self.json_data['jobs'][1]['read']['iops'] |
7ddc4ed1 | 560 | logging.debug("Test %d: iops2: %f", self.testnum, iops2) |
df1eaa36 | 561 | ratio = iops2 / iops1 |
704cc4df | 562 | logging.debug("Test %d: ratio: %f", self.testnum, ratio) |
df1eaa36 | 563 | |
0a9b8988 | 564 | if iops1 < 950 or iops1 > 1050: |
1b4ba547 | 565 | self.failure_reason = f"{self.failure_reason} iops value mismatch," |
df1eaa36 VF |
566 | self.passed = False |
567 | ||
d4e74fda | 568 | if ratio < 6 or ratio > 10: |
1b4ba547 | 569 | self.failure_reason = f"{self.failure_reason} iops ratio mismatch," |
df1eaa36 VF |
570 | self.passed = False |
571 | ||
572 | ||
df1eaa36 | 573 | TEST_LIST = [ |
704cc4df VF |
574 | { |
575 | 'test_id': 1, | |
0dc6e911 | 576 | 'test_class': FioJobFileTest, |
704cc4df VF |
577 | 'job': 't0001-52c58027.fio', |
578 | 'success': SUCCESS_DEFAULT, | |
579 | 'pre_job': None, | |
580 | 'pre_success': None, | |
581 | 'requirements': [], | |
582 | }, | |
583 | { | |
584 | 'test_id': 2, | |
0dc6e911 | 585 | 'test_class': FioJobFileTest, |
704cc4df VF |
586 | 'job': 't0002-13af05ae-post.fio', |
587 | 'success': SUCCESS_DEFAULT, | |
588 | 'pre_job': 't0002-13af05ae-pre.fio', | |
589 | 'pre_success': None, | |
590 | 'requirements': [Requirements.linux, Requirements.libaio], | |
591 | }, | |
592 | { | |
593 | 'test_id': 3, | |
0dc6e911 | 594 | 'test_class': FioJobFileTest, |
704cc4df VF |
595 | 'job': 't0003-0ae2c6e1-post.fio', |
596 | 'success': SUCCESS_NONZERO, | |
597 | 'pre_job': 't0003-0ae2c6e1-pre.fio', | |
598 | 'pre_success': SUCCESS_DEFAULT, | |
599 | 'requirements': [Requirements.linux, Requirements.libaio], | |
600 | }, | |
601 | { | |
602 | 'test_id': 4, | |
0dc6e911 | 603 | 'test_class': FioJobFileTest, |
704cc4df VF |
604 | 'job': 't0004-8a99fdf6.fio', |
605 | 'success': SUCCESS_DEFAULT, | |
606 | 'pre_job': None, | |
607 | 'pre_success': None, | |
608 | 'requirements': [Requirements.linux, Requirements.libaio], | |
609 | }, | |
610 | { | |
611 | 'test_id': 5, | |
0dc6e911 | 612 | 'test_class': FioJobFileTest_t0005, |
704cc4df VF |
613 | 'job': 't0005-f7078f7b.fio', |
614 | 'success': SUCCESS_DEFAULT, | |
615 | 'pre_job': None, | |
616 | 'pre_success': None, | |
617 | 'output_format': 'json', | |
618 | 'requirements': [Requirements.not_windows], | |
619 | }, | |
620 | { | |
621 | 'test_id': 6, | |
0dc6e911 | 622 | 'test_class': FioJobFileTest_t0006, |
704cc4df VF |
623 | 'job': 't0006-82af2a7c.fio', |
624 | 'success': SUCCESS_DEFAULT, | |
625 | 'pre_job': None, | |
626 | 'pre_success': None, | |
627 | 'output_format': 'json', | |
628 | 'requirements': [Requirements.linux, Requirements.libaio], | |
629 | }, | |
630 | { | |
631 | 'test_id': 7, | |
0dc6e911 | 632 | 'test_class': FioJobFileTest_t0007, |
704cc4df VF |
633 | 'job': 't0007-37cf9e3c.fio', |
634 | 'success': SUCCESS_DEFAULT, | |
635 | 'pre_job': None, | |
636 | 'pre_success': None, | |
637 | 'output_format': 'json', | |
638 | 'requirements': [], | |
639 | }, | |
640 | { | |
641 | 'test_id': 8, | |
0dc6e911 | 642 | 'test_class': FioJobFileTest_t0008, |
704cc4df VF |
643 | 'job': 't0008-ae2fafc8.fio', |
644 | 'success': SUCCESS_DEFAULT, | |
645 | 'pre_job': None, | |
646 | 'pre_success': None, | |
647 | 'output_format': 'json', | |
648 | 'requirements': [], | |
649 | }, | |
650 | { | |
651 | 'test_id': 9, | |
0dc6e911 | 652 | 'test_class': FioJobFileTest_t0009, |
704cc4df VF |
653 | 'job': 't0009-f8b0bd10.fio', |
654 | 'success': SUCCESS_DEFAULT, | |
655 | 'pre_job': None, | |
656 | 'pre_success': None, | |
657 | 'output_format': 'json', | |
658 | 'requirements': [Requirements.not_macos, | |
659 | Requirements.cpucount4], | |
660 | # mac os does not support CPU affinity | |
661 | }, | |
662 | { | |
663 | 'test_id': 10, | |
0dc6e911 | 664 | 'test_class': FioJobFileTest, |
704cc4df VF |
665 | 'job': 't0010-b7aae4ba.fio', |
666 | 'success': SUCCESS_DEFAULT, | |
667 | 'pre_job': None, | |
668 | 'pre_success': None, | |
669 | 'requirements': [], | |
670 | }, | |
671 | { | |
672 | 'test_id': 11, | |
0dc6e911 | 673 | 'test_class': FioJobFileTest_iops_rate, |
704cc4df VF |
674 | 'job': 't0011-5d2788d5.fio', |
675 | 'success': SUCCESS_DEFAULT, | |
676 | 'pre_job': None, | |
677 | 'pre_success': None, | |
678 | 'output_format': 'json', | |
679 | 'requirements': [], | |
680 | }, | |
0a602473 BVA |
681 | { |
682 | 'test_id': 12, | |
0dc6e911 | 683 | 'test_class': FioJobFileTest_t0012, |
0a602473 BVA |
684 | 'job': 't0012.fio', |
685 | 'success': SUCCESS_DEFAULT, | |
686 | 'pre_job': None, | |
687 | 'pre_success': None, | |
688 | 'output_format': 'json', | |
d4e74fda | 689 | 'requirements': [], |
0a602473 | 690 | }, |
f0c7ae7a BVA |
691 | { |
692 | 'test_id': 13, | |
0dc6e911 | 693 | 'test_class': FioJobFileTest, |
f0c7ae7a BVA |
694 | 'job': 't0013.fio', |
695 | 'success': SUCCESS_DEFAULT, | |
696 | 'pre_job': None, | |
697 | 'pre_success': None, | |
698 | 'output_format': 'json', | |
699 | 'requirements': [], | |
700 | }, | |
d4e74fda DB |
701 | { |
702 | 'test_id': 14, | |
0dc6e911 | 703 | 'test_class': FioJobFileTest_t0014, |
d4e74fda DB |
704 | 'job': 't0014.fio', |
705 | 'success': SUCCESS_DEFAULT, | |
706 | 'pre_job': None, | |
707 | 'pre_success': None, | |
708 | 'output_format': 'json', | |
709 | 'requirements': [], | |
710 | }, | |
60ebb939 VF |
711 | { |
712 | 'test_id': 15, | |
0dc6e911 | 713 | 'test_class': FioJobFileTest_t0015, |
60ebb939 VF |
714 | 'job': 't0015-e78980ff.fio', |
715 | 'success': SUCCESS_DEFAULT, | |
716 | 'pre_job': None, | |
717 | 'pre_success': None, | |
718 | 'output_format': 'json', | |
719 | 'requirements': [Requirements.linux, Requirements.libaio], | |
720 | }, | |
de31fe9a VF |
721 | { |
722 | 'test_id': 16, | |
0dc6e911 | 723 | 'test_class': FioJobFileTest_t0015, |
f045d5f8 | 724 | 'job': 't0016-d54ae22.fio', |
de31fe9a VF |
725 | 'success': SUCCESS_DEFAULT, |
726 | 'pre_job': None, | |
727 | 'pre_success': None, | |
728 | 'output_format': 'json', | |
729 | 'requirements': [], | |
730 | }, | |
31a58cba VF |
731 | { |
732 | 'test_id': 17, | |
0dc6e911 | 733 | 'test_class': FioJobFileTest_t0015, |
31a58cba VF |
734 | 'job': 't0017.fio', |
735 | 'success': SUCCESS_DEFAULT, | |
736 | 'pre_job': None, | |
737 | 'pre_success': None, | |
738 | 'output_format': 'json', | |
739 | 'requirements': [Requirements.not_windows], | |
740 | }, | |
a2947c33 VF |
741 | { |
742 | 'test_id': 18, | |
0dc6e911 | 743 | 'test_class': FioJobFileTest, |
a2947c33 VF |
744 | 'job': 't0018.fio', |
745 | 'success': SUCCESS_DEFAULT, | |
746 | 'pre_job': None, | |
747 | 'pre_success': None, | |
748 | 'requirements': [Requirements.linux, Requirements.io_uring], | |
749 | }, | |
ef54f290 VF |
750 | { |
751 | 'test_id': 19, | |
0dc6e911 | 752 | 'test_class': FioJobFileTest_t0019, |
ef54f290 VF |
753 | 'job': 't0019.fio', |
754 | 'success': SUCCESS_DEFAULT, | |
755 | 'pre_job': None, | |
756 | 'pre_success': None, | |
757 | 'requirements': [], | |
758 | }, | |
759 | { | |
760 | 'test_id': 20, | |
0dc6e911 | 761 | 'test_class': FioJobFileTest_t0020, |
ef54f290 VF |
762 | 'job': 't0020.fio', |
763 | 'success': SUCCESS_DEFAULT, | |
764 | 'pre_job': None, | |
765 | 'pre_success': None, | |
766 | 'requirements': [], | |
767 | }, | |
eb40b275 VF |
768 | { |
769 | 'test_id': 21, | |
0dc6e911 | 770 | 'test_class': FioJobFileTest_t0020, |
eb40b275 VF |
771 | 'job': 't0021.fio', |
772 | 'success': SUCCESS_DEFAULT, | |
773 | 'pre_job': None, | |
774 | 'pre_success': None, | |
775 | 'requirements': [], | |
776 | }, | |
777 | { | |
778 | 'test_id': 22, | |
0dc6e911 | 779 | 'test_class': FioJobFileTest_t0022, |
eb40b275 VF |
780 | 'job': 't0022.fio', |
781 | 'success': SUCCESS_DEFAULT, | |
782 | 'pre_job': None, | |
783 | 'pre_success': None, | |
784 | 'requirements': [], | |
785 | }, | |
c37183f8 VF |
786 | { |
787 | 'test_id': 23, | |
0dc6e911 | 788 | 'test_class': FioJobFileTest_t0023, |
c37183f8 VF |
789 | 'job': 't0023.fio', |
790 | 'success': SUCCESS_DEFAULT, | |
791 | 'pre_job': None, | |
792 | 'pre_success': None, | |
793 | 'requirements': [], | |
794 | }, | |
2d5c4600 VF |
795 | { |
796 | 'test_id': 24, | |
0dc6e911 | 797 | 'test_class': FioJobFileTest_t0024, |
2d5c4600 VF |
798 | 'job': 't0024.fio', |
799 | 'success': SUCCESS_DEFAULT, | |
800 | 'pre_job': None, | |
801 | 'pre_success': None, | |
802 | 'requirements': [], | |
803 | }, | |
d661fb18 SK |
804 | { |
805 | 'test_id': 25, | |
0dc6e911 | 806 | 'test_class': FioJobFileTest_t0025, |
d661fb18 SK |
807 | 'job': 't0025.fio', |
808 | 'success': SUCCESS_DEFAULT, | |
809 | 'pre_job': None, | |
810 | 'pre_success': None, | |
811 | 'output_format': 'json', | |
812 | 'requirements': [], | |
813 | }, | |
c4704c08 SK |
814 | { |
815 | 'test_id': 26, | |
0dc6e911 | 816 | 'test_class': FioJobFileTest, |
c4704c08 SK |
817 | 'job': 't0026.fio', |
818 | 'success': SUCCESS_DEFAULT, | |
819 | 'pre_job': None, | |
820 | 'pre_success': None, | |
821 | 'requirements': [Requirements.not_windows], | |
822 | }, | |
ede04c27 LG |
823 | { |
824 | 'test_id': 27, | |
0dc6e911 | 825 | 'test_class': FioJobFileTest_t0027, |
ede04c27 LG |
826 | 'job': 't0027.fio', |
827 | 'success': SUCCESS_DEFAULT, | |
828 | 'pre_job': None, | |
829 | 'pre_success': None, | |
830 | 'requirements': [], | |
831 | }, | |
23fb1642 VF |
832 | { |
833 | 'test_id': 28, | |
0dc6e911 | 834 | 'test_class': FioJobFileTest, |
23fb1642 VF |
835 | 'job': 't0028-c6cade16.fio', |
836 | 'success': SUCCESS_DEFAULT, | |
837 | 'pre_job': None, | |
838 | 'pre_success': None, | |
839 | 'requirements': [], | |
840 | }, | |
704cc4df VF |
841 | { |
842 | 'test_id': 1000, | |
843 | 'test_class': FioExeTest, | |
844 | 'exe': 't/axmap', | |
845 | 'parameters': None, | |
846 | 'success': SUCCESS_DEFAULT, | |
847 | 'requirements': [], | |
848 | }, | |
849 | { | |
850 | 'test_id': 1001, | |
851 | 'test_class': FioExeTest, | |
852 | 'exe': 't/ieee754', | |
853 | 'parameters': None, | |
854 | 'success': SUCCESS_DEFAULT, | |
855 | 'requirements': [], | |
856 | }, | |
857 | { | |
858 | 'test_id': 1002, | |
859 | 'test_class': FioExeTest, | |
860 | 'exe': 't/lfsr-test', | |
861 | 'parameters': ['0xFFFFFF', '0', '0', 'verify'], | |
862 | 'success': SUCCESS_STDERR, | |
863 | 'requirements': [], | |
864 | }, | |
865 | { | |
866 | 'test_id': 1003, | |
867 | 'test_class': FioExeTest, | |
868 | 'exe': 't/readonly.py', | |
869 | 'parameters': ['-f', '{fio_path}'], | |
870 | 'success': SUCCESS_DEFAULT, | |
871 | 'requirements': [], | |
872 | }, | |
873 | { | |
874 | 'test_id': 1004, | |
875 | 'test_class': FioExeTest, | |
876 | 'exe': 't/steadystate_tests.py', | |
877 | 'parameters': ['{fio_path}'], | |
878 | 'success': SUCCESS_DEFAULT, | |
879 | 'requirements': [], | |
880 | }, | |
881 | { | |
882 | 'test_id': 1005, | |
883 | 'test_class': FioExeTest, | |
884 | 'exe': 't/stest', | |
885 | 'parameters': None, | |
886 | 'success': SUCCESS_STDERR, | |
887 | 'requirements': [], | |
888 | }, | |
889 | { | |
890 | 'test_id': 1006, | |
891 | 'test_class': FioExeTest, | |
892 | 'exe': 't/strided.py', | |
5a36d0e4 | 893 | 'parameters': ['--fio', '{fio_path}'], |
704cc4df VF |
894 | 'success': SUCCESS_DEFAULT, |
895 | 'requirements': [], | |
896 | }, | |
897 | { | |
898 | 'test_id': 1007, | |
899 | 'test_class': FioExeTest, | |
037b2b50 DF |
900 | 'exe': 't/zbd/run-tests-against-nullb', |
901 | 'parameters': ['-s', '1'], | |
704cc4df VF |
902 | 'success': SUCCESS_DEFAULT, |
903 | 'requirements': [Requirements.linux, Requirements.zbd, | |
904 | Requirements.root], | |
905 | }, | |
906 | { | |
907 | 'test_id': 1008, | |
908 | 'test_class': FioExeTest, | |
037b2b50 DF |
909 | 'exe': 't/zbd/run-tests-against-nullb', |
910 | 'parameters': ['-s', '2'], | |
704cc4df VF |
911 | 'success': SUCCESS_DEFAULT, |
912 | 'requirements': [Requirements.linux, Requirements.zbd, | |
913 | Requirements.root, Requirements.zoned_nullb], | |
914 | }, | |
915 | { | |
916 | 'test_id': 1009, | |
917 | 'test_class': FioExeTest, | |
918 | 'exe': 'unittests/unittest', | |
919 | 'parameters': None, | |
920 | 'success': SUCCESS_DEFAULT, | |
921 | 'requirements': [Requirements.unittests], | |
922 | }, | |
923 | { | |
924 | 'test_id': 1010, | |
925 | 'test_class': FioExeTest, | |
926 | 'exe': 't/latency_percentiles.py', | |
927 | 'parameters': ['-f', '{fio_path}'], | |
928 | 'success': SUCCESS_DEFAULT, | |
929 | 'requirements': [], | |
930 | }, | |
8403eca6 VF |
931 | { |
932 | 'test_id': 1011, | |
933 | 'test_class': FioExeTest, | |
934 | 'exe': 't/jsonplus2csv_test.py', | |
935 | 'parameters': ['-f', '{fio_path}'], | |
936 | 'success': SUCCESS_DEFAULT, | |
937 | 'requirements': [], | |
938 | }, | |
03900b0b | 939 | { |
940 | 'test_id': 1012, | |
941 | 'test_class': FioExeTest, | |
942 | 'exe': 't/log_compression.py', | |
943 | 'parameters': ['-f', '{fio_path}'], | |
944 | 'success': SUCCESS_DEFAULT, | |
945 | 'requirements': [], | |
946 | }, | |
c994fa62 VF |
947 | { |
948 | 'test_id': 1013, | |
949 | 'test_class': FioExeTest, | |
950 | 'exe': 't/random_seed.py', | |
951 | 'parameters': ['-f', '{fio_path}'], | |
952 | 'success': SUCCESS_DEFAULT, | |
953 | 'requirements': [], | |
954 | }, | |
2128f93a VF |
955 | { |
956 | 'test_id': 1014, | |
957 | 'test_class': FioExeTest, | |
958 | 'exe': 't/nvmept.py', | |
959 | 'parameters': ['-f', '{fio_path}', '--dut', '{nvmecdev}'], | |
960 | 'success': SUCCESS_DEFAULT, | |
961 | 'requirements': [Requirements.linux, Requirements.nvmecdev], | |
962 | }, | |
df1eaa36 VF |
963 | ] |
964 | ||
965 | ||
966 | def parse_args(): | |
704cc4df VF |
967 | """Parse command-line arguments.""" |
968 | ||
df1eaa36 VF |
969 | parser = argparse.ArgumentParser() |
970 | parser.add_argument('-r', '--fio-root', | |
971 | help='fio root path') | |
972 | parser.add_argument('-f', '--fio', | |
973 | help='path to fio executable (e.g., ./fio)') | |
974 | parser.add_argument('-a', '--artifact-root', | |
975 | help='artifact root directory') | |
976 | parser.add_argument('-s', '--skip', nargs='+', type=int, | |
977 | help='list of test(s) to skip') | |
978 | parser.add_argument('-o', '--run-only', nargs='+', type=int, | |
979 | help='list of test(s) to run, skipping all others') | |
6d5470c3 VF |
980 | parser.add_argument('-d', '--debug', action='store_true', |
981 | help='provide debug output') | |
b1bc705e VF |
982 | parser.add_argument('-k', '--skip-req', action='store_true', |
983 | help='skip requirements checking') | |
58a77d2a VF |
984 | parser.add_argument('-p', '--pass-through', action='append', |
985 | help='pass-through an argument to an executable test') | |
2128f93a VF |
986 | parser.add_argument('--nvmecdev', action='store', default=None, |
987 | help='NVMe character device for **DESTRUCTIVE** testing (e.g., /dev/ng0n1)') | |
df1eaa36 VF |
988 | args = parser.parse_args() |
989 | ||
990 | return args | |
991 | ||
992 | ||
993 | def main(): | |
704cc4df VF |
994 | """Entry point.""" |
995 | ||
df1eaa36 | 996 | args = parse_args() |
6d5470c3 VF |
997 | if args.debug: |
998 | logging.basicConfig(level=logging.DEBUG) | |
999 | else: | |
1000 | logging.basicConfig(level=logging.INFO) | |
1001 | ||
58a77d2a VF |
1002 | pass_through = {} |
1003 | if args.pass_through: | |
1004 | for arg in args.pass_through: | |
1005 | if not ':' in arg: | |
1b4ba547 | 1006 | print(f"Invalid --pass-through argument '{arg}'") |
58a77d2a VF |
1007 | print("Syntax for --pass-through is TESTNUMBER:ARGUMENT") |
1008 | return | |
061a0773 | 1009 | split = arg.split(":", 1) |
58a77d2a | 1010 | pass_through[int(split[0])] = split[1] |
061a0773 | 1011 | logging.debug("Pass-through arguments: %s", pass_through) |
58a77d2a | 1012 | |
df1eaa36 VF |
1013 | if args.fio_root: |
1014 | fio_root = args.fio_root | |
1015 | else: | |
6d5470c3 | 1016 | fio_root = str(Path(__file__).absolute().parent.parent) |
1b4ba547 | 1017 | print(f"fio root is {fio_root}") |
df1eaa36 VF |
1018 | |
1019 | if args.fio: | |
1020 | fio_path = args.fio | |
1021 | else: | |
742b8799 VF |
1022 | if platform.system() == "Windows": |
1023 | fio_exe = "fio.exe" | |
1024 | else: | |
1025 | fio_exe = "fio" | |
1026 | fio_path = os.path.join(fio_root, fio_exe) | |
1b4ba547 | 1027 | print(f"fio path is {fio_path}") |
6d5470c3 VF |
1028 | if not shutil.which(fio_path): |
1029 | print("Warning: fio executable not found") | |
df1eaa36 VF |
1030 | |
1031 | artifact_root = args.artifact_root if args.artifact_root else \ | |
1b4ba547 | 1032 | f"fio-test-{time.strftime('%Y%m%d-%H%M%S')}" |
df1eaa36 | 1033 | os.mkdir(artifact_root) |
1b4ba547 | 1034 | print(f"Artifact directory is {artifact_root}") |
df1eaa36 | 1035 | |
b1bc705e | 1036 | if not args.skip_req: |
fb551941 VF |
1037 | Requirements(fio_root, args) |
1038 | ||
1039 | test_env = { | |
1040 | 'fio_path': fio_path, | |
1041 | 'fio_root': fio_root, | |
1042 | 'artifact_root': artifact_root, | |
1043 | 'pass_through': pass_through, | |
1044 | } | |
1045 | _, failed, _ = run_fio_tests(TEST_LIST, test_env, args) | |
df1eaa36 VF |
1046 | sys.exit(failed) |
1047 | ||
1048 | ||
1049 | if __name__ == '__main__': | |
1050 | main() |