Blame t/run-fio-tests.py

Packit Service 0d30d9
#! /usr/libexec/platform-python
Packit Service 0e769b
# SPDX-License-Identifier: GPL-2.0-only
Packit Service 0e769b
#
Packit Service 0e769b
# Copyright (c) 2019 Western Digital Corporation or its affiliates.
Packit Service 0e769b
#
Packit Service 0e769b
"""
Packit Service 0e769b
# run-fio-tests.py
Packit Service 0e769b
#
Packit Service 0e769b
# Automate running of fio tests
Packit Service 0e769b
#
Packit Service 0e769b
# USAGE
Packit Service 0e769b
# python3 run-fio-tests.py [-r fio-root] [-f fio-path] [-a artifact-root]
Packit Service 0e769b
#                           [--skip # # #...] [--run-only # # #...]
Packit Service 0e769b
#
Packit Service 0e769b
#
Packit Service 0e769b
# EXAMPLE
Packit Service 0e769b
# # git clone git://git.kernel.dk/fio.git
Packit Service 0e769b
# # cd fio
Packit Service 0e769b
# # make -j
Packit Service 0e769b
# # python3 t/run-fio-tests.py
Packit Service 0e769b
#
Packit Service 0e769b
#
Packit Service 0e769b
# REQUIREMENTS
Packit Service 0e769b
# - Python 3.5 (subprocess.run)
Packit Service 0e769b
# - Linux (libaio ioengine, zbd tests, etc)
Packit Service 0e769b
# - The artifact directory must be on a file system that accepts 512-byte IO
Packit Service 0e769b
#   (t0002, t0003, t0004).
Packit Service 0e769b
# - The artifact directory needs to be on an SSD. Otherwise tests that carry
Packit Service 0e769b
#   out file-based IO will trigger a timeout (t0006).
Packit Service 0e769b
# - 4 CPUs (t0009)
Packit Service 0e769b
# - SciPy (steadystate_tests.py)
Packit Service 0e769b
# - libzbc (zbd tests)
Packit Service 0e769b
# - root privileges (zbd test)
Packit Service 0e769b
# - kernel 4.19 or later for zoned null block devices (zbd tests)
Packit Service 0e769b
# - CUnit support (unittests)
Packit Service 0e769b
#
Packit Service 0e769b
"""
Packit Service 0e769b
Packit Service 0e769b
#
Packit Service 0e769b
# TODO  run multiple tests simultaneously
Packit Service 0e769b
# TODO  Add sgunmap tests (requires SAS SSD)
Packit Service 0e769b
#
Packit Service 0e769b
Packit Service 0e769b
import os
Packit Service 0e769b
import sys
Packit Service 0e769b
import json
Packit Service 0e769b
import time
Packit Service 0e769b
import shutil
Packit Service 0e769b
import logging
Packit Service 0e769b
import argparse
Packit Service 0e769b
import platform
Packit Service 0e769b
import subprocess
Packit Service 0e769b
import multiprocessing
Packit Service 0e769b
from pathlib import Path
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class FioTest(object):
Packit Service 0e769b
    """Base for all fio tests."""
Packit Service 0e769b
Packit Service 0e769b
    def __init__(self, exe_path, parameters, success):
Packit Service 0e769b
        self.exe_path = exe_path
Packit Service 0e769b
        self.parameters = parameters
Packit Service 0e769b
        self.success = success
Packit Service 0e769b
        self.output = {}
Packit Service 0e769b
        self.artifact_root = None
Packit Service 0e769b
        self.testnum = None
Packit Service 0e769b
        self.test_dir = None
Packit Service 0e769b
        self.passed = True
Packit Service 0e769b
        self.failure_reason = ''
Packit Service 0e769b
        self.command_file = None
Packit Service 0e769b
        self.stdout_file = None
Packit Service 0e769b
        self.stderr_file = None
Packit Service 0e769b
        self.exitcode_file = None
Packit Service 0e769b
Packit Service 0e769b
    def setup(self, artifact_root, testnum):
Packit Service 0e769b
        """Setup instance variables for test."""
Packit Service 0e769b
Packit Service 0e769b
        self.artifact_root = artifact_root
Packit Service 0e769b
        self.testnum = testnum
Packit Service 0e769b
        self.test_dir = os.path.join(artifact_root, "{:04d}".format(testnum))
Packit Service 0e769b
        if not os.path.exists(self.test_dir):
Packit Service 0e769b
            os.mkdir(self.test_dir)
Packit Service 0e769b
Packit Service 0e769b
        self.command_file = os.path.join(
Packit Service 0e769b
            self.test_dir,
Packit Service 0e769b
            "{0}.command".format(os.path.basename(self.exe_path)))
Packit Service 0e769b
        self.stdout_file = os.path.join(
Packit Service 0e769b
            self.test_dir,
Packit Service 0e769b
            "{0}.stdout".format(os.path.basename(self.exe_path)))
Packit Service 0e769b
        self.stderr_file = os.path.join(
Packit Service 0e769b
            self.test_dir,
Packit Service 0e769b
            "{0}.stderr".format(os.path.basename(self.exe_path)))
Packit Service 0e769b
        self.exitcode_file = os.path.join(
Packit Service 0e769b
            self.test_dir,
Packit Service 0e769b
            "{0}.exitcode".format(os.path.basename(self.exe_path)))
Packit Service 0e769b
Packit Service 0e769b
    def run(self):
Packit Service 0e769b
        """Run the test."""
