# Common utilities and Python wrappers for qemu-iotests
#
# Copyright (C) 2012 IBM Corp.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import argparse
import atexit
import bz2
from collections import OrderedDict
import faulthandler
import json
import logging
import os
import re
import shutil
import signal
import struct
import subprocess
import sys
import time
from typing import (Any, Callable, Dict, Iterable, Iterator,
                    List, Optional, Sequence, TextIO, Tuple, Type, TypeVar)
import unittest

from contextlib import contextmanager

from qemu.machine import qtest
from qemu.qmp.legacy import QMPMessage, QEMUMonitorProtocol
from qemu.utils import VerboseProcessError

# Use this logger for logging messages directly from the iotests module
logger = logging.getLogger('qemu.iotests')
logger.addHandler(logging.NullHandler())

# Use this logger for messages that ought to be used for diff output.
test_logger = logging.getLogger('qemu.iotests.diff_io')


faulthandler.enable()

# This will not work if arguments contain spaces but is necessary if we
# want to support the override options that ./check supports.
qemu_img_args = [os.environ.get('QEMU_IMG_PROG', 'qemu-img')]
if os.environ.get('QEMU_IMG_OPTIONS'):
    qemu_img_args += os.environ['QEMU_IMG_OPTIONS'].strip().split(' ')

qemu_io_args = [os.environ.get('QEMU_IO_PROG', 'qemu-io')]
if os.environ.get('QEMU_IO_OPTIONS'):
    qemu_io_args += os.environ['QEMU_IO_OPTIONS'].strip().split(' ')

qemu_io_args_no_fmt = [os.environ.get('QEMU_IO_PROG', 'qemu-io')]
if os.environ.get('QEMU_IO_OPTIONS_NO_FMT'):
    qemu_io_args_no_fmt += \
        os.environ['QEMU_IO_OPTIONS_NO_FMT'].strip().split(' ')

qemu_nbd_prog = os.environ.get('QEMU_NBD_PROG', 'qemu-nbd')
qemu_nbd_args = [qemu_nbd_prog]
if os.environ.get('QEMU_NBD_OPTIONS'):
    qemu_nbd_args += os.environ['QEMU_NBD_OPTIONS'].strip().split(' ')

qemu_prog = os.environ.get('QEMU_PROG', 'qemu')
qemu_opts = os.environ.get('QEMU_OPTIONS', '').strip().split(' ')

qsd_prog = os.environ.get('QSD_PROG', 'qemu-storage-daemon')

gdb_qemu_env = os.environ.get('GDB_OPTIONS')
qemu_gdb = []
if gdb_qemu_env:
    qemu_gdb = ['gdbserver'] + gdb_qemu_env.strip().split(' ')

qemu_print = os.environ.get('PRINT_QEMU', False)

imgfmt = os.environ.get('IMGFMT', 'raw')
imgproto = os.environ.get('IMGPROTO', 'file')

try:
    test_dir = os.environ['TEST_DIR']
    sock_dir = os.environ['SOCK_DIR']
    cachemode = os.environ['CACHEMODE']
    aiomode = os.environ['AIOMODE']
    qemu_default_machine = os.environ['QEMU_DEFAULT_MACHINE']
except KeyError:
    # We are using these variables as proxies to indicate that we're
    # not being run via "check". There may be other things set up by
    # "check" that individual test cases rely on.
    sys.stderr.write('Please run this test via the "check" script\n')
    sys.exit(os.EX_USAGE)

qemu_valgrind = []
if os.environ.get('VALGRIND_QEMU') == "y" and \
    os.environ.get('NO_VALGRIND') != "y":
    valgrind_logfile = "--log-file=" + test_dir
    # %p allows to put the valgrind process PID, since
    # we don't know it a priori (subprocess.Popen is
    # not yet invoked)
    valgrind_logfile += "/%p.valgrind"

    qemu_valgrind = ['valgrind', valgrind_logfile, '--error-exitcode=99']

luks_default_secret_object = 'secret,id=keysec0,data=' + \
                             os.environ.get('IMGKEYSECRET', '')
luks_default_key_secret_opt = 'key-secret=keysec0'

sample_img_dir = os.environ['SAMPLE_IMG_DIR']


@contextmanager
def change_log_level(
        logger_name: str, level: int = logging.CRITICAL) -> Iterator[None]:
    """
    Utility function for temporarily changing the log level of a logger.

    This can be used to silence errors that are expected or uninteresting.
    """
    _logger = logging.getLogger(logger_name)
    current_level = _logger.level
    _logger.setLevel(level)

    try:
        yield
    finally:
        _logger.setLevel(current_level)


def unarchive_sample_image(sample, fname):
    sample_fname = os.path.join(sample_img_dir, sample + '.bz2')
    with bz2.open(sample_fname) as f_in, open(fname, 'wb') as f_out:
        shutil.copyfileobj(f_in, f_out)


def qemu_tool_popen(args: Sequence[str],
                    connect_stderr: bool = True) -> 'subprocess.Popen[str]':
    stderr = subprocess.STDOUT if connect_stderr else None
    # pylint: disable=consider-using-with
    return subprocess.Popen(args,
                            stdout=subprocess.PIPE,
                            stderr=stderr,
                            universal_newlines=True)


def qemu_tool_pipe_and_status(tool: str, args: Sequence[str],
                              connect_stderr: bool = True,
                              drop_successful_output: bool = False) \
        -> Tuple[str, int]:
    """
    Run a tool and return both its output and its exit code
    """
    with qemu_tool_popen(args, connect_stderr) as subp:
        output = subp.communicate()[0]
        if subp.returncode < 0:
            cmd = ' '.join(args)
            sys.stderr.write(f'{tool} received signal \
                               {-subp.returncode}: {cmd}\n')
        if drop_successful_output and subp.returncode == 0:
            output = ''
        return (output, subp.returncode)

def qemu_img_create_prepare_args(args: List[str]) -> List[str]:
    if not args or args[0] != 'create':
        return list(args)
    args = args[1:]

    p = argparse.ArgumentParser(allow_abbrev=False)
    # -o option may be specified several times
    p.add_argument('-o', action='append', default=[])
    p.add_argument('-f')
    parsed, remaining = p.parse_known_args(args)

    opts_list = parsed.o

    result = ['create']
    if parsed.f is not None:
        result += ['-f', parsed.f]

    # IMGOPTS most probably contain options specific for the selected format,
    # like extended_l2 or compression_type for qcow2. Test may want to create
    # additional images in other formats that doesn't support these options.
    # So, use IMGOPTS only for images created in imgfmt format.
    imgopts = os.environ.get('IMGOPTS')
    if imgopts and parsed.f == imgfmt:
        opts_list.insert(0, imgopts)

    # default luks support
    if parsed.f == 'luks' and \
            all('key-secret' not in opts for opts in opts_list):
        result += ['--object', luks_default_secret_object]
        opts_list.append(luks_default_key_secret_opt)

    for opts in opts_list:
        result += ['-o', opts]

    result += remaining

    return result


