class FioTest():
"""Base for all fio tests."""
- def __init__(self, exe_path, parameters, success):
- self.exe_path = exe_path
- self.parameters = parameters
+ def __init__(self, exe_path, success):
+ self.paths = {'exe': exe_path}
self.success = success
self.output = {}
- self.artifact_root = None
self.testnum = None
- self.test_dir = None
self.passed = True
self.failure_reason = ''
- self.command_file = None
- self.stdout_file = None
- self.stderr_file = None
- self.exitcode_file = None
+ self.filenames = {}
+ self.parameters = None
- def setup(self, artifact_root, testnum):
+ def setup(self, artifact_root, testnum, parameters):
"""Setup instance variables for test."""
- self.artifact_root = artifact_root
self.testnum = testnum
- self.test_dir = os.path.join(artifact_root, f"{testnum:04d}")
- if not os.path.exists(self.test_dir):
- os.mkdir(self.test_dir)
-
- self.command_file = os.path.join( self.test_dir,
- f"{os.path.basename(self.exe_path)}.command")
- self.stdout_file = os.path.join( self.test_dir,
- f"{os.path.basename(self.exe_path)}.stdout")
- self.stderr_file = os.path.join( self.test_dir,
- f"{os.path.basename(self.exe_path)}.stderr")
- self.exitcode_file = os.path.join( self.test_dir,
- f"{os.path.basename(self.exe_path)}.exitcode")
+ self.parameters = parameters
+ self.paths['artifacts'] = artifact_root
+ self.paths['test_dir'] = os.path.join(artifact_root, f"{testnum:04d}")
+ if not os.path.exists(self.paths['test_dir']):
+ os.mkdir(self.paths['test_dir'])
+
+ self.filenames['cmd'] = os.path.join(self.paths['test_dir'],
+ f"{os.path.basename(self.paths['exe'])}.command")
+ self.filenames['stdout'] = os.path.join(self.paths['test_dir'],
+ f"{os.path.basename(self.paths['exe'])}.stdout")
+ self.filenames['stderr'] = os.path.join(self.paths['test_dir'],
+ f"{os.path.basename(self.paths['exe'])}.stderr")
+ self.filenames['exitcode'] = os.path.join(self.paths['test_dir'],
+ f"{os.path.basename(self.paths['exe'])}.exitcode")
def run(self):
"""Run the test."""
class FioExeTest(FioTest):
"""Test consists of an executable binary or script"""
- def __init__(self, exe_path, parameters, success):
+ def __init__(self, exe_path, success):
"""Construct a FioExeTest which is a FioTest consisting of an
executable binary or script.
exe_path: location of executable binary or script
- parameters: list of parameters for executable
success: Definition of test success
"""
- FioTest.__init__(self, exe_path, parameters, success)
+ FioTest.__init__(self, exe_path, success)
def run(self):
"""Execute the binary or script described by this instance."""
- command = [self.exe_path] + self.parameters
- command_file = open(self.command_file, "w+",
+ command = [self.paths['exe']] + self.parameters
+ command_file = open(self.filenames['cmd'], "w+",
encoding=locale.getpreferredencoding())
command_file.write(f"{command}\n")
command_file.close()
- stdout_file = open(self.stdout_file, "w+",
+ stdout_file = open(self.filenames['stdout'], "w+",
encoding=locale.getpreferredencoding())
- stderr_file = open(self.stderr_file, "w+",
+ stderr_file = open(self.filenames['stderr'], "w+",
encoding=locale.getpreferredencoding())
- exitcode_file = open(self.exitcode_file, "w+",
+ exitcode_file = open(self.filenames['exitcode'], "w+",
encoding=locale.getpreferredencoding())
try:
proc = None
proc = subprocess.Popen(command,
stdout=stdout_file,
stderr=stderr_file,
- cwd=self.test_dir,
+ cwd=self.paths['test_dir'],
universal_newlines=True)
proc.communicate(timeout=self.success['timeout'])
exitcode_file.write(f'{proc.returncode}\n')
self.failure_reason = f"{self.failure_reason} zero return code,"
self.passed = False
- stderr_size = os.path.getsize(self.stderr_file)
+ stderr_size = os.path.getsize(self.filenames['stderr'])
if 'stderr_empty' in self.success:
if self.success['stderr_empty']:
if stderr_size != 0:
class FioJobFileTest(FioExeTest):
- """Test consists of a fio job"""
+ """Test consists of a fio job with options in a job file."""
def __init__(self, fio_path, fio_job, success, fio_pre_job=None,
fio_pre_success=None, output_format="normal"):
self.output_format = output_format
self.precon_failed = False
self.json_data = None
- self.fio_output = f"{os.path.basename(self.fio_job)}.output"
- self.fio_args = [
+
+ FioExeTest.__init__(self, fio_path, success)
+
+ def setup(self, artifact_root, testnum, parameters=None):
+ """Setup instance variables for fio job test."""
+
+ self.filenames['fio_output'] = f"{os.path.basename(self.fio_job)}.output"
+ fio_args = [
"--max-jobs=16",
f"--output-format={self.output_format}",
- f"--output={self.fio_output}",
+ f"--output={self.filenames['fio_output']}",
self.fio_job,
]
- FioExeTest.__init__(self, fio_path, self.fio_args, success)
-
- def setup(self, artifact_root, testnum):
- """Setup instance variables for fio job test."""
- super().setup(artifact_root, testnum)
+ super().setup(artifact_root, testnum, fio_args)
- self.command_file = os.path.join(self.test_dir,
- f"{os.path.basename(self.fio_job)}.command")
- self.stdout_file = os.path.join(self.test_dir,
- f"{os.path.basename(self.fio_job)}.stdout")
- self.stderr_file = os.path.join(self.test_dir,
- f"{os.path.basename(self.fio_job)}.stderr")
- self.exitcode_file = os.path.join(self.test_dir,
- f"{os.path.basename(self.fio_job)}.exitcode")
+ # Update the filenames from the default
+ self.filenames['cmd'] = os.path.join(self.paths['test_dir'],
+ f"{os.path.basename(self.fio_job)}.command")
+ self.filenames['stdout'] = os.path.join(self.paths['test_dir'],
+ f"{os.path.basename(self.fio_job)}.stdout")
+ self.filenames['stderr'] = os.path.join(self.paths['test_dir'],
+ f"{os.path.basename(self.fio_job)}.stderr")
+ self.filenames['exitcode'] = os.path.join(self.paths['test_dir'],
+ f"{os.path.basename(self.fio_job)}.exitcode")
def run_pre_job(self):
"""Run fio job precondition step."""
- precon = FioJobFileTest(self.exe_path, self.fio_pre_job,
+ precon = FioJobFileTest(self.paths['exe'], self.fio_pre_job,
self.fio_pre_success,
output_format=self.output_format)
- precon.setup(self.artifact_root, self.testnum)
+ precon.setup(self.paths['artifacts'], self.testnum)
precon.run()
precon.check_result()
self.precon_failed = not precon.passed
if 'json' not in self.output_format:
return
- file_data = self.get_file_fail(os.path.join(self.test_dir, self.fio_output))
+ file_data = self.get_file_fail(os.path.join(self.paths['test_dir'],
+ self.filenames['fio_output']))
if not file_data:
return
fio_pre_success=fio_pre_success,
output_format=output_format)
desc = config['job']
+ parameters = []
elif issubclass(config['test_class'], FioExeTest):
exe_path = os.path.join(test_env['fio_root'], config['exe'])
+ parameters = []
if config['parameters']:
parameters = [p.format(fio_path=test_env['fio_path'], nvmecdev=args.nvmecdev)
for p in config['parameters']]
- else:
- parameters = []
if Path(exe_path).suffix == '.py' and platform.system() == "Windows":
parameters.insert(0, exe_path)
exe_path = "python.exe"
if config['test_id'] in test_env['pass_through']:
parameters += test_env['pass_through'][config['test_id']].split()
- test = config['test_class'](exe_path, parameters,
- config['success'])
+ test = config['test_class'](exe_path, config['success'])
desc = config['exe']
else:
print(f"Test {config['test_id']} FAILED: unable to process test config")
continue
try:
- test.setup(test_env['artifact_root'], config['test_id'])
+ test.setup(test_env['artifact_root'], config['test_id'], parameters)
test.run()
test.check_result()
except KeyboardInterrupt:
else:
result = f"FAILED: {test.failure_reason}"
failed = failed + 1
- contents, _ = get_file(test.stderr_file)
+ contents, _ = get_file(test.filenames['stderr'])
logging.debug("Test %d: stderr:\n%s", config['test_id'], contents)
- contents, _ = get_file(test.stdout_file)
+ contents, _ = get_file(test.filenames['stdout'])
logging.debug("Test %d: stdout:\n%s", config['test_id'], contents)
print(f"Test {config['test_id']} {result} {desc}")
iops_files = []
for i in range(1, 4):
- filename = os.path.join(self.test_dir, "{0}_iops.{1}.log".format(os.path.basename(
+ filename = os.path.join(self.paths['test_dir'], "{0}_iops.{1}.log".format(os.path.basename(
self.fio_job), i))
file_data = self.get_file_fail(filename)
if not file_data:
iops_files = []
for i in range(1, 4):
- filename = os.path.join(self.test_dir, "{0}_iops.{1}.log".format(os.path.basename(
+ filename = os.path.join(self.paths['test_dir'], "{0}_iops.{1}.log".format(os.path.basename(
self.fio_job), i))
file_data = self.get_file_fail(filename)
if not file_data:
def check_result(self):
super().check_result()
- bw_log_filename = os.path.join(self.test_dir, "test_bw.log")
+ bw_log_filename = os.path.join(self.paths['test_dir'], "test_bw.log")
file_data = self.get_file_fail(bw_log_filename)
if not file_data:
return
def check_result(self):
super().check_result()
- bw_log_filename = os.path.join(self.test_dir, "test_bw.log")
+ bw_log_filename = os.path.join(self.paths['test_dir'], "test_bw.log")
file_data = self.get_file_fail(bw_log_filename)
if not file_data:
return
def check_result(self):
super().check_result()
- bw_log_filename = os.path.join(self.test_dir, "test_bw.log")
+ bw_log_filename = os.path.join(self.paths['test_dir'], "test_bw.log")
file_data = self.get_file_fail(bw_log_filename)
if not file_data:
return
def check_trimwrite(self, filename):
"""Make sure that trims are followed by writes of the same size at the same offset."""
- bw_log_filename = os.path.join(self.test_dir, filename)
+ bw_log_filename = os.path.join(self.paths['test_dir'], filename)
file_data = self.get_file_fail(bw_log_filename)
if not file_data:
return
def check_all_offsets(self, filename, sectorsize, filesize):
"""Make sure all offsets were touched."""
- file_data = self.get_file_fail(os.path.join(self.test_dir, filename))
+ file_data = self.get_file_fail(os.path.join(self.paths['test_dir'], filename))
if not file_data:
return
class FioJobFileTest_t0027(FioJobFileTest):
def setup(self, *args, **kws):
super().setup(*args, **kws)
- self.pattern_file = os.path.join(self.test_dir, "t0027.pattern")
- self.output_file = os.path.join(self.test_dir, "t0027file")
+ self.pattern_file = os.path.join(self.paths['test_dir'], "t0027.pattern")
+ self.output_file = os.path.join(self.paths['test_dir'], "t0027file")
self.pattern = os.urandom(16 << 10)
with open(self.pattern_file, "wb") as f:
f.write(self.pattern)