forked from OSchip/llvm-project
116 lines
4.0 KiB
Python
116 lines
4.0 KiB
Python
#===----------------------------------------------------------------------===##
|
|
#
|
|
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
# See https://llvm.org/LICENSE.txt for license information.
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
#
|
|
#===----------------------------------------------------------------------===##
|
|
"""Commands used to automate testing gdb pretty printers.
|
|
|
|
This script is part of a larger framework to test gdb pretty printers. It
|
|
runs the program, detects test cases, checks them, and prints results.
|
|
|
|
See gdb_pretty_printer_test.sh.cpp on how to write a test case.
|
|
|
|
"""
|
|
|
|
from __future__ import print_function
|
|
import re
|
|
import gdb
|
|
import sys
|
|
|
|
test_failures = 0
|
|
|
|
|
|
class CheckResult(gdb.Command):
|
|
|
|
def __init__(self):
|
|
super(CheckResult, self).__init__(
|
|
"print_and_compare", gdb.COMMAND_DATA)
|
|
|
|
def invoke(self, arg, from_tty):
|
|
try:
|
|
# Stack frame is:
|
|
# 0. StopForDebugger
|
|
# 1. ComparePrettyPrintToChars or ComparePrettyPrintToRegex
|
|
# 2. TestCase
|
|
compare_frame = gdb.newest_frame().older()
|
|
testcase_frame = compare_frame.older()
|
|
test_loc = testcase_frame.find_sal()
|
|
# Use interactive commands in the correct context to get the pretty
|
|
# printed version
|
|
|
|
value_str = self._get_value_string(compare_frame, testcase_frame)
|
|
|
|
# Ignore the convenience variable name and newline
|
|
value = value_str[value_str.find("= ") + 2:-1]
|
|
gdb.newest_frame().select()
|
|
|
|
expectation_val = compare_frame.read_var("expectation")
|
|
check_literal = expectation_val.string(encoding="utf-8")
|
|
if "PrettyPrintToRegex" in compare_frame.name():
|
|
test_fails = not re.match(check_literal, value)
|
|
else:
|
|
test_fails = value != check_literal
|
|
|
|
if test_fails:
|
|
global test_failures
|
|
print("FAIL: " + test_loc.symtab.filename +
|
|
":" + str(test_loc.line))
|
|
print("GDB printed:")
|
|
print(" " + repr(value))
|
|
print("Value should match:")
|
|
print(" " + repr(check_literal))
|
|
test_failures += 1
|
|
else:
|
|
print("PASS: " + test_loc.symtab.filename +
|
|
":" + str(test_loc.line))
|
|
|
|
except RuntimeError as e:
|
|
# At this point, lots of different things could be wrong, so don't try to
|
|
# recover or figure it out. Don't exit either, because then it's
|
|
# impossible debug the framework itself.
|
|
print("FAIL: Something is wrong in the test framework.")
|
|
print(str(e))
|
|
test_failures += 1
|
|
|
|
def _get_value_string(self, compare_frame, testcase_frame):
|
|
compare_frame.select()
|
|
if "ComparePrettyPrint" in compare_frame.name():
|
|
s = gdb.execute("p value", to_string=True)
|
|
else:
|
|
value_str = str(compare_frame.read_var("value"))
|
|
clean_expression_str = value_str.strip("'\"")
|
|
testcase_frame.select()
|
|
s = gdb.execute("p " + clean_expression_str, to_string=True)
|
|
if sys.version_info.major == 2:
|
|
return s.decode("utf-8")
|
|
return s
|
|
|
|
|
|
def exit_handler(event=None):
|
|
global test_failures
|
|
if test_failures:
|
|
print("FAILED %d cases" % test_failures)
|
|
exit(test_failures)
|
|
|
|
|
|
# Start code executed at load time
|
|
|
|
# Disable terminal paging
|
|
gdb.execute("set height 0")
|
|
gdb.execute("set python print-stack full")
|
|
test_failures = 0
|
|
CheckResult()
|
|
test_bp = gdb.Breakpoint("StopForDebugger")
|
|
test_bp.enabled = True
|
|
test_bp.silent = True
|
|
test_bp.commands = "print_and_compare\ncontinue"
|
|
# "run" won't return if the program exits; ensure the script regains control.
|
|
gdb.events.exited.connect(exit_handler)
|
|
gdb.execute("run")
|
|
# If the program didn't exit, something went wrong, but we don't
|
|
# know what. Fail on exit.
|
|
test_failures += 1
|
|
exit_handler(None)
|