Packit Service 0e769b
Packit Service 0e769b
        raise NotImplementedError()
Packit Service 0e769b
Packit Service 0e769b
    def check_result(self):
Packit Service 0e769b
        """Check test results."""
Packit Service 0e769b
Packit Service 0e769b
        raise NotImplementedError()
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class FioExeTest(FioTest):
Packit Service 0e769b
    """Test consists of an executable binary or script"""
Packit Service 0e769b
Packit Service 0e769b
    def __init__(self, exe_path, parameters, success):
Packit Service 0e769b
        """Construct a FioExeTest which is a FioTest consisting of an
Packit Service 0e769b
        executable binary or script.
Packit Service 0e769b
Packit Service 0e769b
        exe_path:       location of executable binary or script
Packit Service 0e769b
        parameters:     list of parameters for executable
Packit Service 0e769b
        success:        Definition of test success
Packit Service 0e769b
        """
Packit Service 0e769b
Packit Service 0e769b
        FioTest.__init__(self, exe_path, parameters, success)
Packit Service 0e769b
Packit Service 0e769b
    def run(self):
Packit Service 0e769b
        """Execute the binary or script described by this instance."""
Packit Service 0e769b
Packit Service 0e769b
        if self.parameters:
Packit Service 0e769b
            command = [self.exe_path] + self.parameters
Packit Service 0e769b
        else:
Packit Service 0e769b
            command = [self.exe_path]
Packit Service 0e769b
        command_file = open(self.command_file, "w+")
Packit Service 0e769b
        command_file.write("%s\n" % command)
Packit Service 0e769b
        command_file.close()
Packit Service 0e769b
Packit Service 0e769b
        stdout_file = open(self.stdout_file, "w+")
Packit Service 0e769b
        stderr_file = open(self.stderr_file, "w+")
Packit Service 0e769b
        exitcode_file = open(self.exitcode_file, "w+")
Packit Service 0e769b
        try:
Packit Service 0e769b
            proc = None
Packit Service 0e769b
            # Avoid using subprocess.run() here because when a timeout occurs,
Packit Service 0e769b
            # fio will be stopped with SIGKILL. This does not give fio a
Packit Service 0e769b
            # chance to clean up and means that child processes may continue
Packit Service 0e769b
            # running and submitting IO.
Packit Service 0e769b
            proc = subprocess.Popen(command,
Packit Service 0e769b
                                    stdout=stdout_file,
Packit Service 0e769b
                                    stderr=stderr_file,
Packit Service 0e769b
                                    cwd=self.test_dir,
Packit Service 0e769b
                                    universal_newlines=True)
Packit Service 0e769b
            proc.communicate(timeout=self.success['timeout'])
Packit Service 0e769b
            exitcode_file.write('{0}\n'.format(proc.returncode))
Packit Service 0e769b
            logging.debug("Test %d: return code: %d", self.testnum, proc.returncode)
Packit Service 0e769b
            self.output['proc'] = proc
Packit Service 0e769b
        except subprocess.TimeoutExpired:
Packit Service 0e769b
            proc.terminate()
Packit Service 0e769b
            proc.communicate()
Packit Service 0e769b
            assert proc.poll()
Packit Service 0e769b
            self.output['failure'] = 'timeout'
Packit Service 0e769b
        except Exception:
Packit Service 0e769b
            if proc:
Packit Service 0e769b
                if not proc.poll():
Packit Service 0e769b
                    proc.terminate()
Packit Service 0e769b
                    proc.communicate()
Packit Service 0e769b
            self.output['failure'] = 'exception'
Packit Service 0e769b
            self.output['exc_info'] = sys.exc_info()
Packit Service 0e769b
        finally:
Packit Service 0e769b
            stdout_file.close()
Packit Service 0e769b
            stderr_file.close()
Packit Service 0e769b
            exitcode_file.close()
Packit Service 0e769b
Packit Service 0e769b
    def check_result(self):
Packit Service 0e769b
        """Check results of test run."""
Packit Service 0e769b
Packit Service 0e769b
        if 'proc' not in self.output:
Packit Service 0e769b
            if self.output['failure'] == 'timeout':
Packit Service 0e769b
                self.failure_reason = "{0} timeout,".format(self.failure_reason)
Packit Service 0e769b
            else:
Packit Service 0e769b
                assert self.output['failure'] == 'exception'
Packit Service 0e769b
                self.failure_reason = '{0} exception: {1}, {2}'.format(
Packit Service 0e769b
                    self.failure_reason, self.output['exc_info'][0],
Packit Service 0e769b
                    self.output['exc_info'][1])
Packit Service 0e769b
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        if 'zero_return' in self.success:
Packit Service 0e769b
            if self.success['zero_return']:
Packit Service 0e769b
                if self.output['proc'].returncode != 0:
Packit Service 0e769b
                    self.passed = False
Packit Service 0e769b
                    self.failure_reason = "{0} non-zero return code,".format(self.failure_reason)
Packit Service 0e769b
            else:
Packit Service 0e769b
                if self.output['proc'].returncode == 0:
Packit Service 0e769b
                    self.failure_reason = "{0} zero return code,".format(self.failure_reason)
Packit Service 0e769b
                    self.passed = False
Packit Service 0e769b
Packit Service 0e769b
        stderr_size = os.path.getsize(self.stderr_file)
Packit Service 0e769b
        if 'stderr_empty' in self.success:
Packit Service 0e769b
            if self.success['stderr_empty']:
Packit Service 0e769b
                if stderr_size != 0:
