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