1""" Test that stop-on-sharedlibrary-events works and cooperates with breakpoints. """
2import lldb
3from lldbsuite.test.decorators import *
4from lldbsuite.test.lldbtest import *
5from lldbsuite.test import lldbutil
6
7
8class TestStopOnSharedlibraryEvents(TestBase):
9    @skipIfRemote
10    @skipIfWindows
11    @no_debug_info_test
12    def test_stopping_breakpoints(self):
13        self.do_test()
14
15    @skipIfRemote
16    @skipIfWindows
17    @no_debug_info_test
18    def test_auto_continue(self):
19        def auto_continue(bkpt):
20            bkpt.SetAutoContinue(True)
21
22        self.do_test(auto_continue)
23
24    @skipIfRemote
25    @skipIfWindows
26    @no_debug_info_test
27    def test_failing_condition(self):
28        def condition(bkpt):
29            bkpt.SetCondition("1 == 2")
30
31        self.do_test(condition)
32
33    @skipIfRemote
34    @skipIfWindows
35    @no_debug_info_test
36    def test_continue_callback(self):
37        def bkpt_callback(bkpt):
38            bkpt.SetScriptCallbackBody("return False")
39
40        self.do_test(bkpt_callback)
41
42    def do_test(self, bkpt_modifier=None):
43        self.build()
44        main_spec = lldb.SBFileSpec("main.cpp")
45        # Launch and stop before the dlopen call.
46        target, process, thread, _ = lldbutil.run_to_source_breakpoint(
47            self,
48            "// Set a breakpoint here",
49            main_spec,
50            extra_images=["load_a", "load_b"],
51        )
52
53        # Now turn on shared library events, continue and make sure we stop for the event.
54        self.runCmd("settings set target.process.stop-on-sharedlibrary-events 1")
55        self.addTearDownHook(
56            lambda: self.runCmd(
57                "settings set target.process.stop-on-sharedlibrary-events 0"
58            )
59        )
60
61        # Since I don't know how to check that we are at the "right place" to stop for
62        # shared library events, make an breakpoint after the load is done and
63        # make sure we don't stop there:
64        backstop_bkpt_1 = target.BreakpointCreateBySourceRegex(
65            "Set another here - we should not hit this one", main_spec
66        )
67        self.assertGreater(
68            backstop_bkpt_1.GetNumLocations(), 0, "Set our second breakpoint"
69        )
70
71        process.Continue()
72        self.assertState(
73            process.GetState(), lldb.eStateStopped, "We didn't stop for the load"
74        )
75        self.assertEqual(
76            backstop_bkpt_1.GetHitCount(), 0, "Hit our backstop breakpoint"
77        )
78
79        # We should be stopped after the library is loaded, check that:
80        found_it = False
81        for module in target.modules:
82            if module.file.basename.find("load_a") > -1:
83                found_it = True
84                break
85        self.assertTrue(found_it, "Found the loaded module.")
86
87        # Now capture the place where we stopped so we can set a breakpoint and make
88        # sure the breakpoint there works correctly:
89        load_address = process.GetSelectedThread().frames[0].addr
90        load_bkpt = target.BreakpointCreateBySBAddress(load_address)
91        self.assertGreater(load_bkpt.GetNumLocations(), 0, "Set the load breakpoint")
92
93        backstop_bkpt_1.SetEnabled(False)
94
95        backstop_bkpt_2 = target.BreakpointCreateBySourceRegex(
96            "Set a third here - we should not hit this one", main_spec
97        )
98        self.assertGreater(
99            backstop_bkpt_2.GetNumLocations(), 0, "Set our third breakpoint"
100        )
101
102        if bkpt_modifier is None:
103            process.Continue()
104            self.assertState(
105                process.GetState(), lldb.eStateStopped, "We didn't stop for the load"
106            )
107            self.assertEqual(
108                backstop_bkpt_2.GetHitCount(), 0, "Hit our backstop breakpoint"
109            )
110            self.assertStopReason(
111                thread.stop_reason,
112                lldb.eStopReasonBreakpoint,
113                "We attributed the stop to the breakpoint",
114            )
115            self.assertEqual(
116                load_bkpt.GetHitCount(), 1, "We hit our breakpoint at the load address"
117            )
118        else:
119            bkpt_modifier(load_bkpt)
120            process.Continue()
121            self.assertState(process.GetState(), lldb.eStateStopped, "We didn't stop")
122            self.assertTrue(thread.IsValid(), "Our thread was no longer valid.")
123            self.assertStopReason(
124                thread.stop_reason,
125                lldb.eStopReasonBreakpoint,
126                "We didn't hit some breakpoint",
127            )
128            self.assertEqual(
129                backstop_bkpt_2.GetHitCount(), 1, "We continued to the right breakpoint"
130            )
131