Skip to content

Commit

Permalink
tests/tcg: Factor out gdbstub test functions
Browse files Browse the repository at this point in the history
Both the report() function as well as the initial gdbstub test sequence
are copy-pasted into ~10 files with slight modifications. This
indicates that they are indeed generic, so factor them out. While
at it, add a few newlines to make the formatting closer to PEP-8.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Message-Id: <20240129093410.3151-3-iii@linux.ibm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
iii-i authored and rth7680 committed Jan 29, 2024
1 parent 87ab270 commit 4d48c1b
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 397 deletions.
7 changes: 6 additions & 1 deletion tests/guest-debug/run-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,12 @@ def log(output, msg):
sleep(1)
log(output, "GDB CMD: %s" % (gdb_cmd))

result = subprocess.call(gdb_cmd, shell=True, stdout=output, stderr=stderr)
gdb_env = dict(os.environ)
gdb_pythonpath = gdb_env.get("PYTHONPATH", "").split(os.pathsep)
gdb_pythonpath.append(os.path.dirname(os.path.realpath(__file__)))
gdb_env["PYTHONPATH"] = os.pathsep.join(gdb_pythonpath)
result = subprocess.call(gdb_cmd, shell=True, stdout=output, stderr=stderr,
env=gdb_env)

# A result of greater than 128 indicates a fatal signal (likely a
# crash due to gdb internal failure). That's a problem for GDB and
Expand Down
60 changes: 60 additions & 0 deletions tests/guest-debug/test_gdbstub.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""Helper functions for gdbstub testing
"""
from __future__ import print_function
import gdb
import os
import sys
import traceback

fail_count = 0


def report(cond, msg):
"""Report success/fail of a test"""
if cond:
print("PASS: {}".format(msg))
else:
print("FAIL: {}".format(msg))
global fail_count
fail_count += 1


def main(test, expected_arch=None):
"""Run a test function
This runs as the script it sourced (via -x, via run-test.py)."""
try:
inferior = gdb.selected_inferior()
arch = inferior.architecture()
print("ATTACHED: {}".format(arch.name()))
if expected_arch is not None:
report(arch.name() == expected_arch,
"connected to {}".format(expected_arch))
except (gdb.error, AttributeError):
print("SKIP: not connected")
exit(0)

if gdb.parse_and_eval("$pc") == 0:
print("SKIP: PC not set")
exit(0)

try:
test()
except:
print("GDB Exception:")
traceback.print_exc(file=sys.stdout)
global fail_count
fail_count += 1
if "QEMU_TEST_INTERACTIVE" in os.environ:
import code
code.InteractiveConsole(locals=globals()).interact()
raise

try:
gdb.execute("kill")
except gdb.error:
pass

print("All tests complete: {} failures".format(fail_count))
exit(fail_count)
34 changes: 2 additions & 32 deletions tests/tcg/aarch64/gdbstub/test-sve-ioctl.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,10 @@
#

import gdb
import sys
from test_gdbstub import main, report

initial_vlen = 0
failcount = 0

def report(cond, msg):
"Report success/fail of test"
if cond:
print ("PASS: %s" % (msg))
else:
print ("FAIL: %s" % (msg))
global failcount
failcount += 1

class TestBreakpoint(gdb.Breakpoint):
def __init__(self, sym_name="__sve_ld_done"):
Expand Down Expand Up @@ -64,26 +55,5 @@ def run_test():

gdb.execute("c")

#
# This runs as the script it sourced (via -x, via run-test.py)
#
try:
inferior = gdb.selected_inferior()
arch = inferior.architecture()
report(arch.name() == "aarch64", "connected to aarch64")
except (gdb.error, AttributeError):
print("SKIPPING (not connected)", file=sys.stderr)
exit(0)

try:
# Run the actual tests
run_test()
except:
print ("GDB Exception: %s" % (sys.exc_info()[0]))
failcount += 1
import code
code.InteractiveConsole(locals=globals()).interact()
raise

print("All tests complete: %d failures" % failcount)
exit(failcount)
main(run_test, expected_arch="aarch64")
33 changes: 2 additions & 31 deletions tests/tcg/aarch64/gdbstub/test-sve.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,10 @@
#

import gdb
import sys
from test_gdbstub import main, report

MAGIC = 0xDEADBEEF

failcount = 0

def report(cond, msg):
"Report success/fail of test"
if cond:
print ("PASS: %s" % (msg))
else:
print ("FAIL: %s" % (msg))
global failcount
failcount += 1

def run_test():
"Run through the tests one by one"
Expand Down Expand Up @@ -54,24 +44,5 @@ def run_test():
report(str(v.type) == "uint64_t", "size of %s" % (reg))
report(int(v) == MAGIC, "%s is 0x%x" % (reg, MAGIC))

#
# This runs as the script it sourced (via -x, via run-test.py)
#
try:
inferior = gdb.selected_inferior()
arch = inferior.architecture()
report(arch.name() == "aarch64", "connected to aarch64")
except (gdb.error, AttributeError):
print("SKIPPING (not connected)", file=sys.stderr)
exit(0)

try:
# Run the actual tests
run_test()
except:
print ("GDB Exception: %s" % (sys.exc_info()[0]))
failcount += 1

print("All tests complete: %d failures" % failcount)

exit(failcount)
main(run_test, expected_arch="aarch64")
47 changes: 5 additions & 42 deletions tests/tcg/multiarch/gdbstub/interrupt.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,7 @@
#

import gdb
import sys

failcount = 0


def report(cond, msg):
"Report success/fail of test"
if cond:
print("PASS: %s" % (msg))
else:
print("FAIL: %s" % (msg))
global failcount
failcount += 1
from test_gdbstub import main, report


def check_interrupt(thread):
Expand Down Expand Up @@ -59,39 +47,14 @@ def run_test():
Test if interrupting the code always lands us on the same thread when
running with scheduler-lock enabled.
"""
if len(gdb.selected_inferior().threads()) == 1:
print("SKIP: set to run on a single thread")
exit(0)