Packit Service 0e769b
                    self.failure_reason = "{0} stderr not empty,".format(self.failure_reason)
Packit Service 0e769b
                    self.passed = False
Packit Service 0e769b
            else:
Packit Service 0e769b
                if stderr_size == 0:
Packit Service 0e769b
                    self.failure_reason = "{0} stderr empty,".format(self.failure_reason)
Packit Service 0e769b
                    self.passed = False
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class FioJobTest(FioExeTest):
Packit Service 0e769b
    """Test consists of a fio job"""
Packit Service 0e769b
Packit Service 0e769b
    def __init__(self, fio_path, fio_job, success, fio_pre_job=None,
Packit Service 0e769b
                 fio_pre_success=None, output_format="normal"):
Packit Service 0e769b
        """Construct a FioJobTest which is a FioExeTest consisting of a
Packit Service 0e769b
        single fio job file with an optional setup step.
Packit Service 0e769b
Packit Service 0e769b
        fio_path:           location of fio executable
Packit Service 0e769b
        fio_job:            location of fio job file
Packit Service 0e769b
        success:            Definition of test success
Packit Service 0e769b
        fio_pre_job:        fio job for preconditioning
Packit Service 0e769b
        fio_pre_success:    Definition of test success for fio precon job
Packit Service 0e769b
        output_format:      normal (default), json, jsonplus, or terse
Packit Service 0e769b
        """
Packit Service 0e769b
Packit Service 0e769b
        self.fio_job = fio_job
Packit Service 0e769b
        self.fio_pre_job = fio_pre_job
Packit Service 0e769b
        self.fio_pre_success = fio_pre_success if fio_pre_success else success
Packit Service 0e769b
        self.output_format = output_format
Packit Service 0e769b
        self.precon_failed = False
Packit Service 0e769b
        self.json_data = None
Packit Service 0e769b
        self.fio_output = "{0}.output".format(os.path.basename(self.fio_job))
Packit Service 0e769b
        self.fio_args = [
Packit Service 0e769b
            "--output-format={0}".format(self.output_format),
Packit Service 0e769b
            "--output={0}".format(self.fio_output),
Packit Service 0e769b
            self.fio_job,
Packit Service 0e769b
            ]
Packit Service 0e769b
        FioExeTest.__init__(self, fio_path, self.fio_args, success)
Packit Service 0e769b
Packit Service 0e769b
    def setup(self, artifact_root, testnum):
Packit Service 0e769b
        """Setup instance variables for fio job test."""
Packit Service 0e769b
Packit Service 0e769b
        super(FioJobTest, self).setup(artifact_root, testnum)
Packit Service 0e769b
Packit Service 0e769b
        self.command_file = os.path.join(
Packit Service 0e769b
            self.test_dir,
Packit Service 0e769b
            "{0}.command".format(os.path.basename(self.fio_job)))
Packit Service 0e769b
        self.stdout_file = os.path.join(
Packit Service 0e769b
            self.test_dir,
Packit Service 0e769b
            "{0}.stdout".format(os.path.basename(self.fio_job)))
Packit Service 0e769b
        self.stderr_file = os.path.join(
Packit Service 0e769b
            self.test_dir,
Packit Service 0e769b
            "{0}.stderr".format(os.path.basename(self.fio_job)))
Packit Service 0e769b
        self.exitcode_file = os.path.join(
Packit Service 0e769b
            self.test_dir,
Packit Service 0e769b
            "{0}.exitcode".format(os.path.basename(self.fio_job)))
Packit Service 0e769b
Packit Service 0e769b
    def run_pre_job(self):
Packit Service 0e769b
        """Run fio job precondition step."""
Packit Service 0e769b
Packit Service 0e769b
        precon = FioJobTest(self.exe_path, self.fio_pre_job,
Packit Service 0e769b
                            self.fio_pre_success,
Packit Service 0e769b
                            output_format=self.output_format)
Packit Service 0e769b
        precon.setup(self.artifact_root, self.testnum)
Packit Service 0e769b
        precon.run()
Packit Service 0e769b
        precon.check_result()
Packit Service 0e769b
        self.precon_failed = not precon.passed
Packit Service 0e769b
        self.failure_reason = precon.failure_reason
Packit Service 0e769b
Packit Service 0e769b
    def run(self):
Packit Service 0e769b
        """Run fio job test."""
Packit Service 0e769b
Packit Service 0e769b
        if self.fio_pre_job:
Packit Service 0e769b
            self.run_pre_job()
Packit Service 0e769b
Packit Service 0e769b
        if not self.precon_failed:
Packit Service 0e769b
            super(FioJobTest, self).run()
Packit Service 0e769b
        else:
Packit Service 0e769b
            logging.debug("Test %d: precondition step failed", self.testnum)
Packit Service 0e769b
Packit Service 0e769b
    def check_result(self):
Packit Service 0e769b
        """Check fio job results."""
Packit Service 0e769b
Packit Service 0e769b
        if self.precon_failed:
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
            self.failure_reason = "{0} precondition step failed,".format(self.failure_reason)
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        super(FioJobTest, self).check_result()
Packit Service 0e769b
Packit Service 0e769b
        if not self.passed:
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        if 'json' not in self.output_format:
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        try:
Packit Service 0e769b
            with open(os.path.join(self.test_dir, self.fio_output), "r") as output_file:
Packit Service 0e769b
                file_data = output_file.read()
Packit Service 0e769b
        except EnvironmentError:
