PageRenderTime 45ms CodeModel.GetById 35ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/test/test_jit_gdb.py

http://unladen-swallow.googlecode.com/
Python | 79 lines | 59 code | 9 blank | 11 comment | 1 complexity | 2c183d083ed6fc1600de4661c554cbc8 MD5 | raw file
 1# Test that gdb can debug JITted Python code.
 2
 3import os
 4import re
 5import subprocess
 6import sys
 7import unittest
 8
 9from test.test_support import run_unittest, TestSkipped
10
11try:
12    import _llvm
13except ImportError:
14    raise TestSkipped("Built without JIT support")
15
16try:
17    gdb_version, _ = subprocess.Popen(["gdb", "--version"],
18                                      stdout=subprocess.PIPE).communicate()
19except OSError:
20    # This is what "no gdb" looks like.  There may, however, be other
21    # errors that manifest this way too.
22    raise TestSkipped("Couldn't find gdb on the path")
23gdb_version_number = re.search(r"^GNU gdb [^\d]*(\d+)\.", gdb_version)
24if int(gdb_version_number.group(1)) < 7:
25    raise TestSkipped("gdb versions before 7.0 didn't support JIT debugging."
26                      " Saw:\n" + gdb_version)
27
28
29class DebuggerTests(unittest.TestCase):
30
31    """Test that the debugger can debug Python."""
32
33    def run_gdb(self, *args):
34        """Runs gdb with the command line given by *args. Returns its stdout.
35
36        Forwards stderr to the current process's stderr.
37        """
38        # err winds up empty.
39        out, err = subprocess.Popen(
40            args, stdout=subprocess.PIPE,
41            stderr=None,  # Forward stderr to the current process's stderr.
42            env=dict(PYTHONLLVMFLAGS="-jit-emit-debug", **os.environ)
43            ).communicate()
44        return out
45
46    def test_gets_stack_trace(self):
47        gdb_output = self.run_gdb("gdb", "--batch",
48                                  # Use 'start' to load any shared libraries.
49                                  "--eval-command=start",
50                                  "--eval-command=break PyObject_Print",
51                                  "--eval-command=run",
52                                  "--eval-command=backtrace",
53                                  "--eval-command=continue",
54                                  "--args",
55                                  sys.executable, "-S", "-c", """
56def foo(): bar()
57def bar(): baz()
58def baz(): print 'Hello, World!'
59for function in (foo, bar, baz):
60    function.__code__.co_use_jit = True
61foo()""")
62        # Get the indices of each function in the stack trace.
63        foo, bar, baz, output = map(
64            gdb_output.find, ("_23_foo", "_23_bar",
65                              "_23_baz", "Hello, World!"))
66        # str.find returns -1 on failure, so this makes sure each
67        # string is in the output.
68        self.assertTrue(-1 not in (foo, bar, baz, output), msg=gdb_output)
69        # And now we make sure they're in the right order in the backtrace.
70        self.assertTrue(baz < bar < foo < output, msg=gdb_output)
71
72
73
74def test_main():
75    run_unittest(DebuggerTests)
76
77
78if __name__ == "__main__":
79    test_main()