def qemu_tool(*args: str, check: bool = True, combine_stdio: bool = True
              ) -> 'subprocess.CompletedProcess[str]':
    """
    Run a qemu tool and return its status code and console output.

    :param args: full command line to run.
    :param check: Enforce a return code of zero.
    :param combine_stdio: set to False to keep stdout/stderr separated.

    :raise VerboseProcessError:
        When the return code is negative, or on any non-zero exit code
        when 'check=True' was provided (the default). This exception has
        'stdout', 'stderr', and 'returncode' properties that may be
        inspected to show greater detail. If this exception is not
        handled, the command-line, return code, and all console output
        will be included at the bottom of the stack trace.

    :return:
        a CompletedProcess. This object has args, returncode, and stdout
        properties. If streams are not combined, it will also have a
        stderr property.
    """
    subp = subprocess.run(
        args,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT if combine_stdio else subprocess.PIPE,
        universal_newlines=True,
        check=False
    )

    if check and subp.returncode or (subp.returncode < 0):
        raise VerboseProcessError(
            subp.returncode, args,
            output=subp.stdout,
            stderr=subp.stderr,
        )

    return subp


def qemu_img(*args: str, check: bool = True, combine_stdio: bool = True
             ) -> 'subprocess.CompletedProcess[str]':
    """
    Run QEMU_IMG_PROG and return its status code and console output.

    This function always prepends QEMU_IMG_OPTIONS and may further alter
    the args for 'create' commands.

    See `qemu_tool()` for greater detail.
    """
    full_args = qemu_img_args + qemu_img_create_prepare_args(list(args))
    return qemu_tool(*full_args, check=check, combine_stdio=combine_stdio)


def ordered_qmp(qmsg, conv_keys=True):
    # Dictionaries are not ordered prior to 3.6, therefore:
    if isinstance(qmsg, list):
        return [ordered_qmp(atom) for atom in qmsg]
    if isinstance(qmsg, dict):
        od = OrderedDict()
        for k, v in sorted(qmsg.items()):
            if conv_keys:
                k = k.replace('_', '-')
            od[k] = ordered_qmp(v, conv_keys=False)
        return od
    return qmsg

def qemu_img_create(*args: str) -> 'subprocess.CompletedProcess[str]':
    return qemu_img('create', *args)

def qemu_img_json(*args: str) -> Any:
    """
    Run qemu-img and return its output as deserialized JSON.

    :raise CalledProcessError:
        When qemu-img crashes, or returns a non-zero exit code without
        producing a valid JSON document to stdout.
    :raise JSONDecoderError:
        When qemu-img returns 0, but failed to produce a valid JSON document.

    :return: A deserialized JSON object; probably a dict[str, Any].
    """
    try:
        res = qemu_img(*args, combine_stdio=False)
    except subprocess.CalledProcessError as exc:
        # Terminated due to signal. Don't bother.
        if exc.returncode < 0:
            raise

        # Commands like 'check' can return failure (exit codes 2 and 3)
        # to indicate command completion, but with errors found. For
        # multi-command flexibility, ignore the exact error codes and
        # *try* to load JSON.
        try:
            return json.loads(exc.stdout)
        except json.JSONDecodeError:
            # Nope. This thing is toast. Raise the /process/ error.
            pass
        raise

    return json.loads(res.stdout)

def qemu_img_measure(*args: str) -> Any:
    return qemu_img_json("measure", "--output", "json", *args)

def qemu_img_check(*args: str) -> Any:
    return qemu_img_json("check", "--output", "json", *args)

def qemu_img_info(*args: str) -> Any:
    return qemu_img_json('info', "--output", "json", *args)

def qemu_img_map(*args: str) -> Any:
    return qemu_img_json('map', "--output", "json", *args)

def qemu_img_log(*args: str, check: bool = True
                 ) -> 'subprocess.CompletedProcess[str]':
    result = qemu_img(*args, check=check)
    log(result.stdout, filters=[filter_testfiles])
    return result

def img_info_log(filename: str, filter_path: Optional[str] = None,
                 use_image_opts: bool = False, extra_args: Sequence[str] = (),
                 check: bool = True, drop_child_info: bool = True,
                 ) -> None:
    args = ['info']
    if use_image_opts:
        args.append('--image-opts')
    else:
        args += ['-f', imgfmt]
    args += extra_args
    args.append(filename)

    output = qemu_img(*args, check=check).stdout
    if not filter_path:
        filter_path = filename
    log(filter_img_info(output, filter_path, drop_child_info))

def qemu_io_wrap_args(args: Sequence[str]) -> List[str]:
    if '-f' in args or '--image-opts' in args:
        return qemu_io_args_no_fmt + list(args)
    else:
        return qemu_io_args + list(args)

def qemu_io_popen(*args):
    return qemu_tool_popen(qemu_io_wrap_args(args))

def qemu_io(*args: str, check: bool = True, combine_stdio: bool = True
            ) -> 'subprocess.CompletedProcess[str]':
    """
    Run QEMU_IO_PROG and return the status code and console output.

    This function always prepends either QEMU_IO_OPTIONS or
    QEMU_IO_OPTIONS_NO_FMT.
    """
    return qemu_tool(*qemu_io_wrap_args(args),
                     check=check, combine_stdio=combine_stdio)

def qemu_io_log(*args: str, check: bool = True
                ) -> 'subprocess.CompletedProcess[str]':
    result = qemu_io(*args, check=check)
    log(result.stdout, filters=[filter_testfiles, filter_qemu_io])
    return result

class QemuIoInteractive:
    def __init__(self, *args):
        self.args = qemu_io_wrap_args(args)
        # We need to keep the Popen objext around, and not
        # close it immediately. Therefore, disable the pylint check:
        # pylint: disable=consider-using-with
        self._p = subprocess.Popen(self.args, stdin=subprocess.PIPE,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.STDOUT,
                                   universal_newlines=True)
        out = self._p.stdout.read(9)
        if out != 'qemu-io> ':
            # Most probably qemu-io just failed to start.
            # Let's collect the whole output and exit.
            out += self._p.stdout.read()
            self._p.wait(timeout=1)
            raise ValueError(out)

    def close(self):
        self._p.communicate('q\n')

    def _read_output(self):
        pattern = 'qemu-io> '
        n = len(pattern)
        pos = 0
        s = []
        while pos != n:
            c = self._p.stdout.read(1)
            # check unexpected EOF
            assert c != ''
            s.append(c)
            if c == pattern[pos]:
                pos += 1
            else:
                pos = 0

        return ''.join(s[:-n])

    def cmd(self, cmd):
        # quit command is in close(), '\n' is added automatically
        assert '\n' not in cmd
        cmd = cmd.strip()
        assert cmd not in ('q', 'quit')
        self._p.stdin.write(cmd + '\n')
        self._p.stdin.flush()
        return self._read_output()