Packit Service 0e769b
            self.failure_reason = "{0} unable to open output file,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        #
Packit Service 0e769b
        # Sometimes fio informational messages are included at the top of the
Packit Service 0e769b
        # JSON output, especially under Windows. Try to decode output as JSON
Packit Service 0e769b
        # data, lopping off up to the first four lines
Packit Service 0e769b
        #
Packit Service 0e769b
        lines = file_data.splitlines()
Packit Service 0e769b
        for i in range(5):
Packit Service 0e769b
            file_data = '\n'.join(lines[i:])
Packit Service 0e769b
            try:
Packit Service 0e769b
                self.json_data = json.loads(file_data)
Packit Service 0e769b
            except json.JSONDecodeError:
Packit Service 0e769b
                continue
Packit Service 0e769b
            else:
Packit Service 0e769b
                logging.debug("Test %d: skipped %d lines decoding JSON data", self.testnum, i)
Packit Service 0e769b
                return
Packit Service 0e769b
Packit Service 0e769b
        self.failure_reason = "{0} unable to decode JSON data,".format(self.failure_reason)
Packit Service 0e769b
        self.passed = False
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class FioJobTest_t0005(FioJobTest):
Packit Service 0e769b
    """Test consists of fio test job t0005
Packit Service 0e769b
    Confirm that read['io_kbytes'] == write['io_kbytes'] == 102400"""
Packit Service 0e769b
Packit Service 0e769b
    def check_result(self):
Packit Service 0e769b
        super(FioJobTest_t0005, self).check_result()
Packit Service 0e769b
Packit Service 0e769b
        if not self.passed:
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        if self.json_data['jobs'][0]['read']['io_kbytes'] != 102400:
Packit Service 0e769b
            self.failure_reason = "{0} bytes read mismatch,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
        if self.json_data['jobs'][0]['write']['io_kbytes'] != 102400:
Packit Service 0e769b
            self.failure_reason = "{0} bytes written mismatch,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class FioJobTest_t0006(FioJobTest):
Packit Service 0e769b
    """Test consists of fio test job t0006
Packit Service 0e769b
    Confirm that read['io_kbytes'] ~ 2*write['io_kbytes']"""
Packit Service 0e769b
Packit Service 0e769b
    def check_result(self):
Packit Service 0e769b
        super(FioJobTest_t0006, self).check_result()
Packit Service 0e769b
Packit Service 0e769b
        if not self.passed:
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        ratio = self.json_data['jobs'][0]['read']['io_kbytes'] \
Packit Service 0e769b
            / self.json_data['jobs'][0]['write']['io_kbytes']
Packit Service 0e769b
        logging.debug("Test %d: ratio: %f", self.testnum, ratio)
Packit Service 0e769b
        if ratio < 1.99 or ratio > 2.01:
Packit Service 0e769b
            self.failure_reason = "{0} read/write ratio mismatch,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class FioJobTest_t0007(FioJobTest):
Packit Service 0e769b
    """Test consists of fio test job t0007
Packit Service 0e769b
    Confirm that read['io_kbytes'] = 87040"""
Packit Service 0e769b
Packit Service 0e769b
    def check_result(self):
Packit Service 0e769b
        super(FioJobTest_t0007, self).check_result()
Packit Service 0e769b
Packit Service 0e769b
        if not self.passed:
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        if self.json_data['jobs'][0]['read']['io_kbytes'] != 87040:
Packit Service 0e769b
            self.failure_reason = "{0} bytes read mismatch,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class FioJobTest_t0008(FioJobTest):
Packit Service 0e769b
    """Test consists of fio test job t0008
Packit Service 0e769b
    Confirm that read['io_kbytes'] = 32768 and that
Packit Service 0e769b
                write['io_kbytes'] ~ 16568
Packit Service 0e769b
Packit Service 0e769b
    I did runs with fio-ae2fafc8 and saw write['io_kbytes'] values of
Packit Service 0e769b
    16585, 16588. With two runs of fio-3.16 I obtained 16568"""
Packit Service 0e769b
Packit Service 0e769b
    def check_result(self):
Packit Service 0e769b
        super(FioJobTest_t0008, self).check_result()
Packit Service 0e769b
Packit Service 0e769b
        if not self.passed:
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        ratio = self.json_data['jobs'][0]['write']['io_kbytes'] / 16568
Packit Service 0e769b
        logging.debug("Test %d: ratio: %f", self.testnum, ratio)
Packit Service 0e769b
Packit Service 0e769b
        if ratio < 0.99 or ratio > 1.01:
Packit Service 0e769b
            self.failure_reason = "{0} bytes written mismatch,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
        if self.json_data['jobs'][0]['read']['io_kbytes'] != 32768:
Packit Service 0e769b
            self.failure_reason = "{0} bytes read mismatch,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class FioJobTest_t0009(FioJobTest):
Packit Service 0e769b
    """Test consists of fio test job t0009
Packit Service 0e769b
    Confirm that runtime >= 60s"""
Packit Service 0e769b
Packit Service 0e769b
    def check_result(self):
Packit Service 0e769b
        super(FioJobTest_t0009, self).check_result()
Packit Service 0e769b
Packit Service 0e769b
        if not self.passed:
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        logging.debug('Test %d: elapsed: %d', self.testnum, self.json_data['jobs'][0]['elapsed'])
Packit Service 0e769b
Packit Service 0e769b
        if self.json_data['jobs'][0]['elapsed'] < 60:
Packit Service 0e769b
            self.failure_reason = "{0} elapsed time mismatch,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class FioJobTest_t0011(FioJobTest):