gdb.execute("set scheduler-locking on")
for thread in gdb.selected_inferior().threads():
report(check_interrupt(thread),
"thread %d resumes correctly on interrupt" % thread.num)


#
# This runs as the script it sourced (via -x, via run-test.py)
#
try:
inferior = gdb.selected_inferior()
arch = inferior.architecture()
print("ATTACHED: %s" % arch.name())
except (gdb.error, AttributeError):
print("SKIPPING (not connected)", file=sys.stderr)
exit(0)

if gdb.parse_and_eval('$pc') == 0:
print("SKIP: PC not set")
exit(0)
if len(gdb.selected_inferior().threads()) == 1:
print("SKIP: set to run on a single thread")
exit(0)

try:
# Run the actual tests
run_test()
except (gdb.error):
print("GDB Exception: %s" % (sys.exc_info()[0]))
failcount += 1
pass

# Finally kill the inferior and exit gdb with a count of failures
gdb.execute("kill")
exit(failcount)
main(run_test)
41 changes: 3 additions & 38 deletions tests/tcg/multiarch/gdbstub/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,7 @@

import gdb
import sys

failcount = 0


def report(cond, msg):
"Report success/fail of test"
if cond:
print("PASS: %s" % (msg))
else:
print("FAIL: %s" % (msg))
global failcount
failcount += 1
from test_gdbstub import main, report


def check_step():
Expand Down Expand Up @@ -99,29 +88,5 @@ def run_test():

report(cbp.hit_count == 0, "didn't reach backstop")

#
# This runs as the script it sourced (via -x, via run-test.py)
#
try:
inferior = gdb.selected_inferior()
arch = inferior.architecture()
print("ATTACHED: %s" % arch.name())
except (gdb.error, AttributeError):
print("SKIPPING (not connected)", file=sys.stderr)
exit(0)

if gdb.parse_and_eval('$pc') == 0:
print("SKIP: PC not set")
exit(0)

try:
# Run the actual tests
run_test()
except (gdb.error):
print("GDB Exception: %s" % (sys.exc_info()[0]))
failcount += 1
pass

# Finally kill the inferior and exit gdb with a count of failures
gdb.execute("kill")
exit(failcount)

main(run_test)
41 changes: 6 additions & 35 deletions tests/tcg/multiarch/gdbstub/registers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,11 @@
# SPDX-License-Identifier: GPL-2.0-or-later

import gdb
import sys
import xml.etree.ElementTree as ET
from test_gdbstub import main, report

initial_vlen = 0
failcount = 0

def report(cond, msg):
"Report success/fail of test."
if cond:
print("PASS: %s" % (msg))
else:
print("FAIL: %s" % (msg))
global failcount
failcount += 1
initial_vlen = 0


def fetch_xml_regmap():
Expand Down Expand Up @@ -75,6 +66,7 @@ def fetch_xml_regmap():

return reg_map


def get_register_by_regnum(reg_map, regnum):
"""
Helper to find a register from the map via its XML regnum
Expand All @@ -84,6 +76,7 @@ def get_register_by_regnum(reg_map, regnum):
return entry
return None


def crosscheck_remote_xml(reg_map):
"""
Cross-check the list of remote-registers with the XML info.
Expand Down Expand Up @@ -144,6 +137,7 @@ def crosscheck_remote_xml(reg_map):
elif "seen" not in x_reg:
print(f"{x_reg} wasn't seen in remote-registers")


def initial_register_read(reg_map):
"""
Do an initial read of all registers that we know gdb cares about
Expand Down Expand Up @@ -214,27 +208,4 @@ def run_test():
complete_and_diff(reg_map)


#
# This runs as the script it sourced (via -x, via run-test.py)
#
try:
inferior = gdb.selected_inferior()
arch = inferior.architecture()
print("ATTACHED: %s" % arch.name())
except (gdb.error, AttributeError):
print("SKIPPING (not connected)", file=sys.stderr)
exit(0)

if gdb.parse_and_eval('$pc') == 0:
print("SKIP: PC not set")
exit(0)

try:
run_test()
except (gdb.error):
print ("GDB Exception: %s" % (sys.exc_info()[0]))
failcount += 1
pass

print("All tests complete: %d failures" % failcount)
exit(failcount)
main(run_test)

0 comments on commit 4d48c1b

Please sign in to comment.