xref: /llvm-project/lldb/test/API/lang/cpp/exceptions/TestCPPExceptionBreakpoints.py (revision 80fcecb13c388ff087a27a4b0e7ca3dd8c98eaa4)
1"""
2Test lldb exception breakpoint command for CPP.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class CPPBreakpointTestCase(TestBase):
13    def setUp(self):
14        # Call super's setUp().
15        TestBase.setUp(self)
16        self.source = "exceptions.cpp"
17        self.catch_line = line_number(
18            self.source, "// This is the line you should stop at for catch"
19        )
20
21    @expectedFailureAll(
22        oslist=["windows"],
23        bugnumber="llvm.org/pr24538, clang-cl does not support throw or catch",
24    )
25    def test(self):
26        """Test lldb exception breakpoint command for CPP."""
27        self.build()
28        exe = self.getBuildArtifact("a.out")
29
30        # Create a target from the debugger.
31
32        target = self.dbg.CreateTarget(exe)
33        self.assertTrue(target, VALID_TARGET)
34
35        exception_bkpt = target.BreakpointCreateForException(
36            lldb.eLanguageTypeC_plus_plus, True, True
37        )
38        self.assertTrue(exception_bkpt, "Made an exception breakpoint")
39
40        # Now run, and make sure we hit our breakpoint:
41        process = target.LaunchSimple(None, None, self.get_process_working_directory())
42        self.assertTrue(process, "Got a valid process")
43
44        stopped_threads = []
45        stopped_threads = lldbutil.get_threads_stopped_at_breakpoint(
46            process, exception_bkpt
47        )
48        self.assertEqual(
49            len(stopped_threads), 1, "Stopped at our exception breakpoint."
50        )
51        thread = stopped_threads[0]
52        # Make sure our throw function is still above us on the stack:
53
54        frame_functions = lldbutil.get_function_names(thread)
55        self.assertEqual(
56            frame_functions.count("throws_exception_on_even(int)"),
57            1,
58            "Our throw function is still on the stack.",
59        )
60
61        # Okay we hit our exception throw breakpoint, now make sure we get our catch breakpoint.
62        # One potential complication is that we might hit a couple of the exception breakpoints in getting out of the throw.
63        # so loop till we don't see the throws function on the stack.  We should stop one more time for our exception breakpoint
64        # and that should be the catch...
65
66        while frame_functions.count("throws_exception_on_even(int)") == 1:
67            stopped_threads = lldbutil.continue_to_breakpoint(process, exception_bkpt)
68            self.assertEqual(len(stopped_threads), 1)
69
70            thread = stopped_threads[0]
71            frame_functions = lldbutil.get_function_names(thread)
72
73        self.assertEqual(
74            frame_functions.count("throws_exception_on_even(int)"),
75            0,
76            "At catch our throw function is off the stack",
77        )
78        self.assertEqual(
79            frame_functions.count("intervening_function(int)"),
80            0,
81            "At catch our intervening function is off the stack",
82        )
83        self.assertEqual(
84            frame_functions.count("catches_exception(int)"),
85            1,
86            "At catch our catch function is on the stack",
87        )
88