Packit Service 0e769b
    """Test consists of fio test job t0009
Packit Service 0e769b
    Confirm that job0 iops == 1000
Packit Service 0e769b
    and that job1_iops / job0_iops ~ 8
Packit Service 0e769b
    With two runs of fio-3.16 I observed a ratio of 8.3"""
Packit Service 0e769b
Packit Service 0e769b
    def check_result(self):
Packit Service 0e769b
        super(FioJobTest_t0011, self).check_result()
Packit Service 0e769b
Packit Service 0e769b
        if not self.passed:
Packit Service 0e769b
            return
Packit Service 0e769b
Packit Service 0e769b
        iops1 = self.json_data['jobs'][0]['read']['iops']
Packit Service 0e769b
        iops2 = self.json_data['jobs'][1]['read']['iops']
Packit Service 0e769b
        ratio = iops2 / iops1
Packit Service 0e769b
        logging.debug("Test %d: iops1: %f", self.testnum, iops1)
Packit Service 0e769b
        logging.debug("Test %d: ratio: %f", self.testnum, ratio)
Packit Service 0e769b
Packit Service 0e769b
        if iops1 < 998 or iops1 > 1002:
Packit Service 0e769b
            self.failure_reason = "{0} iops value mismatch,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
Packit Service 0e769b
        if ratio < 7 or ratio > 9:
Packit Service 0e769b
            self.failure_reason = "{0} iops ratio mismatch,".format(self.failure_reason)
Packit Service 0e769b
            self.passed = False
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
class Requirements(object):
Packit Service 0e769b
    """Requirements consists of multiple run environment characteristics.
Packit Service 0e769b
    These are to determine if a particular test can be run"""
Packit Service 0e769b
Packit Service 0e769b
    _linux = False
Packit Service 0e769b
    _libaio = False
Packit Service 0e769b
    _zbd = False
Packit Service 0e769b
    _root = False
Packit Service 0e769b
    _zoned_nullb = False
Packit Service 0e769b
    _not_macos = False
Packit Service 0e769b
    _not_windows = False
Packit Service 0e769b
    _unittests = False
Packit Service 0e769b
    _cpucount4 = False
Packit Service 0e769b
Packit Service 0e769b
    def __init__(self, fio_root):
Packit Service 0e769b
        Requirements._not_macos = platform.system() != "Darwin"
Packit Service 0e769b
        Requirements._not_windows = platform.system() != "Windows"
Packit Service 0e769b
        Requirements._linux = platform.system() == "Linux"
Packit Service 0e769b
Packit Service 0e769b
        if Requirements._linux:
Packit Service 0e769b
            try:
Packit Service 0e769b
                config_file = os.path.join(fio_root, "config-host.h")
Packit Service 0e769b
                with open(config_file, "r") as config:
Packit Service 0e769b
                    contents = config.read()
Packit Service 0e769b
            except Exception:
Packit Service 0e769b
                print("Unable to open {0} to check requirements".format(config_file))
Packit Service 0e769b
                Requirements._zbd = True
Packit Service 0e769b
            else:
Packit Service 0e769b
                Requirements._zbd = "CONFIG_LINUX_BLKZONED" in contents
Packit Service 0e769b
                Requirements._libaio = "CONFIG_LIBAIO" in contents
Packit Service 0e769b
Packit Service 0e769b
            Requirements._root = (os.geteuid() == 0)
Packit Service 0e769b
            if Requirements._zbd and Requirements._root:
Packit Service 0e769b
                subprocess.run(["modprobe", "null_blk"],
Packit Service 0e769b
                               stdout=subprocess.PIPE,
Packit Service 0e769b
                               stderr=subprocess.PIPE)
Packit Service 0e769b
                if os.path.exists("/sys/module/null_blk/parameters/zoned"):
Packit Service 0e769b
                    Requirements._zoned_nullb = True
Packit Service 0e769b
Packit Service 0e769b
        if platform.system() == "Windows":
Packit Service 0e769b
            utest_exe = "unittest.exe"
Packit Service 0e769b
        else:
Packit Service 0e769b
            utest_exe = "unittest"
Packit Service 0e769b
        unittest_path = os.path.join(fio_root, "unittests", utest_exe)
Packit Service 0e769b
        Requirements._unittests = os.path.exists(unittest_path)
Packit Service 0e769b
Packit Service 0e769b
        Requirements._cpucount4 = multiprocessing.cpu_count() >= 4
Packit Service 0e769b
Packit Service 0e769b
        req_list = [Requirements.linux,
Packit Service 0e769b
                    Requirements.libaio,
Packit Service 0e769b
                    Requirements.zbd,
Packit Service 0e769b
                    Requirements.root,
Packit Service 0e769b
                    Requirements.zoned_nullb,
Packit Service 0e769b
                    Requirements.not_macos,
Packit Service 0e769b
                    Requirements.not_windows,
Packit Service 0e769b
                    Requirements.unittests,
Packit Service 0e769b
                    Requirements.cpucount4]
Packit Service 0e769b
        for req in req_list:
Packit Service 0e769b
            value, desc = req()
Packit Service 0e769b
            logging.debug("Requirements: Requirement '%s' met? %s", desc, value)
Packit Service 0e769b
Packit Service 0e769b
    @classmethod
Packit Service 0e769b
    def linux(cls):
Packit Service 0e769b
        """Are we running on Linux?"""
Packit Service 0e769b
        return Requirements._linux, "Linux required"
