diff options
Diffstat (limited to 'tests/functional/qemu_test')
-rw-r--r-- | tests/functional/qemu_test/__init__.py | 4 | ||||
-rw-r--r-- | tests/functional/qemu_test/asset.py | 1 | ||||
-rw-r--r-- | tests/functional/qemu_test/decorators.py | 18 | ||||
-rw-r--r-- | tests/functional/qemu_test/gdb.py | 86 |
4 files changed, 107 insertions, 2 deletions
diff --git a/tests/functional/qemu_test/__init__.py b/tests/functional/qemu_test/__init__.py index 6e666a0..3201935 100644 --- a/tests/functional/qemu_test/__init__.py +++ b/tests/functional/qemu_test/__init__.py @@ -15,6 +15,8 @@ from .testcase import QemuBaseTest, QemuUserTest, QemuSystemTest from .linuxkernel import LinuxKernelTest from .decorators import skipIfMissingCommands, skipIfNotMachine, \ skipFlakyTest, skipUntrustedTest, skipBigDataTest, skipSlowTest, \ - skipIfMissingImports, skipIfOperatingSystem, skipLockedMemoryTest + skipIfMissingImports, skipIfOperatingSystem, skipLockedMemoryTest, \ + skipIfMissingEnv from .archive import archive_extract from .uncompress import uncompress +from .gdb import GDB diff --git a/tests/functional/qemu_test/asset.py b/tests/functional/qemu_test/asset.py index 2971a98..f666125 100644 --- a/tests/functional/qemu_test/asset.py +++ b/tests/functional/qemu_test/asset.py @@ -225,7 +225,6 @@ class Asset: log.addHandler(handler) for name, asset in vars(test.__class__).items(): if name.startswith("ASSET_") and type(asset) == Asset: - log.info("Attempting to cache '%s'" % asset) try: asset.fetch() except AssetError as e: diff --git a/tests/functional/qemu_test/decorators.py b/tests/functional/qemu_test/decorators.py index c0d1567..b239295 100644 --- a/tests/functional/qemu_test/decorators.py +++ b/tests/functional/qemu_test/decorators.py @@ -11,6 +11,24 @@ from unittest import skipIf, skipUnless from .cmd import which ''' +Decorator to skip execution of a test if the provided +environment variables are not set. +Example: + + @skipIfMissingEnv("QEMU_ENV_VAR0", "QEMU_ENV_VAR1") +''' +def skipIfMissingEnv(*vars_): + missing_vars = [] + for var in vars_: + if os.getenv(var) == None: + missing_vars.append(var) + + has_vars = True if len(missing_vars) == 0 else False + + return skipUnless(has_vars, f"Missing env var(s): {', '.join(missing_vars)}") + +''' + Decorator to skip execution of a test if the list of command binaries is not available in $PATH. Example: diff --git a/tests/functional/qemu_test/gdb.py b/tests/functional/qemu_test/gdb.py new file mode 100644 index 0000000..558d476 --- /dev/null +++ b/tests/functional/qemu_test/gdb.py @@ -0,0 +1,86 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# A simple interface module built around pygdbmi for handling GDB commands. +# +# Copyright (c) 2025 Linaro Limited +# +# Author: +# Gustavo Romero <gustavo.romero@linaro.org> +# + +import re + + +class GDB: + """Provides methods to run and capture GDB command output.""" + + + def __init__(self, gdb_path, echo=True, suffix='# ', prompt="$ "): + from pygdbmi.gdbcontroller import GdbController + from pygdbmi.constants import GdbTimeoutError + type(self).TimeoutError = GdbTimeoutError + + gdb_cmd = [gdb_path, "-q", "--interpreter=mi2"] + self.gdbmi = GdbController(gdb_cmd) + self.echo = echo + self.suffix = suffix + self.prompt = prompt + self.response = None + self.cmd_output = None + + + def get_payload(self, response, kind): + output = [] + for o in response: + # Unpack payloads of the same type. + _type, _, payload, *_ = o.values() + if _type == kind: + output += [payload] + + # Some output lines do not end with \n but begin with it, + # so remove the leading \n and merge them with the next line + # that ends with \n. + lines = [line.lstrip('\n') for line in output] + lines = "".join(lines) + lines = lines.splitlines(keepends=True) + + return lines + + + def cli(self, cmd, timeout=32.0): + self.response = self.gdbmi.write(cmd, timeout_sec=timeout) + self.cmd_output = self.get_payload(self.response, kind="console") + if self.echo: + print(self.suffix + self.prompt + cmd) + + if len(self.cmd_output) > 0: + cmd_output = self.suffix.join(self.cmd_output) + print(self.suffix + cmd_output, end="") + + return self + + + def get_addr(self): + address_pattern = r"0x[0-9A-Fa-f]+" + cmd_output = "".join(self.cmd_output) # Concat output lines. + + match = re.search(address_pattern, cmd_output) + + return int(match[0], 16) if match else None + + + def get_log(self): + r = self.get_payload(self.response, kind="log") + r = "".join(r) + + return r + + + def get_console(self): + r = "".join(self.cmd_output) + + return r + + + def exit(self): + self.gdbmi.exit() |