1"""
2Test lldb exception breakpoint command for CPP.
3"""
4
5import os, time
6import unittest2
7import lldb
8import lldbutil
9from lldbtest import *
10
11class CPPBreakpointTestCase(TestBase):
12
13    mydir = os.path.join("lang", "cpp", "exceptions")
14
15    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
16    @dsym_test
17    def test_with_dsym(self):
18        """Test lldb exception breakpoint command for CPP."""
19        self.buildDsym()
20        self.cpp_exceptions()
21
22    @dwarf_test
23    def test_with_dwarf(self):
24        """Test lldb exception breakpoint command for CPP."""
25        self.buildDwarf()
26        self.cpp_exceptions()
27
28    def setUp(self):
29        # Call super's setUp().
30        TestBase.setUp(self)
31        self.source = 'exceptions.cpp'
32        self.catch_line = line_number(self.source, '// This is the line you should stop at for catch')
33
34    def cpp_exceptions (self):
35        """Test lldb exception breakpoint command for CPP."""
36        exe = os.path.join(os.getcwd(), "a.out")
37
38        # Create a target from the debugger.
39
40        target = self.dbg.CreateTarget (exe)
41        self.assertTrue(target, VALID_TARGET)
42
43        exception_bkpt = target.BreakpointCreateForException (lldb.eLanguageTypeC_plus_plus, True, True)
44        self.assertTrue (exception_bkpt, "Made an exception breakpoint")
45
46        # Now run, and make sure we hit our breakpoint:
47        process = target.LaunchSimple (None, None, os.getcwd())
48        self.assertTrue (process, "Got a valid process")
49
50        stopped_threads = []
51        stopped_threads = lldbutil.get_threads_stopped_at_breakpoint (process, exception_bkpt)
52        self.assertTrue (len(stopped_threads) == 1, "Stopped at our exception breakpoint.")
53        thread = stopped_threads[0]
54        # Make sure our throw function is still above us on the stack:
55
56        frame_functions = lldbutil.get_function_names(thread)
57        self.assertTrue (frame_functions.count ("throws_exception_on_even(int)") == 1, "Our throw function is still on the stack.")
58
59        # Okay we hit our exception throw breakpoint, now make sure we get our catch breakpoint.
60        # One potential complication is that we might hit a couple of the exception breakpoints in getting out of the throw.
61        # so loop till we don't see the throws function on the stack.  We should stop one more time for our exception breakpoint
62        # and that should be the catch...
63
64        while frame_functions.count ("throws_exception_on_even(int)") == 1:
65            stopped_threads = lldbutil.continue_to_breakpoint (process, exception_bkpt)
66            self.assertTrue (len(stopped_threads) == 1)
67
68            thread = stopped_threads[0]
69            frame_functions = lldbutil.get_function_names(thread)
70
71        self.assertTrue (frame_functions.count ("throws_exception_on_even(int)") == 0, "At catch our throw function is off the stack")
72        self.assertTrue (frame_functions.count ("intervening_function(int)") == 0,     "At catch our intervening function is off the stack")
73        self.assertTrue (frame_functions.count ("catches_exception(int)") == 1, "At catch our catch function is on the stack")
74
75
76
77if __name__ == '__main__':
78    import atexit
79    lldb.SBDebugger.Initialize()
80    atexit.register(lambda: lldb.SBDebugger.Terminate())
81    unittest2.main()
82