class QemuStorageDaemon:
    _qmp: Optional[QEMUMonitorProtocol] = None
    _qmpsock: Optional[str] = None
    # Python < 3.8 would complain if this type were not a string literal
    # (importing `annotations` from `__future__` would work; but not on <= 3.6)
    _p: 'Optional[subprocess.Popen[bytes]]' = None

    def __init__(self, *args: str, instance_id: str = 'a', qmp: bool = False):
        assert '--pidfile' not in args
        self.pidfile = os.path.join(test_dir, f'qsd-{instance_id}-pid')
        all_args = [qsd_prog] + list(args) + ['--pidfile', self.pidfile]

        if qmp:
            self._qmpsock = os.path.join(sock_dir, f'qsd-{instance_id}.sock')
            all_args += ['--chardev',
                         f'socket,id=qmp-sock,path={self._qmpsock}',
                         '--monitor', 'qmp-sock']

            self._qmp = QEMUMonitorProtocol(self._qmpsock, server=True)

        # Cannot use with here, we want the subprocess to stay around
        # pylint: disable=consider-using-with
        self._p = subprocess.Popen(all_args)
        if self._qmp is not None:
            self._qmp.accept()
        while not os.path.exists(self.pidfile):
            if self._p.poll() is not None:
                cmd = ' '.join(all_args)
                raise RuntimeError(
                    'qemu-storage-daemon terminated with exit code ' +
                    f'{self._p.returncode}: {cmd}')

            time.sleep(0.01)

        with open(self.pidfile, encoding='utf-8') as f:
            self._pid = int(f.read().strip())

        assert self._pid == self._p.pid

    def qmp(self, cmd: str, args: Optional[Dict[str, object]] = None) \
            -> QMPMessage:
        assert self._qmp is not None
        return self._qmp.cmd(cmd, args)

    def stop(self, kill_signal=15):
        self._p.send_signal(kill_signal)
        self._p.wait()
        self._p = None

        if self._qmp:
            self._qmp.close()

        if self._qmpsock is not None:
            try:
                os.remove(self._qmpsock)
            except OSError:
                pass
        try:
            os.remove(self.pidfile)
        except OSError:
            pass

    def __del__(self):
        if self._p is not None:
            self.stop(kill_signal=9)


def qemu_nbd(*args):
    '''Run qemu-nbd in daemon mode and return the parent's exit code'''
    return subprocess.call(qemu_nbd_args + ['--fork'] + list(args))

def qemu_nbd_early_pipe(*args: str) -> Tuple[int, str]:
    '''Run qemu-nbd in daemon mode and return both the parent's exit code
       and its output in case of an error'''
    full_args = qemu_nbd_args + ['--fork'] + list(args)
    output, returncode = qemu_tool_pipe_and_status('qemu-nbd', full_args,
                                                   connect_stderr=False)
    return returncode, output if returncode else ''

def qemu_nbd_list_log(*args: str) -> str:
    '''Run qemu-nbd to list remote exports'''
    full_args = [qemu_nbd_prog, '-L'] + list(args)
    output, _ = qemu_tool_pipe_and_status('qemu-nbd', full_args)
    log(output, filters=[filter_testfiles, filter_nbd_exports])
    return output

@contextmanager
def qemu_nbd_popen(*args):
    '''Context manager running qemu-nbd within the context'''
    pid_file = file_path("qemu_nbd_popen-nbd-pid-file")

    assert not os.path.exists(pid_file)

    cmd = list(qemu_nbd_args)
    cmd.extend(('--persistent', '--pid-file', pid_file))
    cmd.extend(args)

    log('Start NBD server')
    with subprocess.Popen(cmd) as p:
        try:
            while not os.path.exists(pid_file):
                if p.poll() is not None:
                    raise RuntimeError(
                        "qemu-nbd terminated with exit code {}: {}"
                        .format(p.returncode, ' '.join(cmd)))

                time.sleep(0.01)
            yield
        finally:
            if os.path.exists(pid_file):
                os.remove(pid_file)
            log('Kill NBD server')
            p.kill()
            p.wait()

def compare_images(img1: str, img2: str,
                   fmt1: str = imgfmt, fmt2: str = imgfmt) -> bool:
    """
    Compare two images with QEMU_IMG; return True if they are identical.

    :raise CalledProcessError:
        when qemu-img crashes or returns a status code of anything other
        than 0 (identical) or 1 (different).
    """
    try:
        qemu_img('compare', '-f', fmt1, '-F', fmt2, img1, img2)
        return True
    except subprocess.CalledProcessError as exc:
        if exc.returncode == 1:
            return False
        raise

def create_image(name, size):
    '''Create a fully-allocated raw image with sector markers'''
    with open(name, 'wb') as file:
        i = 0
        while i < size:
            sector = struct.pack('>l504xl', i // 512, i // 512)
            file.write(sector)
            i = i + 512

def image_size(img: str) -> int:
    """Return image's virtual size"""
    value = qemu_img_info('-f', imgfmt, img)['virtual-size']
    if not isinstance(value, int):
        type_name = type(value).__name__
        raise TypeError("Expected 'int' for 'virtual-size', "
                        f"got '{value}' of type '{type_name}'")
    return value

def is_str(val):
    return isinstance(val, str)

test_dir_re = re.compile(r"%s" % test_dir)
def filter_test_dir(msg):
    return test_dir_re.sub("TEST_DIR", msg)

win32_re = re.compile(r"\r")
def filter_win32(msg):
    return win32_re.sub("", msg)

qemu_io_re = re.compile(r"[0-9]* ops; [0-9\/:. sec]* "
                        r"\([0-9\/.inf]* [EPTGMKiBbytes]*\/sec "
                        r"and [0-9\/.inf]* ops\/sec\)")
def filter_qemu_io(msg):
    msg = filter_win32(msg)
    return qemu_io_re.sub("X ops; XX:XX:XX.X "
                          "(XXX YYY/sec and XXX ops/sec)", msg)

chown_re = re.compile(r"chown [0-9]+:[0-9]+")
def filter_chown(msg):
    return chown_re.sub("chown UID:GID", msg)

def filter_qmp_event(event):
    '''Filter a QMP event dict'''
    event = dict(event)
    if 'timestamp' in event:
        event['timestamp']['seconds'] = 'SECS'
        event['timestamp']['microseconds'] = 'USECS'
    return event

def filter_qmp(qmsg, filter_fn):
    '''Given a string filter, filter a QMP object's values.
    filter_fn takes a (key, value) pair.'''
    # Iterate through either lists or dicts;
    if isinstance(qmsg, list):
        items = enumerate(qmsg)
    elif isinstance(qmsg, dict):
        items = qmsg.items()
    else:
        return filter_fn(None, qmsg)

    for k, v in items:
        if isinstance(v, (dict, list)):
            qmsg[k] = filter_qmp(v, filter_fn)
        else:
            qmsg[k] = filter_fn(k, v)
    return qmsg

def filter_testfiles(msg):
    pref1 = os.path.join(test_dir, "%s-" % (os.getpid()))
    pref2 = os.path.join(sock_dir, "%s-" % (os.getpid()))
    return msg.replace(pref1, 'TEST_DIR/PID-').replace(pref2, 'SOCK_DIR/PID-')

def filter_qmp_testfiles(qmsg):
    def _filter(_key, value):
        if is_str(value):
            return filter_testfiles(value)
        return value
    return filter_qmp(qmsg, _filter)

def filter_virtio_scsi(output: str) -> str:
    return re.sub(r'(virtio-scsi)-(ccw|pci)', r'\1', output)

def filter_qmp_virtio_scsi(qmsg):
    def _filter(_key, value):
        if is_str(value):
            return filter_virtio_scsi(value)
        return value
    return filter_qmp(qmsg, _filter)

def filter_generated_node_ids(msg):
    return re.sub("#block[0-9]+", "NODE_NAME", msg)

def filter_img_info(output: str, filename: str,
                    drop_child_info: bool = True) -> str:
    lines = []
    drop_indented = False
    for line in output.split('\n'):
        if 'disk size' in line or 'actual-size' in line:
            continue

        # Drop child node info
        if drop_indented:
            if line.startswith(' '):
                continue
            drop_indented = False
        if drop_child_info and "Child node '/" in line:
            drop_indented = True
            continue

        line = line.replace(filename, 'TEST_IMG')
        line = filter_testfiles(line)
        line = line.replace(imgfmt, 'IMGFMT')
        line = re.sub('iters: [0-9]+', 'iters: XXX', line)
        line = re.sub('uuid: [-a-f0-9]+',
                      'uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
                      line)
        line = re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line)
        line = re.sub('(compression type: )(zlib|zstd)', r'\1COMPRESSION_TYPE',
                      line)
        lines.append(line)
    return '\n'.join(lines)