Packit Service 0e769b
Packit Service 0e769b
    @classmethod
Packit Service 0e769b
    def libaio(cls):
Packit Service 0e769b
        """Is libaio available?"""
Packit Service 0e769b
        return Requirements._libaio, "libaio required"
Packit Service 0e769b
Packit Service 0e769b
    @classmethod
Packit Service 0e769b
    def zbd(cls):
Packit Service 0e769b
        """Is ZBD support available?"""
Packit Service 0e769b
        return Requirements._zbd, "Zoned block device support required"
Packit Service 0e769b
Packit Service 0e769b
    @classmethod
Packit Service 0e769b
    def root(cls):
Packit Service 0e769b
        """Are we running as root?"""
Packit Service 0e769b
        return Requirements._root, "root required"
Packit Service 0e769b
Packit Service 0e769b
    @classmethod
Packit Service 0e769b
    def zoned_nullb(cls):
Packit Service 0e769b
        """Are zoned null block devices available?"""
Packit Service 0e769b
        return Requirements._zoned_nullb, "Zoned null block device support required"
Packit Service 0e769b
Packit Service 0e769b
    @classmethod
Packit Service 0e769b
    def not_macos(cls):
Packit Service 0e769b
        """Are we running on a platform other than macOS?"""
Packit Service 0e769b
        return Requirements._not_macos, "platform other than macOS required"
Packit Service 0e769b
Packit Service 0e769b
    @classmethod
Packit Service 0e769b
    def not_windows(cls):
Packit Service 0e769b
        """Are we running on a platform other than Windws?"""
Packit Service 0e769b
        return Requirements._not_windows, "platform other than Windows required"
Packit Service 0e769b
Packit Service 0e769b
    @classmethod
Packit Service 0e769b
    def unittests(cls):
Packit Service 0e769b
        """Were unittests built?"""
Packit Service 0e769b
        return Requirements._unittests, "Unittests support required"
Packit Service 0e769b
Packit Service 0e769b
    @classmethod
Packit Service 0e769b
    def cpucount4(cls):
Packit Service 0e769b
        """Do we have at least 4 CPUs?"""
Packit Service 0e769b
        return Requirements._cpucount4, "4+ CPUs required"
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
SUCCESS_DEFAULT = {
Packit Service 0e769b
    'zero_return': True,
Packit Service 0e769b
    'stderr_empty': True,
Packit Service 0e769b
    'timeout': 600,
Packit Service 0e769b
    }
Packit Service 0e769b
SUCCESS_NONZERO = {
Packit Service 0e769b
    'zero_return': False,
Packit Service 0e769b
    'stderr_empty': False,
Packit Service 0e769b
    'timeout': 600,
Packit Service 0e769b
    }
Packit Service 0e769b
SUCCESS_STDERR = {
Packit Service 0e769b
    'zero_return': True,
Packit Service 0e769b
    'stderr_empty': False,
Packit Service 0e769b
    'timeout': 600,
Packit Service 0e769b
    }
Packit Service 0e769b
TEST_LIST = [
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1,
Packit Service 0e769b
        'test_class':       FioJobTest,
Packit Service 0e769b
        'job':              't0001-52c58027.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          None,
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          2,
Packit Service 0e769b
        'test_class':       FioJobTest,
Packit Service 0e769b
        'job':              't0002-13af05ae-post.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          't0002-13af05ae-pre.fio',
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'requirements':     [Requirements.linux, Requirements.libaio],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          3,
Packit Service 0e769b
        'test_class':       FioJobTest,
Packit Service 0e769b
        'job':              't0003-0ae2c6e1-post.fio',
Packit Service 0e769b
        'success':          SUCCESS_NONZERO,
Packit Service 0e769b
        'pre_job':          't0003-0ae2c6e1-pre.fio',
Packit Service 0e769b
        'pre_success':      SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [Requirements.linux, Requirements.libaio],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          4,
Packit Service 0e769b
        'test_class':       FioJobTest,
Packit Service 0e769b
        'job':              't0004-8a99fdf6.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          None,
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'requirements':     [Requirements.linux, Requirements.libaio],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          5,
Packit Service 0e769b
        'test_class':       FioJobTest_t0005,
Packit Service 0e769b
        'job':              't0005-f7078f7b.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          None,
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'output_format':    'json',
Packit Service 0e769b
        'requirements':     [Requirements.not_windows],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          6,
Packit Service 0e769b
        'test_class':       FioJobTest_t0006,
Packit Service 0e769b
        'job':              't0006-82af2a7c.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          None,
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'output_format':    'json',
Packit Service 0e769b
        'requirements':     [Requirements.linux, Requirements.libaio],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          7,
Packit Service 0e769b
        'test_class':       FioJobTest_t0007,
Packit Service 0e769b
        'job':              't0007-37cf9e3c.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          None,
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'output_format':    'json',
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          8,
Packit Service 0e769b
        'test_class':       FioJobTest_t0008,
Packit Service 0e769b
        'job':              't0008-ae2fafc8.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          None,
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'output_format':    'json',
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          9,
Packit Service 0e769b
        'test_class':       FioJobTest_t0009,
Packit Service 0e769b
        'job':              't0009-f8b0bd10.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          None,
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'output_format':    'json',
Packit Service 0e769b
        'requirements':     [Requirements.not_macos,
Packit Service 0e769b
                             Requirements.cpucount4],
Packit Service 0e769b
        # mac os does not support CPU affinity
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          10,
Packit Service 0e769b
        'test_class':       FioJobTest,
Packit Service 0e769b
        'job':              't0010-b7aae4ba.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          None,
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          11,
Packit Service 0e769b
        'test_class':       FioJobTest_t0011,
Packit Service 0e769b
        'job':              't0011-5d2788d5.fio',
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'pre_job':          None,
Packit Service 0e769b
        'pre_success':      None,
Packit Service 0e769b
        'output_format':    'json',
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1000,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/axmap',
Packit Service 0e769b
        'parameters':       None,
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1001,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/ieee754',
Packit Service 0e769b
        'parameters':       None,
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1002,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/lfsr-test',
Packit Service 0e769b
        'parameters':       ['0xFFFFFF', '0', '0', 'verify'],
Packit Service 0e769b
        'success':          SUCCESS_STDERR,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1003,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/readonly.py',
Packit Service 0e769b
        'parameters':       ['-f', '{fio_path}'],
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1004,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/steadystate_tests.py',
Packit Service 0e769b
        'parameters':       ['{fio_path}'],
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1005,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/stest',
Packit Service 0e769b
        'parameters':       None,
Packit Service 0e769b
        'success':          SUCCESS_STDERR,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1006,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/strided.py',
Packit Service 0e769b
        'parameters':       ['{fio_path}'],
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1007,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/zbd/run-tests-against-regular-nullb',
Packit Service 0e769b
        'parameters':       None,
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [Requirements.linux, Requirements.zbd,
Packit Service 0e769b
                             Requirements.root],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1008,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/zbd/run-tests-against-zoned-nullb',
Packit Service 0e769b
        'parameters':       None,
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [Requirements.linux, Requirements.zbd,
Packit Service 0e769b
                             Requirements.root, Requirements.zoned_nullb],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1009,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              'unittests/unittest',
Packit Service 0e769b
        'parameters':       None,
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [Requirements.unittests],
Packit Service 0e769b
    },
