1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this file,
3# You can obtain one at http://mozilla.org/MPL/2.0/.
4
5# flake8: noqa: F821
6
7import gdb
8import re
9import sys
10import traceback
11
12# testlibdir is set on the GDB command line, via --eval-command python testlibdir=...
13sys.path[0:0] = [testlibdir]
14
15active_fragment = None
16
17# Run the C++ fragment named |fragment|, stopping on entry to |function|
18# ('breakpoint', by default) and then select the calling frame.
19
20
21def run_fragment(fragment, function="gdb-tests.cpp:breakpoint"):
22    # Arrange to stop at a reasonable place in the test program.
23    bp = gdb.Breakpoint(function)
24    try:
25        gdb.execute("run %s" % (fragment,))
26        # Check that we did indeed stop by hitting the breakpoint we set.
27        assert bp.hit_count == 1
28    finally:
29        bp.delete()
30    gdb.execute("frame 1")
31
32    global active_fragment
33    active_fragment = fragment
34
35
36# Assert that |actual| is equal to |expected|; if not, complain in a helpful way.
37
38
39def assert_eq(actual, expected):
40    if actual != expected:
41        raise AssertionError(
42            """Unexpected result:
43expected: %r
44actual:   %r"""
45            % (expected, actual)
46        )
47
48
49# Assert that |expected| regex matches |actual| result; if not, complain in a helpful way.
50
51
52def assert_match(actual, expected):
53    if re.match(expected, actual, re.MULTILINE) is None:
54        raise AssertionError(
55            """Unexpected result:
56expected pattern: %r
57actual:           %r"""
58            % (expected, actual)
59        )
60
61
62# Assert that |value|'s pretty-printed form is |form|. If |value| is a
63# string, then evaluate it with gdb.parse_and_eval to produce a value.
64
65
66def assert_pretty(value, form):
67    if isinstance(value, str):
68        value = gdb.parse_and_eval(value)
69    assert_eq(str(value), form)
70
71
72# Assert that |value|'s pretty-printed form match the pattern |pattern|. If
73# |value| is a string, then evaluate it with gdb.parse_and_eval to produce a
74# value.
75
76
77def assert_regexp_pretty(value, form):
78    if isinstance(value, str):
79        value = gdb.parse_and_eval(value)
80    assert_match(str(value), form)
81
82
83# Check that the list of registered pretty-printers includes one named
84# |printer|, with a subprinter named |subprinter|.
85
86
87def assert_subprinter_registered(printer, subprinter):
88    # Match a line containing |printer| followed by a colon, and then a
89    # series of more-indented lines containing |subprinter|.
90
91    names = {"printer": re.escape(printer), "subprinter": re.escape(subprinter)}
92    pat = r"^( +)%(printer)s *\n(\1 +.*\n)*\1 +%(subprinter)s *\n" % names
93    output = gdb.execute("info pretty-printer", to_string=True)
94    if not re.search(pat, output, re.MULTILINE):
95        raise AssertionError(
96            "assert_subprinter_registered failed to find pretty-printer:\n"
97            "  %s:%s\n"
98            "'info pretty-printer' says:\n"
99            "%s" % (printer, subprinter, output)
100        )
101
102
103# Request full stack traces for Python errors.
104gdb.execute("set python print-stack full")
105
106# Tell GDB not to ask the user about the things we tell it to do.
107gdb.execute("set confirm off", False)
108
109# Some print settings that make testing easier.
110gdb.execute("set print static-members off")
111gdb.execute("set print address off")
112gdb.execute("set print pretty off")
113gdb.execute("set width 0")
114
115try:
116    # testscript is set on the GDB command line, via:
117    # --eval-command python testscript=...
118    execfile(testscript, globals(), locals())
119except AssertionError as err:
120    header = "\nAssertion traceback"
121    if active_fragment:
122        header += " for " + active_fragment
123    sys.stderr.write(header + ":\n")
124    (t, v, tb) = sys.exc_info()
125    traceback.print_tb(tb)
126    sys.stderr.write("\nTest assertion failed:\n")
127    sys.stderr.write(str(err))
128    sys.exit(1)
129