def filter_imgfmt(msg):
    return msg.replace(imgfmt, 'IMGFMT')

def filter_qmp_imgfmt(qmsg):
    def _filter(_key, value):
        if is_str(value):
            return filter_imgfmt(value)
        return value
    return filter_qmp(qmsg, _filter)

def filter_nbd_exports(output: str) -> str:
    return re.sub(r'((min|opt|max) block): [0-9]+', r'\1: XXX', output)


Msg = TypeVar('Msg', Dict[str, Any], List[Any], str)

def log(msg: Msg,
        filters: Iterable[Callable[[Msg], Msg]] = (),
        indent: Optional[int] = None) -> None:
    """
    Logs either a string message or a JSON serializable message (like QMP).
    If indent is provided, JSON serializable messages are pretty-printed.
    """
    for flt in filters:
        msg = flt(msg)
    if isinstance(msg, (dict, list)):
        # Don't sort if it's already sorted
        do_sort = not isinstance(msg, OrderedDict)
        test_logger.info(json.dumps(msg, sort_keys=do_sort, indent=indent))
    else:
        test_logger.info(msg)

class Timeout:
    def __init__(self, seconds, errmsg="Timeout"):
        self.seconds = seconds
        self.errmsg = errmsg
    def __enter__(self):
        if qemu_gdb or qemu_valgrind:
            return self
        signal.signal(signal.SIGALRM, self.timeout)
        signal.setitimer(signal.ITIMER_REAL, self.seconds)
        return self
    def __exit__(self, exc_type, value, traceback):
        if qemu_gdb or qemu_valgrind:
            return False
        signal.setitimer(signal.ITIMER_REAL, 0)
        return False
    def timeout(self, signum, frame):
        raise TimeoutError(self.errmsg)

def file_pattern(name):
    return "{0}-{1}".format(os.getpid(), name)

class FilePath:
    """
    Context manager generating multiple file names. The generated files are
    removed when exiting the context.

    Example usage:

        with FilePath('a.img', 'b.img') as (img_a, img_b):
            # Use img_a and img_b here...

        # a.img and b.img are automatically removed here.

    By default images are created in iotests.test_dir. To create sockets use
    iotests.sock_dir:

       with FilePath('a.sock', base_dir=iotests.sock_dir) as sock:

    For convenience, calling with one argument yields a single file instead of
    a tuple with one item.

    """
    def __init__(self, *names, base_dir=test_dir):
        self.paths = [os.path.join(base_dir, file_pattern(name))
                      for name in names]

    def __enter__(self):
        if len(self.paths) == 1:
            return self.paths[0]
        else:
            return self.paths

    def __exit__(self, exc_type, exc_val, exc_tb):
        for path in self.paths:
            try:
                os.remove(path)
            except OSError:
                pass
        return False


def try_remove(img):
    try:
        os.remove(img)
    except OSError:
        pass

def file_path_remover():
    for path in reversed(file_path_remover.paths):
        try_remove(path)


def file_path(*names, base_dir=test_dir):
    ''' Another way to get auto-generated filename that cleans itself up.

    Use is as simple as:

    img_a, img_b = file_path('a.img', 'b.img')
    sock = file_path('socket')
    '''

    if not hasattr(file_path_remover, 'paths'):
        file_path_remover.paths = []
        atexit.register(file_path_remover)

    paths = []
    for name in names:
        filename = file_pattern(name)
        path = os.path.join(base_dir, filename)
        file_path_remover.paths.append(path)
        paths.append(path)

    return paths[0] if len(paths) == 1 else paths

def remote_filename(path):
    if imgproto == 'file':
        return path
    elif imgproto == 'ssh':
        return "ssh://%s@127.0.0.1:22%s" % (os.environ.get('USER'), path)
    else:
        raise ValueError("Protocol %s not supported" % (imgproto))