Packit Service 0e769b
    {
Packit Service 0e769b
        'test_id':          1010,
Packit Service 0e769b
        'test_class':       FioExeTest,
Packit Service 0e769b
        'exe':              't/latency_percentiles.py',
Packit Service 0e769b
        'parameters':       ['-f', '{fio_path}'],
Packit Service 0e769b
        'success':          SUCCESS_DEFAULT,
Packit Service 0e769b
        'requirements':     [],
Packit Service 0e769b
    },
Packit Service 0e769b
]
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
def parse_args():
Packit Service 0e769b
    """Parse command-line arguments."""
Packit Service 0e769b
Packit Service 0e769b
    parser = argparse.ArgumentParser()
Packit Service 0e769b
    parser.add_argument('-r', '--fio-root',
Packit Service 0e769b
                        help='fio root path')
Packit Service 0e769b
    parser.add_argument('-f', '--fio',
Packit Service 0e769b
                        help='path to fio executable (e.g., ./fio)')
Packit Service 0e769b
    parser.add_argument('-a', '--artifact-root',
Packit Service 0e769b
                        help='artifact root directory')
Packit Service 0e769b
    parser.add_argument('-s', '--skip', nargs='+', type=int,
Packit Service 0e769b
                        help='list of test(s) to skip')
Packit Service 0e769b
    parser.add_argument('-o', '--run-only', nargs='+', type=int,
Packit Service 0e769b
                        help='list of test(s) to run, skipping all others')
Packit Service 0e769b
    parser.add_argument('-d', '--debug', action='store_true',
Packit Service 0e769b
                        help='provide debug output')
Packit Service 0e769b
    parser.add_argument('-k', '--skip-req', action='store_true',
Packit Service 0e769b
                        help='skip requirements checking')
Packit Service 0e769b
    args = parser.parse_args()
Packit Service 0e769b
Packit Service 0e769b
    return args
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
def main():
Packit Service 0e769b
    """Entry point."""
Packit Service 0e769b
Packit Service 0e769b
    args = parse_args()
Packit Service 0e769b
    if args.debug:
Packit Service 0e769b
        logging.basicConfig(level=logging.DEBUG)
Packit Service 0e769b
    else:
Packit Service 0e769b
        logging.basicConfig(level=logging.INFO)
Packit Service 0e769b
Packit Service 0e769b
    if args.fio_root:
Packit Service 0e769b
        fio_root = args.fio_root
Packit Service 0e769b
    else:
Packit Service 0e769b
        fio_root = str(Path(__file__).absolute().parent.parent)
Packit Service 0e769b
    print("fio root is %s" % fio_root)
Packit Service 0e769b
Packit Service 0e769b
    if args.fio:
Packit Service 0e769b
        fio_path = args.fio
Packit Service 0e769b
    else:
Packit Service 0e769b
        if platform.system() == "Windows":
Packit Service 0e769b
            fio_exe = "fio.exe"
Packit Service 0e769b
        else:
Packit Service 0e769b
            fio_exe = "fio"
Packit Service 0e769b
        fio_path = os.path.join(fio_root, fio_exe)
Packit Service 0e769b
    print("fio path is %s" % fio_path)
Packit Service 0e769b
    if not shutil.which(fio_path):
Packit Service 0e769b
        print("Warning: fio executable not found")
Packit Service 0e769b
Packit Service 0e769b
    artifact_root = args.artifact_root if args.artifact_root else \
Packit Service 0e769b
        "fio-test-{0}".format(time.strftime("%Y%m%d-%H%M%S"))
Packit Service 0e769b
    os.mkdir(artifact_root)
