diff options
Diffstat (limited to 'js/src/gdb/lib-for-tests')
-rw-r--r-- | js/src/gdb/lib-for-tests/catcher.py | 35 | ||||
-rw-r--r-- | js/src/gdb/lib-for-tests/prologue.py | 128 |
2 files changed, 163 insertions, 0 deletions
diff --git a/js/src/gdb/lib-for-tests/catcher.py b/js/src/gdb/lib-for-tests/catcher.py new file mode 100644 index 0000000000..8ef3529255 --- /dev/null +++ b/js/src/gdb/lib-for-tests/catcher.py @@ -0,0 +1,35 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +# Apparently, there's simply no way to ask GDB to exit with a non-zero +# status when the script run with the --eval-command option fails. Thus, if +# we have --eval-command run prologue.py directly, syntax errors there will +# lead GDB to exit with no indication anything went wrong. +# +# To avert that, we use this very small launcher script to run prologue.py +# and catch errors. +# +# Remember, errors in this file will cause spurious passes, so keep this as +# simple as possible! +# flake8: noqa: F821 + +import os +import sys +import traceback + + +def execfile(filename, globs, locs): + with open(filename) as f: + code = compile(f.read(), filename, "exec") + exec(code, globs, locs) + + +try: + # testlibdir is set on the GDB command line, via: + # --eval-command python testlibdir=... + execfile(os.path.join(testlibdir, "prologue.py"), globals(), locals()) +except Exception as err: + sys.stderr.write("Error running GDB prologue:\n") + traceback.print_exc() + sys.exit(1) diff --git a/js/src/gdb/lib-for-tests/prologue.py b/js/src/gdb/lib-for-tests/prologue.py new file mode 100644 index 0000000000..64f2994abe --- /dev/null +++ b/js/src/gdb/lib-for-tests/prologue.py @@ -0,0 +1,128 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. + +# flake8: noqa: F821 + +import gdb +import re +import sys +import traceback + +# testlibdir is set on the GDB command line, via --eval-command python testlibdir=... +sys.path[0:0] = [testlibdir] + +active_fragment = None + +# Run the C++ fragment named |fragment|, stopping on entry to |function| +# ('breakpoint', by default) and then select the calling frame. + + +def run_fragment(fragment, function="gdb-tests.cpp:breakpoint"): + # Arrange to stop at a reasonable place in the test program. + bp = gdb.Breakpoint(function) + try: + gdb.execute("run %s" % (fragment,)) + # Check that we did indeed stop by hitting the breakpoint we set. + assert bp.hit_count == 1 + finally: + bp.delete() + gdb.execute("frame 1") + + global active_fragment + active_fragment = fragment + + +# Assert that |actual| is equal to |expected|; if not, complain in a helpful way. + + +def assert_eq(actual, expected): + if actual != expected: + raise AssertionError( + """Unexpected result: +expected: %r +actual: %r""" + % (expected, actual) + ) + + +# Assert that |expected| regex matches |actual| result; if not, complain in a helpful way. + + +def assert_match(actual, expected): + if re.match(expected, actual, re.MULTILINE) is None: + raise AssertionError( + """Unexpected result: +expected pattern: %r +actual: %r""" + % (expected, actual) + ) + + +# Assert that |value|'s pretty-printed form is |form|. If |value| is a +# string, then evaluate it with gdb.parse_and_eval to produce a value. + + +def assert_pretty(value, form): + if isinstance(value, str): + value = gdb.parse_and_eval(value) + assert_eq(str(value), form) + + +# Assert that |value|'s pretty-printed form match the pattern |pattern|. If +# |value| is a string, then evaluate it with gdb.parse_and_eval to produce a +# value. + + +def assert_regexp_pretty(value, form): + if isinstance(value, str): + value = gdb.parse_and_eval(value) + assert_match(str(value), form) + + +# Check that the list of registered pretty-printers includes one named +# |printer|, with a subprinter named |subprinter|. + + +def assert_subprinter_registered(printer, subprinter): + # Match a line containing |printer| followed by a colon, and then a + # series of more-indented lines containing |subprinter|. + + names = {"printer": re.escape(printer), "subprinter": re.escape(subprinter)} + pat = r"^( +)%(printer)s *\n(\1 +.*\n)*\1 +%(subprinter)s *\n" % names + output = gdb.execute("info pretty-printer", to_string=True) + if not re.search(pat, output, re.MULTILINE): + raise AssertionError( + "assert_subprinter_registered failed to find pretty-printer:\n" + " %s:%s\n" + "'info pretty-printer' says:\n" + "%s" % (printer, subprinter, output) + ) + + +# Request full stack traces for Python errors. +gdb.execute("set python print-stack full") + +# Tell GDB not to ask the user about the things we tell it to do. +gdb.execute("set confirm off", False) + +# Some print settings that make testing easier. +gdb.execute("set print static-members off") +gdb.execute("set print address off") +gdb.execute("set print pretty off") +gdb.execute("set width 0") + +try: + # testscript is set on the GDB command line, via: + # --eval-command python testscript=... + execfile(testscript, globals(), locals()) +except AssertionError as err: + header = "\nAssertion traceback" + if active_fragment: + header += " for " + active_fragment + sys.stderr.write(header + ":\n") + (t, v, tb) = sys.exc_info() + traceback.print_tb(tb) + sys.stderr.write("\nTest assertion failed:\n") + sys.stderr.write(str(err)) + sys.exit(1) |