class VM(qtest.QEMUQtestMachine):
    '''A QEMU VM'''

    def __init__(self, path_suffix=''):
        name = "qemu%s-%d" % (path_suffix, os.getpid())
        timer = 15.0 if not (qemu_gdb or qemu_valgrind) else None
        if qemu_gdb and qemu_valgrind:
            sys.stderr.write('gdb and valgrind are mutually exclusive\n')
            sys.exit(1)
        wrapper = qemu_gdb if qemu_gdb else qemu_valgrind
        super().__init__(qemu_prog, qemu_opts, wrapper=wrapper,
                         name=name,
                         base_temp_dir=test_dir,
                         sock_dir=sock_dir, qmp_timer=timer)
        self._num_drives = 0

    def _post_shutdown(self) -> None:
        super()._post_shutdown()
        if not qemu_valgrind or not self._popen:
            return
        valgrind_filename = f"{test_dir}/{self._popen.pid}.valgrind"
        if self.exitcode() == 99:
            with open(valgrind_filename, encoding='utf-8') as f:
                print(f.read())
        else:
            os.remove(valgrind_filename)

    def _pre_launch(self) -> None:
        super()._pre_launch()
        if qemu_print:
            # set QEMU binary output to stdout
            self._close_qemu_log_file()

    def add_object(self, opts):
        self._args.append('-object')
        self._args.append(opts)
        return self

    def add_device(self, opts):
        self._args.append('-device')
        self._args.append(opts)
        return self

    def add_drive_raw(self, opts):
        self._args.append('-drive')
        self._args.append(opts)
        return self

    def add_drive(self, path, opts='', interface='virtio', img_format=imgfmt):
        '''Add a virtio-blk drive to the VM'''
        options = ['if=%s' % interface,
                   'id=drive%d' % self._num_drives]

        if path is not None:
            options.append('file=%s' % path)
            options.append('format=%s' % img_format)
            options.append('cache=%s' % cachemode)
            options.append('aio=%s' % aiomode)

        if opts:
            options.append(opts)

        if img_format == 'luks' and 'key-secret' not in opts:
            # default luks support
            if luks_default_secret_object not in self._args:
                self.add_object(luks_default_secret_object)

            options.append(luks_default_key_secret_opt)

        self._args.append('-drive')
        self._args.append(','.join(options))
        self._num_drives += 1
        return self

    def add_blockdev(self, opts):
        self._args.append('-blockdev')
        if isinstance(opts, str):
            self._args.append(opts)
        else:
            self._args.append(','.join(opts))
        return self

    def add_incoming(self, addr):
        self._args.append('-incoming')
        self._args.append(addr)
        return self

    def hmp(self, command_line: str, use_log: bool = False) -> QMPMessage:
        cmd = 'human-monitor-command'
        kwargs: Dict[str, Any] = {'command-line': command_line}
        if use_log:
            return self.qmp_log(cmd, **kwargs)
        else:
            return self.qmp(cmd, **kwargs)

    def pause_drive(self, drive: str, event: Optional[str] = None) -> None:
        """Pause drive r/w operations"""
        if not event:
            self.pause_drive(drive, "read_aio")
            self.pause_drive(drive, "write_aio")
            return
        self.hmp(f'qemu-io {drive} "break {event} bp_{drive}"')

    def resume_drive(self, drive: str) -> None:
        """Resume drive r/w operations"""
        self.hmp(f'qemu-io {drive} "remove_break bp_{drive}"')

    def hmp_qemu_io(self, drive: str, cmd: str,
                    use_log: bool = False, qdev: bool = False) -> QMPMessage:
        """Write to a given drive using an HMP command"""
        d = '-d ' if qdev else ''
        return self.hmp(f'qemu-io {d}{drive} "{cmd}"', use_log=use_log)

    def flatten_qmp_object(self, obj, output=None, basestr=''):
        if output is None:
            output = {}
        if isinstance(obj, list):
            for i, item in enumerate(obj):
                self.flatten_qmp_object(item, output, basestr + str(i) + '.')
        elif isinstance(obj, dict):
            for key in obj:
                self.flatten_qmp_object(obj[key], output, basestr + key + '.')
        else:
            output[basestr[:-1]] = obj # Strip trailing '.'
        return output

    def qmp_to_opts(self, obj):
        obj = self.flatten_qmp_object(obj)
        output_list = []
        for key in obj:
            output_list += [key + '=' + obj[key]]
        return ','.join(output_list)

    def get_qmp_events_filtered(self, wait=60.0):
        result = []
        for ev in self.get_qmp_events(wait=wait):
            result.append(filter_qmp_event(ev))
        return result

    def qmp_log(self, cmd, filters=(), indent=None, **kwargs):
        full_cmd = OrderedDict((
            ("execute", cmd),
            ("arguments", ordered_qmp(kwargs))
        ))
        log(full_cmd, filters, indent=indent)
        result = self.qmp(cmd, **kwargs)
        log(result, filters, indent=indent)
        return result

    # Returns None on success, and an error string on failure
    def run_job(self, job: str, auto_finalize: bool = True,
                auto_dismiss: bool = False,
                pre_finalize: Optional[Callable[[], None]] = None,
                cancel: bool = False, wait: float = 60.0,
                filters: Iterable[Callable[[Any], Any]] = (),
                ) -> Optional[str]:
        """
        run_job moves a job from creation through to dismissal.

        :param job: String. ID of recently-launched job
        :param auto_finalize: Bool. True if the job was launched with
                              auto_finalize. Defaults to True.
        :param auto_dismiss: Bool. True if the job was launched with
                             auto_dismiss=True. Defaults to False.
        :param pre_finalize: Callback. A callable that takes no arguments to be
                             invoked prior to issuing job-finalize, if any.
        :param cancel: Bool. When true, cancels the job after the pre_finalize
                       callback.
        :param wait: Float. Timeout value specifying how long to wait for any
                     event, in seconds. Defaults to 60.0.
        """
        match_device = {'data': {'device': job}}
        match_id = {'data': {'id': job}}
        events = [
            ('BLOCK_JOB_COMPLETED', match_device),
            ('BLOCK_JOB_CANCELLED', match_device),
            ('BLOCK_JOB_ERROR', match_device),
            ('BLOCK_JOB_READY', match_device),
            ('BLOCK_JOB_PENDING', match_id),
            ('JOB_STATUS_CHANGE', match_id)
        ]
        error = None
        while True:
            ev = filter_qmp_event(self.events_wait(events, timeout=wait))
            if ev['event'] != 'JOB_STATUS_CHANGE':
                log(ev, filters=filters)
                continue
            status = ev['data']['status']
            if status == 'aborting':
                result = self.qmp('query-jobs')
                for j in result['return']:
                    if j['id'] == job:
                        error = j['error']
                        log('Job failed: %s' % (j['error']), filters=filters)
            elif status == 'ready':
                self.qmp_log('job-complete', id=job, filters=filters)
            elif status == 'pending' and not auto_finalize:
                if pre_finalize:
                    pre_finalize()
                if cancel:
                    self.qmp_log('job-cancel', id=job, filters=filters)
                else:
                    self.qmp_log('job-finalize', id=job, filters=filters)
            elif status == 'concluded' and not auto_dismiss:
                self.qmp_log('job-dismiss', id=job, filters=filters)
            elif status == 'null':
                return error

    # Returns None on success, and an error string on failure
    def blockdev_create(self, options, job_id='job0', filters=None):
        if filters is None:
            filters = [filter_qmp_testfiles]
        result = self.qmp_log('blockdev-create', filters=filters,
                              job_id=job_id, options=options)

        if 'return' in result:
            assert result['return'] == {}
            job_result = self.run_job(job_id, filters=filters)
        else:
            job_result = result['error']

        log("")
        return job_result

    def enable_migration_events(self, name):
        log('Enabling migration QMP events on %s...' % name)
        log(self.qmp('migrate-set-capabilities', capabilities=[
            {
                'capability': 'events',
                'state': True
            }
        ]))

    def wait_migration(self, expect_runstate: Optional[str]) -> bool:
        while True:
            event = self.event_wait('MIGRATION')
            # We use the default timeout, and with a timeout, event_wait()
            # never returns None
            assert event

            log(event, filters=[filter_qmp_event])
            if event['data']['status'] in ('completed', 'failed'):
                break

        if event['data']['status'] == 'completed':
            # The event may occur in finish-migrate, so wait for the expected
            # post-migration runstate
            runstate = None
            while runstate != expect_runstate:
                runstate = self.qmp('query-status')['return']['status']
            return True
        else:
            return False

    def node_info(self, node_name):
        nodes = self.qmp('query-named-block-nodes')
        for x in nodes['return']:
            if x['node-name'] == node_name:
                return x
        return None

    def query_bitmaps(self):
        res = self.qmp("query-named-block-nodes")
        return {device['node-name']: device['dirty-bitmaps']
                for device in res['return'] if 'dirty-bitmaps' in device}

    def get_bitmap(self, node_name, bitmap_name, recording=None, bitmaps=None):
        """
        get a specific bitmap from the object returned by query_bitmaps.
        :param recording: If specified, filter results by the specified value.
        :param bitmaps: If specified, use it instead of call query_bitmaps()
        """
        if bitmaps is None:
            bitmaps = self.query_bitmaps()

        for bitmap in bitmaps[node_name]:
            if bitmap.get('name', '') == bitmap_name:
                if recording is None or bitmap.get('recording') == recording:
                    return bitmap
        return None

    def check_bitmap_status(self, node_name, bitmap_name, fields):
        ret = self.get_bitmap(node_name, bitmap_name)

        return fields.items() <= ret.items()

    def assert_block_path(self, root, path, expected_node, graph=None):
        """
        Check whether the node under the given path in the block graph
        is @expected_node.

        @root is the node name of the node where the @path is rooted.

        @path is a string that consists of child names separated by
        slashes.  It must begin with a slash.

        Examples for @root + @path:
          - root="qcow2-node", path="/backing/file"
          - root="quorum-node", path="/children.2/file"

        Hypothetically, @path could be empty, in which case it would
        point to @root.  However, in practice this case is not useful
        and hence not allowed.

        @expected_node may be None.  (All elements of the path but the
        leaf must still exist.)

        @graph may be None or the result of an x-debug-query-block-graph
        call that has already been performed.
        """
        if graph is None:
            graph = self.qmp('x-debug-query-block-graph')['return']

        iter_path = iter(path.split('/'))

        # Must start with a /
        assert next(iter_path) == ''

        node = next((node for node in graph['nodes'] if node['name'] == root),
                    None)

        # An empty @path is not allowed, so the root node must be present
        assert node is not None, 'Root node %s not found' % root

        for child_name in iter_path:
            assert node is not None, 'Cannot follow path %s%s' % (root, path)

            try:
                node_id = next(edge['child'] for edge in graph['edges']
                               if (edge['parent'] == node['id'] and
                                   edge['name'] == child_name))

                node = next(node for node in graph['nodes']
                            if node['id'] == node_id)

            except StopIteration:
                node = None

        if node is None:
            assert expected_node is None, \
                   'No node found under %s (but expected %s)' % \
                   (path, expected_node)
        else:
            assert node['name'] == expected_node, \
                   'Found node %s under %s (but expected %s)' % \
                   (node['name'], path, expected_node)