Packit Service 0e769b
    print("Artifact directory is %s" % artifact_root)
Packit Service 0e769b
Packit Service 0e769b
    if not args.skip_req:
Packit Service 0e769b
        req = Requirements(fio_root)
Packit Service 0e769b
Packit Service 0e769b
    passed = 0
Packit Service 0e769b
    failed = 0
Packit Service 0e769b
    skipped = 0
Packit Service 0e769b
Packit Service 0e769b
    for config in TEST_LIST:
Packit Service 0e769b
        if (args.skip and config['test_id'] in args.skip) or \
Packit Service 0e769b
           (args.run_only and config['test_id'] not in args.run_only):
Packit Service 0e769b
            skipped = skipped + 1
Packit Service 0e769b
            print("Test {0} SKIPPED (User request)".format(config['test_id']))
Packit Service 0e769b
            continue
Packit Service 0e769b
Packit Service 0e769b
        if issubclass(config['test_class'], FioJobTest):
Packit Service 0e769b
            if config['pre_job']:
Packit Service 0e769b
                fio_pre_job = os.path.join(fio_root, 't', 'jobs',
Packit Service 0e769b
                                           config['pre_job'])
Packit Service 0e769b
            else:
Packit Service 0e769b
                fio_pre_job = None
Packit Service 0e769b
            if config['pre_success']:
Packit Service 0e769b
                fio_pre_success = config['pre_success']
Packit Service 0e769b
            else:
Packit Service 0e769b
                fio_pre_success = None
Packit Service 0e769b
            if 'output_format' in config:
Packit Service 0e769b
                output_format = config['output_format']
Packit Service 0e769b
            else:
Packit Service 0e769b
                output_format = 'normal'
Packit Service 0e769b
            test = config['test_class'](
Packit Service 0e769b
                fio_path,
Packit Service 0e769b
                os.path.join(fio_root, 't', 'jobs', config['job']),
Packit Service 0e769b
                config['success'],
Packit Service 0e769b
                fio_pre_job=fio_pre_job,
Packit Service 0e769b
                fio_pre_success=fio_pre_success,
Packit Service 0e769b
                output_format=output_format)
Packit Service 0e769b
        elif issubclass(config['test_class'], FioExeTest):
Packit Service 0e769b
            exe_path = os.path.join(fio_root, config['exe'])
Packit Service 0e769b
            if config['parameters']:
Packit Service 0e769b
                parameters = [p.format(fio_path=fio_path) for p in config['parameters']]
Packit Service 0e769b
            else:
Packit Service 0e769b
                parameters = None
Packit Service 0e769b
            if Path(exe_path).suffix == '.py' and platform.system() == "Windows":
Packit Service 0e769b
                if parameters:
Packit Service 0e769b
                    parameters.insert(0, exe_path)
Packit Service 0e769b
                else:
Packit Service 0e769b
                    parameters = [exe_path]
Packit Service 0e769b
                exe_path = "python.exe"
Packit Service 0e769b
            test = config['test_class'](exe_path, parameters,
Packit Service 0e769b
                                        config['success'])
Packit Service 0e769b
        else:
Packit Service 0e769b
            print("Test {0} FAILED: unable to process test config".format(config['test_id']))
Packit Service 0e769b
            failed = failed + 1
Packit Service 0e769b
            continue
Packit Service 0e769b
Packit Service 0e769b
        if not args.skip_req:
Packit Service 0e769b
            reqs_met = True
Packit Service 0e769b
            for req in config['requirements']:
Packit Service 0e769b
                reqs_met, reason = req()
Packit Service 0e769b
                logging.debug("Test %d: Requirement '%s' met? %s", config['test_id'], reason,
Packit Service 0e769b
                              reqs_met)
Packit Service 0e769b
                if not reqs_met:
Packit Service 0e769b
                    break
Packit Service 0e769b
            if not reqs_met:
Packit Service 0e769b
                print("Test {0} SKIPPED ({1})".format(config['test_id'], reason))
Packit Service 0e769b
                skipped = skipped + 1
Packit Service 0e769b
                continue
Packit Service 0e769b
Packit Service 0e769b
        test.setup(artifact_root, config['test_id'])
Packit Service 0e769b
        test.run()
Packit Service 0e769b
        test.check_result()
Packit Service 0e769b
        if test.passed:
Packit Service 0e769b
            result = "PASSED"
Packit Service 0e769b
            passed = passed + 1
Packit Service 0e769b
        else:
Packit Service 0e769b
            result = "FAILED: {0}".format(test.failure_reason)
Packit Service 0e769b
            failed = failed + 1
Packit Service 0e769b
            with open(test.stderr_file, "r") as stderr_file:
Packit Service 0e769b
                logging.debug("Test %d: stderr:\n%s", config['test_id'], stderr_file.read())
Packit Service 0e769b
            with open(test.stdout_file, "r") as stdout_file:
Packit Service 0e769b
                logging.debug("Test %d: stdout:\n%s", config['test_id'], stdout_file.read())
Packit Service 0e769b
        print("Test {0} {1}".format(config['test_id'], result))
Packit Service 0e769b
Packit Service 0e769b
    print("{0} test(s) passed, {1} failed, {2} skipped".format(passed, failed, skipped))
Packit Service 0e769b
Packit Service 0e769b
    sys.exit(failed)
Packit Service 0e769b
Packit Service 0e769b
Packit Service 0e769b
if __name__ == '__main__':
Packit Service 0e769b
    main()