tests/functional: Convert reverse_debugging tests to the functional framework

These tests are using the gdb-related library functions from the
Avocado framework which we don't have in the functional framework
yet. So for the time being, keep those imports and skip the test
if the Avocado framework is not installed on the host.

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20250414113031.151105-4-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Thomas Huth 2025-04-14 13:30:17 +02:00
parent bc65ae6961
commit 951ededf12
6 changed files with 139 additions and 96 deletions

View file

@ -3671,7 +3671,7 @@ F: docs/system/replay.rst
F: stubs/replay.c F: stubs/replay.c
F: tests/avocado/replay_kernel.py F: tests/avocado/replay_kernel.py
F: tests/avocado/replay_linux.py F: tests/avocado/replay_linux.py
F: tests/avocado/reverse_debugging.py F: tests/functional/*reverse_debug*.py
F: tests/functional/*replay*.py F: tests/functional/*replay*.py
F: qapi/replay.json F: qapi/replay.json

View file

@ -13,6 +13,7 @@ endif
test_timeouts = { test_timeouts = {
'aarch64_aspeed' : 600, 'aarch64_aspeed' : 600,
'aarch64_raspi4' : 480, 'aarch64_raspi4' : 480,
'aarch64_reverse_debug' : 180,
'aarch64_rme_virt' : 1200, 'aarch64_rme_virt' : 1200,
'aarch64_rme_sbsaref' : 1200, 'aarch64_rme_sbsaref' : 1200,
'aarch64_sbsaref_alpine' : 1200, 'aarch64_sbsaref_alpine' : 1200,
@ -78,6 +79,7 @@ tests_aarch64_system_thorough = [
'aarch64_raspi3', 'aarch64_raspi3',
'aarch64_raspi4', 'aarch64_raspi4',
'aarch64_replay', 'aarch64_replay',
'aarch64_reverse_debug',
'aarch64_rme_virt', 'aarch64_rme_virt',
'aarch64_rme_sbsaref', 'aarch64_rme_sbsaref',
'aarch64_sbsaref', 'aarch64_sbsaref',
@ -229,6 +231,7 @@ tests_ppc64_system_thorough = [
'ppc64_powernv', 'ppc64_powernv',
'ppc64_pseries', 'ppc64_pseries',
'ppc64_replay', 'ppc64_replay',
'ppc64_reverse_debug',
'ppc64_tuxrun', 'ppc64_tuxrun',
'ppc64_mac99', 'ppc64_mac99',
] ]
@ -311,6 +314,7 @@ tests_x86_64_system_thorough = [
'x86_64_hotplug_cpu', 'x86_64_hotplug_cpu',
'x86_64_kvm_xen', 'x86_64_kvm_xen',
'x86_64_replay', 'x86_64_replay',
'x86_64_reverse_debug',
'x86_64_tuxrun', 'x86_64_tuxrun',
] ]

View file

@ -1,5 +1,7 @@
# Reverse debugging test # Reverse debugging test
# #
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Copyright (c) 2020 ISP RAS # Copyright (c) 2020 ISP RAS
# #
# Author: # Author:
@ -10,14 +12,9 @@
import os import os
import logging import logging
from avocado import skipUnless from qemu_test import LinuxKernelTest, get_qemu_img
from avocado_qemu import BUILD_DIR from qemu_test.ports import Ports
from avocado.utils import datadrainer
from avocado.utils import gdb
from avocado.utils import process
from avocado.utils.network.ports import find_free_port
from avocado.utils.path import find_command
from boot_linux_console import LinuxKernelTest
class ReverseDebugging(LinuxKernelTest): class ReverseDebugging(LinuxKernelTest):
""" """
@ -36,8 +33,10 @@ class ReverseDebugging(LinuxKernelTest):
endian_is_le = True endian_is_le = True
def run_vm(self, record, shift, args, replay_path, image_path, port): def run_vm(self, record, shift, args, replay_path, image_path, port):
from avocado.utils import datadrainer
logger = logging.getLogger('replay') logger = logging.getLogger('replay')
vm = self.get_vm() vm = self.get_vm(name='record' if record else 'replay')
vm.set_console() vm.set_console()
if record: if record:
logger.info('recording the execution...') logger.info('recording the execution...')
@ -100,25 +99,25 @@ class ReverseDebugging(LinuxKernelTest):
return vm.qmp('query-replay')['return']['icount'] return vm.qmp('query-replay')['return']['icount']
def reverse_debugging(self, shift=7, args=None): def reverse_debugging(self, shift=7, args=None):
from avocado.utils import gdb
from avocado.utils import process
logger = logging.getLogger('replay') logger = logging.getLogger('replay')
# create qcow2 for snapshots # create qcow2 for snapshots
logger.info('creating qcow2 image for VM snapshots') logger.info('creating qcow2 image for VM snapshots')
image_path = os.path.join(self.workdir, 'disk.qcow2') image_path = os.path.join(self.workdir, 'disk.qcow2')
qemu_img = os.path.join(BUILD_DIR, 'qemu-img') qemu_img = get_qemu_img(self)
if not os.path.exists(qemu_img): if qemu_img is None:
qemu_img = find_command('qemu-img', False) self.skipTest('Could not find "qemu-img", which is required to '
if qemu_img is False: 'create the temporary qcow2 image')
self.cancel('Could not find "qemu-img", which is required to '
'create the temporary qcow2 image')
cmd = '%s create -f qcow2 %s 128M' % (qemu_img, image_path) cmd = '%s create -f qcow2 %s 128M' % (qemu_img, image_path)
process.run(cmd) process.run(cmd)
replay_path = os.path.join(self.workdir, 'replay.bin') replay_path = os.path.join(self.workdir, 'replay.bin')
port = find_free_port()
# record the log # record the log
vm = self.run_vm(True, shift, args, replay_path, image_path, port) vm = self.run_vm(True, shift, args, replay_path, image_path, -1)
while self.vm_get_icount(vm) <= self.STEPS: while self.vm_get_icount(vm) <= self.STEPS:
pass pass
last_icount = self.vm_get_icount(vm) last_icount = self.vm_get_icount(vm)
@ -127,7 +126,9 @@ class ReverseDebugging(LinuxKernelTest):
logger.info("recorded log with %s+ steps" % last_icount) logger.info("recorded log with %s+ steps" % last_icount)
# replay and run debug commands # replay and run debug commands
vm = self.run_vm(False, shift, args, replay_path, image_path, port) with Ports() as ports:
port = ports.find_free_port()
vm = self.run_vm(False, shift, args, replay_path, image_path, port)
logger.info('connecting to gdbstub') logger.info('connecting to gdbstub')
g = gdb.GDBRemote('127.0.0.1', port, False, False) g = gdb.GDBRemote('127.0.0.1', port, False, False)
g.connect() g.connect()
@ -193,80 +194,3 @@ class ReverseDebugging(LinuxKernelTest):
logger.info('exiting gdb and qemu') logger.info('exiting gdb and qemu')
vm.shutdown() vm.shutdown()
class ReverseDebugging_X86_64(ReverseDebugging):
"""
:avocado: tags=accel:tcg
"""
REG_PC = 0x10
REG_CS = 0x12
def get_pc(self, g):
return self.get_reg_le(g, self.REG_PC) \
+ self.get_reg_le(g, self.REG_CS) * 0x10
# unidentified gitlab timeout problem
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
def test_x86_64_pc(self):
"""
:avocado: tags=arch:x86_64
:avocado: tags=machine:pc
"""
# start with BIOS only
self.reverse_debugging()
class ReverseDebugging_AArch64(ReverseDebugging):
"""
:avocado: tags=accel:tcg
"""
REG_PC = 32
# unidentified gitlab timeout problem
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
def test_aarch64_virt(self):
"""
:avocado: tags=arch:aarch64
:avocado: tags=machine:virt
:avocado: tags=cpu:cortex-a53
"""
kernel_url = ('https://archives.fedoraproject.org/pub/archive/fedora'
'/linux/releases/29/Everything/aarch64/os/images/pxeboot'
'/vmlinuz')
kernel_hash = '8c73e469fc6ea06a58dc83a628fc695b693b8493'
kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
self.reverse_debugging(
args=('-kernel', kernel_path))
class ReverseDebugging_ppc64(ReverseDebugging):
"""
:avocado: tags=accel:tcg
"""
REG_PC = 0x40
# unidentified gitlab timeout problem
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
def test_ppc64_pseries(self):
"""
:avocado: tags=arch:ppc64
:avocado: tags=machine:pseries
:avocado: tags=flaky
"""
# SLOF branches back to its entry point, which causes this test
# to take the 'hit a breakpoint again' path. That's not a problem,
# just slightly different than the other machines.
self.endian_is_le = False
self.reverse_debugging()
# See https://gitlab.com/qemu-project/qemu/-/issues/1992
@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab')
def test_ppc64_powernv(self):
"""
:avocado: tags=arch:ppc64
:avocado: tags=machine:powernv
:avocado: tags=flaky
"""
self.endian_is_le = False
self.reverse_debugging()

View file

@ -0,0 +1,38 @@
#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Reverse debugging test
#
# Copyright (c) 2020 ISP RAS
#
# Author:
# Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
#
# This work is licensed under the terms of the GNU GPL, version 2 or
# later. See the COPYING file in the top-level directory.
from qemu_test import Asset, skipIfMissingImports, skipFlakyTest
from reverse_debugging import ReverseDebugging
@skipIfMissingImports('avocado.utils')
class ReverseDebugging_AArch64(ReverseDebugging):
REG_PC = 32
KERNEL_ASSET = Asset(
('https://archives.fedoraproject.org/pub/archive/fedora/linux/'
'releases/29/Everything/aarch64/os/images/pxeboot/vmlinuz'),
'7e1430b81c26bdd0da025eeb8fbd77b5dc961da4364af26e771bd39f379cbbf7')
@skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/2921")
def test_aarch64_virt(self):
self.set_machine('virt')
self.cpu = 'cortex-a53'
kernel_path = self.KERNEL_ASSET.fetch()
self.reverse_debugging(args=('-kernel', kernel_path))
if __name__ == '__main__':
ReverseDebugging.main()

View file

@ -0,0 +1,41 @@
#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Reverse debugging test
#
# Copyright (c) 2020 ISP RAS
#
# Author:
# Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
#
# This work is licensed under the terms of the GNU GPL, version 2 or
# later. See the COPYING file in the top-level directory.
from qemu_test import skipIfMissingImports, skipFlakyTest
from reverse_debugging import ReverseDebugging
@skipIfMissingImports('avocado.utils')
class ReverseDebugging_ppc64(ReverseDebugging):
REG_PC = 0x40
@skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/1992")
def test_ppc64_pseries(self):
self.set_machine('pseries')
# SLOF branches back to its entry point, which causes this test
# to take the 'hit a breakpoint again' path. That's not a problem,
# just slightly different than the other machines.
self.endian_is_le = False
self.reverse_debugging()
@skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/1992")
def test_ppc64_powernv(self):
self.set_machine('powernv')
self.endian_is_le = False
self.reverse_debugging()
if __name__ == '__main__':
ReverseDebugging.main()

View file

@ -0,0 +1,36 @@
#!/usr/bin/env python3
#
# SPDX-License-Identifier: GPL-2.0-or-later
#
# Reverse debugging test
#
# Copyright (c) 2020 ISP RAS
#
# Author:
# Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
#
# This work is licensed under the terms of the GNU GPL, version 2 or
# later. See the COPYING file in the top-level directory.
from qemu_test import skipIfMissingImports, skipFlakyTest
from reverse_debugging import ReverseDebugging
@skipIfMissingImports('avocado.utils')
class ReverseDebugging_X86_64(ReverseDebugging):
REG_PC = 0x10
REG_CS = 0x12
def get_pc(self, g):
return self.get_reg_le(g, self.REG_PC) \
+ self.get_reg_le(g, self.REG_CS) * 0x10
@skipFlakyTest("https://gitlab.com/qemu-project/qemu/-/issues/2922")
def test_x86_64_pc(self):
self.set_machine('pc')
# start with BIOS only
self.reverse_debugging()
if __name__ == '__main__':
ReverseDebugging.main()