index_re = re.compile(r'([^\[]+)\[([^\]]+)\]')

class QMPTestCase(unittest.TestCase):
    '''Abstract base class for QMP test cases'''

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Many users of this class set a VM property we rely on heavily
        # in the methods below.
        self.vm = None

    def dictpath(self, d, path):
        '''Traverse a path in a nested dict'''
        for component in path.split('/'):
            m = index_re.match(component)
            if m:
                component, idx = m.groups()
                idx = int(idx)

            if not isinstance(d, dict) or component not in d:
                self.fail(f'failed path traversal for "{path}" in "{d}"')
            d = d[component]

            if m:
                if not isinstance(d, list):
                    self.fail(f'path component "{component}" in "{path}" '
                              f'is not a list in "{d}"')
                try:
                    d = d[idx]
                except IndexError:
                    self.fail(f'invalid index "{idx}" in path "{path}" '
                              f'in "{d}"')
        return d

    def assert_qmp_absent(self, d, path):
        try:
            result = self.dictpath(d, path)
        except AssertionError:
            return
        self.fail('path "%s" has value "%s"' % (path, str(result)))

    def assert_qmp(self, d, path, value):
        '''Assert that the value for a specific path in a QMP dict
           matches.  When given a list of values, assert that any of
           them matches.'''

        result = self.dictpath(d, path)

        # [] makes no sense as a list of valid values, so treat it as
        # an actual single value.
        if isinstance(value, list) and value != []:
            for v in value:
                if result == v:
                    return
            self.fail('no match for "%s" in %s' % (str(result), str(value)))
        else:
            self.assertEqual(result, value,
                             '"%s" is "%s", expected "%s"'
                             % (path, str(result), str(value)))

    def assert_no_active_block_jobs(self):
        result = self.vm.qmp('query-block-jobs')
        self.assert_qmp(result, 'return', [])

    def assert_has_block_node(self, node_name=None, file_name=None):
        """Issue a query-named-block-nodes and assert node_name and/or
        file_name is present in the result"""
        def check_equal_or_none(a, b):
            return a is None or b is None or a == b
        assert node_name or file_name
        result = self.vm.qmp('query-named-block-nodes')
        for x in result["return"]:
            if check_equal_or_none(x.get("node-name"), node_name) and \
                    check_equal_or_none(x.get("file"), file_name):
                return
        self.fail("Cannot find %s %s in result:\n%s" %
                  (node_name, file_name, result))

    def assert_json_filename_equal(self, json_filename, reference):
        '''Asserts that the given filename is a json: filename and that its
           content is equal to the given reference object'''
        self.assertEqual(json_filename[:5], 'json:')
        self.assertEqual(
            self.vm.flatten_qmp_object(json.loads(json_filename[5:])),
            self.vm.flatten_qmp_object(reference)
        )

    def cancel_and_wait(self, drive='drive0', force=False,
                        resume=False, wait=60.0):
        '''Cancel a block job and wait for it to finish, returning the event'''
        result = self.vm.qmp('block-job-cancel', device=drive, force=force)
        self.assert_qmp(result, 'return', {})

        if resume:
            self.vm.resume_drive(drive)

        cancelled = False
        result = None
        while not cancelled:
            for event in self.vm.get_qmp_events(wait=wait):
                if event['event'] == 'BLOCK_JOB_COMPLETED' or \
                   event['event'] == 'BLOCK_JOB_CANCELLED':
                    self.assert_qmp(event, 'data/device', drive)
                    result = event
                    cancelled = True
                elif event['event'] == 'JOB_STATUS_CHANGE':
                    self.assert_qmp(event, 'data/id', drive)


        self.assert_no_active_block_jobs()
        return result

    def wait_until_completed(self, drive='drive0', check_offset=True,
                             wait=60.0, error=None):
        '''Wait for a block job to finish, returning the event'''
        while True:
            for event in self.vm.get_qmp_events(wait=wait):
                if event['event'] == 'BLOCK_JOB_COMPLETED':
                    self.assert_qmp(event, 'data/device', drive)
                    if error is None:
                        self.assert_qmp_absent(event, 'data/error')
                        if check_offset:
                            self.assert_qmp(event, 'data/offset',
                                            event['data']['len'])
                    else:
                        self.assert_qmp(event, 'data/error', error)
                    self.assert_no_active_block_jobs()
                    return event
                if event['event'] == 'JOB_STATUS_CHANGE':
                    self.assert_qmp(event, 'data/id', drive)

    def wait_ready(self, drive='drive0'):
        """Wait until a BLOCK_JOB_READY event, and return the event."""
        return self.vm.events_wait([
            ('BLOCK_JOB_READY',
             {'data': {'type': 'mirror', 'device': drive}}),
            ('BLOCK_JOB_READY',
             {'data': {'type': 'commit', 'device': drive}})
        ])

    def wait_ready_and_cancel(self, drive='drive0'):
        self.wait_ready(drive=drive)
        event = self.cancel_and_wait(drive=drive)
        self.assertEqual(event['event'], 'BLOCK_JOB_COMPLETED')
        self.assert_qmp(event, 'data/type', 'mirror')
        self.assert_qmp(event, 'data/offset', event['data']['len'])

    def complete_and_wait(self, drive='drive0', wait_ready=True,
                          completion_error=None):
        '''Complete a block job and wait for it to finish'''
        if wait_ready:
            self.wait_ready(drive=drive)

        result = self.vm.qmp('block-job-complete', device=drive)
        self.assert_qmp(result, 'return', {})

        event = self.wait_until_completed(drive=drive, error=completion_error)
        self.assertTrue(event['data']['type'] in ['mirror', 'commit'])

    def pause_wait(self, job_id='job0'):
        with Timeout(3, "Timeout waiting for job to pause"):
            while True:
                result = self.vm.qmp('query-block-jobs')
                found = False
                for job in result['return']:
                    if job['device'] == job_id:
                        found = True
                        if job['paused'] and not job['busy']:
                            return job
                        break
                assert found

    def pause_job(self, job_id='job0', wait=True):
        result = self.vm.qmp('block-job-pause', device=job_id)
        self.assert_qmp(result, 'return', {})
        if wait:
            return self.pause_wait(job_id)
        return result

    def case_skip(self, reason):
        '''Skip this test case'''
        case_notrun(reason)
        self.skipTest(reason)


def notrun(reason):
    '''Skip this test suite'''
    # Each test in qemu-iotests has a number ("seq")
    seq = os.path.basename(sys.argv[0])

    with open('%s/%s.notrun' % (test_dir, seq), 'w', encoding='utf-8') \
            as outfile:
        outfile.write(reason + '\n')
    logger.warning("%s not run: %s", seq, reason)
    sys.exit(0)

def case_notrun(reason):
    '''Mark this test case as not having been run (without actually
    skipping it, that is left to the caller).  See
    QMPTestCase.case_skip() for a variant that actually skips the
    current test case.'''

    # Each test in qemu-iotests has a number ("seq")
    seq = os.path.basename(sys.argv[0])

    with open('%s/%s.casenotrun' % (test_dir, seq), 'a', encoding='utf-8') \
            as outfile:
        outfile.write('    [case not run] ' + reason + '\n')

def _verify_image_format(supported_fmts: Sequence[str] = (),
                         unsupported_fmts: Sequence[str] = ()) -> None:
    if 'generic' in supported_fmts and \
            os.environ.get('IMGFMT_GENERIC', 'true') == 'true':
        # similar to
        #   _supported_fmt generic
        # for bash tests
        supported_fmts = ()

    not_sup = supported_fmts and (imgfmt not in supported_fmts)
    if not_sup or (imgfmt in unsupported_fmts):
        notrun('not suitable for this image format: %s' % imgfmt)

    if imgfmt == 'luks':
        verify_working_luks()

def _verify_protocol(supported: Sequence[str] = (),
                     unsupported: Sequence[str] = ()) -> None:
    assert not (supported and unsupported)

    if 'generic' in supported:
        return

    not_sup = supported and (imgproto not in supported)
    if not_sup or (imgproto in unsupported):
        notrun('not suitable for this protocol: %s' % imgproto)

def _verify_platform(supported: Sequence[str] = (),
                     unsupported: Sequence[str] = ()) -> None:
    if any((sys.platform.startswith(x) for x in unsupported)):
        notrun('not suitable for this OS: %s' % sys.platform)

    if supported:
        if not any((sys.platform.startswith(x) for x in supported)):
            notrun('not suitable for this OS: %s' % sys.platform)

def _verify_cache_mode(supported_cache_modes: Sequence[str] = ()) -> None:
    if supported_cache_modes and (cachemode not in supported_cache_modes):
        notrun('not suitable for this cache mode: %s' % cachemode)

def _verify_aio_mode(supported_aio_modes: Sequence[str] = ()) -> None:
    if supported_aio_modes and (aiomode not in supported_aio_modes):
        notrun('not suitable for this aio mode: %s' % aiomode)

def _verify_formats(required_formats: Sequence[str] = ()) -> None:
    usf_list = list(set(required_formats) - set(supported_formats()))
    if usf_list:
        notrun(f'formats {usf_list} are not whitelisted')


def _verify_virtio_blk() -> None:
    out = qemu_pipe('-M', 'none', '-device', 'help')
    if 'virtio-blk' not in out:
        notrun('Missing virtio-blk in QEMU binary')

def _verify_virtio_scsi_pci_or_ccw() -> None:
    out = qemu_pipe('-M', 'none', '-device', 'help')
    if 'virtio-scsi-pci' not in out and 'virtio-scsi-ccw' not in out:
        notrun('Missing virtio-scsi-pci or virtio-scsi-ccw in QEMU binary')


def _verify_imgopts(unsupported: Sequence[str] = ()) -> None:
    imgopts = os.environ.get('IMGOPTS')
    # One of usage examples for IMGOPTS is "data_file=$TEST_IMG.ext_data_file"
    # but it supported only for bash tests. We don't have a concept of global
    # TEST_IMG in iotests.py, not saying about somehow parsing $variables.
    # So, for simplicity let's just not support any IMGOPTS with '$' inside.
    unsup = list(unsupported) + ['$']
    if imgopts and any(x in imgopts for x in unsup):
        notrun(f'not suitable for this imgopts: {imgopts}')


def supports_quorum() -> bool:
    return 'quorum' in qemu_img('--help').stdout

def verify_quorum():
    '''Skip test suite if quorum support is not available'''
    if not supports_quorum():
        notrun('quorum support missing')

def has_working_luks() -> Tuple[bool, str]:
    """
    Check whether our LUKS driver can actually create images
    (this extends to LUKS encryption for qcow2).

    If not, return the reason why.
    """

    img_file = f'{test_dir}/luks-test.luks'
    res = qemu_img('create', '-f', 'luks',
                   '--object', luks_default_secret_object,
                   '-o', luks_default_key_secret_opt,
                   '-o', 'iter-time=10',
                   img_file, '1G',
                   check=False)
    try:
        os.remove(img_file)
    except OSError:
        pass

    if res.returncode:
        reason = res.stdout
        for line in res.stdout.splitlines():
            if img_file + ':' in line:
                reason = line.split(img_file + ':', 1)[1].strip()
                break

        return (False, reason)
    else:
        return (True, '')

def verify_working_luks():
    """
    Skip test suite if LUKS does not work
    """
    (working, reason) = has_working_luks()
    if not working:
        notrun(reason)

def supports_qcow2_zstd_compression() -> bool:
    img_file = f'{test_dir}/qcow2-zstd-test.qcow2'
    res = qemu_img('create', '-f', 'qcow2', '-o', 'compression_type=zstd',
                   img_file, '0',
                   check=False)
    try:
        os.remove(img_file)
    except OSError:
        pass

    if res.returncode == 1 and \
            "'compression-type' does not accept value 'zstd'" in res.stdout:
        return False
    else:
        return True

def verify_qcow2_zstd_compression():
    if not supports_qcow2_zstd_compression():
        notrun('zstd compression not supported')

def qemu_pipe(*args: str) -> str:
    """
    Run qemu with an option to print something and exit (e.g. a help option).

    :return: QEMU's stdout output.
    """
    full_args = [qemu_prog] + qemu_opts + list(args)
    output, _ = qemu_tool_pipe_and_status('qemu', full_args)
    return output

def supported_formats(read_only=False):
    '''Set 'read_only' to True to check ro-whitelist
       Otherwise, rw-whitelist is checked'''

    if not hasattr(supported_formats, "formats"):
        supported_formats.formats = {}

    if read_only not in supported_formats.formats:
        format_message = qemu_pipe("-drive", "format=help")
        line = 1 if read_only else 0
        supported_formats.formats[read_only] = \
            format_message.splitlines()[line].split(":")[1].split()

    return supported_formats.formats[read_only]

def skip_if_unsupported(required_formats=(), read_only=False):
    '''Skip Test Decorator
       Runs the test if all the required formats are whitelisted'''
    def skip_test_decorator(func):
        def func_wrapper(test_case: QMPTestCase, *args: List[Any],
                         **kwargs: Dict[str, Any]) -> None:
            if callable(required_formats):
                fmts = required_formats(test_case)
            else:
                fmts = required_formats

            usf_list = list(set(fmts) - set(supported_formats(read_only)))
            if usf_list:
                msg = f'{test_case}: formats {usf_list} are not whitelisted'
                test_case.case_skip(msg)
            else:
                func(test_case, *args, **kwargs)
        return func_wrapper
    return skip_test_decorator

def skip_for_formats(formats: Sequence[str] = ()) \
    -> Callable[[Callable[[QMPTestCase, List[Any], Dict[str, Any]], None]],
                Callable[[QMPTestCase, List[Any], Dict[str, Any]], None]]:
    '''Skip Test Decorator
       Skips the test for the given formats'''
    def skip_test_decorator(func):
        def func_wrapper(test_case: QMPTestCase, *args: List[Any],
                         **kwargs: Dict[str, Any]) -> None:
            if imgfmt in formats:
                msg = f'{test_case}: Skipped for format {imgfmt}'
                test_case.case_skip(msg)
            else:
                func(test_case, *args, **kwargs)
        return func_wrapper
    return skip_test_decorator

def skip_if_user_is_root(func):
    '''Skip Test Decorator
       Runs the test only without root permissions'''
    def func_wrapper(*args, **kwargs):
        if os.getuid() == 0:
            case_notrun('{}: cannot be run as root'.format(args[0]))
            return None
        else:
            return func(*args, **kwargs)
    return func_wrapper

# We need to filter out the time taken from the output so that
# qemu-iotest can reliably diff the results against master output,
# and hide skipped tests from the reference output.

class ReproducibleTestResult(unittest.TextTestResult):
    def addSkip(self, test, reason):
        # Same as TextTestResult, but print dot instead of "s"
        unittest.TestResult.addSkip(self, test, reason)
        if self.showAll:
            self.stream.writeln("skipped {0!r}".format(reason))
        elif self.dots:
            self.stream.write(".")
            self.stream.flush()

class ReproducibleStreamWrapper:
    def __init__(self, stream: TextIO):
        self.stream = stream

    def __getattr__(self, attr):
        if attr in ('stream', '__getstate__'):
            raise AttributeError(attr)
        return getattr(self.stream, attr)

    def write(self, arg=None):
        arg = re.sub(r'Ran (\d+) tests? in [\d.]+s', r'Ran \1 tests', arg)
        arg = re.sub(r' \(skipped=\d+\)', r'', arg)
        self.stream.write(arg)

class ReproducibleTestRunner(unittest.TextTestRunner):
    def __init__(self, stream: Optional[TextIO] = None,
                 resultclass: Type[unittest.TestResult] =
                 ReproducibleTestResult,
                 **kwargs: Any) -> None:
        rstream = ReproducibleStreamWrapper(stream or sys.stdout)
        super().__init__(stream=rstream,           # type: ignore
                         descriptions=True,
                         resultclass=resultclass,
                         **kwargs)

def execute_unittest(argv: List[str], debug: bool = False) -> None:
    """Executes unittests within the calling module."""

    # Some tests have warnings, especially ResourceWarnings for unclosed
    # files and sockets.  Ignore them for now to ensure reproducibility of
    # the test output.
    unittest.main(argv=argv,
                  testRunner=ReproducibleTestRunner,
                  verbosity=2 if debug else 1,
                  warnings=None if sys.warnoptions else 'ignore')

def execute_setup_common(supported_fmts: Sequence[str] = (),
                         supported_platforms: Sequence[str] = (),
                         supported_cache_modes: Sequence[str] = (),
                         supported_aio_modes: Sequence[str] = (),
                         unsupported_fmts: Sequence[str] = (),
                         supported_protocols: Sequence[str] = (),
                         unsupported_protocols: Sequence[str] = (),
                         required_fmts: Sequence[str] = (),
                         unsupported_imgopts: Sequence[str] = ()) -> bool:
    """
    Perform necessary setup for either script-style or unittest-style tests.

    :return: Bool; Whether or not debug mode has been requested via the CLI.
    """
    # Note: Python 3.6 and pylint do not like 'Collection' so use 'Sequence'.

    debug = '-d' in sys.argv
    if debug:
        sys.argv.remove('-d')
    logging.basicConfig(level=(logging.DEBUG if debug else logging.WARN))

    _verify_image_format(supported_fmts, unsupported_fmts)
    _verify_protocol(supported_protocols, unsupported_protocols)
    _verify_platform(supported=supported_platforms)
    _verify_cache_mode(supported_cache_modes)
    _verify_aio_mode(supported_aio_modes)
    _verify_formats(required_fmts)
    _verify_virtio_blk()
    _verify_imgopts(unsupported_imgopts)

    return debug

def execute_test(*args, test_function=None, **kwargs):
    """Run either unittest or script-style tests."""

    debug = execute_setup_common(*args, **kwargs)
    if not test_function:
        execute_unittest(sys.argv, debug)
    else:
        test_function()

def activate_logging():
    """Activate iotests.log() output to stdout for script-style tests."""
    handler = logging.StreamHandler(stream=sys.stdout)
    formatter = logging.Formatter('%(message)s')
    handler.setFormatter(formatter)
    test_logger.addHandler(handler)
    test_logger.setLevel(logging.INFO)
    test_logger.propagate = False

# This is called from script-style iotests without a single point of entry
def script_initialize(*args, **kwargs):
    """Initialize script-style tests without running any tests."""
    activate_logging()
    execute_setup_common(*args, **kwargs)

# This is called from script-style iotests with a single point of entry
def script_main(test_function, *args, **kwargs):
    """Run script-style tests outside of the unittest framework"""
    activate_logging()
    execute_test(*args, test_function=test_function, **kwargs)

# This is called from unittest style iotests
def main(*args, **kwargs):
    """Run tests using the unittest framework"""
    execute_test(*args, **kwargs)
