1"""
2Test that we obey thread conditioned breakpoints.
3"""
4
5
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12def using_current(test, thread, breakpoint):
13    bp_id = breakpoint.GetID()
14    test.runCmd("break modify -t current {0}".format(bp_id))
15
16
17def set_thread_id(test, thread, breakpoint):
18    id = thread.id
19    breakpoint.SetThreadID(id)
20
21
22def set_thread_name(test, thread, breakpoint):
23    breakpoint.SetThreadName("main-thread")
24
25
26class ThreadSpecificBreakTestCase(TestBase):
27    NO_DEBUG_INFO_TESTCASE = True
28
29    @add_test_categories(["pyapi"])
30    @expectedFailureAll(
31        oslist=["ios", "watchos", "tvos", "bridgeos"],
32        archs=["armv7", "armv7k"],
33        bugnumber="rdar://problem/34563920",
34    )  # armv7 ios problem - breakpoint with tid qualifier isn't working
35    @skipIf(oslist=["windows"], archs=["aarch64"])  # Flaky on buildbot
36    def test_thread_id(self):
37        self.do_test(set_thread_id)
38
39    @skipUnlessDarwin
40    @expectedFailureAll(
41        oslist=["ios", "watchos", "tvos", "bridgeos"],
42        archs=["armv7", "armv7k"],
43        bugnumber="rdar://problem/34563920",
44    )  # armv7 ios problem - breakpoint with tid qualifier isn't working
45    def test_thread_name(self):
46        self.do_test(set_thread_name)
47
48    @expectedFailureAll(
49        oslist=["ios", "watchos", "tvos", "bridgeos"],
50        archs=["armv7", "armv7k"],
51        bugnumber="rdar://problem/34563920",
52    )  # armv7 ios problem - breakpoint with tid qualifier isn't working
53    @skipIf(oslist=["windows"], archs=["aarch64"])  # Flaky on buildbot
54    def test_current_token(self):
55        self.do_test(using_current)
56
57    def do_test(self, setter_method):
58        """Test that we obey thread conditioned breakpoints."""
59        self.build()
60        main_source_spec = lldb.SBFileSpec("main.cpp")
61        (
62            target,
63            process,
64            main_thread,
65            main_breakpoint,
66        ) = lldbutil.run_to_source_breakpoint(
67            self, "Set main breakpoint here", main_source_spec
68        )
69
70        thread_breakpoint = target.BreakpointCreateBySourceRegex(
71            "Set thread-specific breakpoint here", main_source_spec
72        )
73        self.assertGreater(
74            thread_breakpoint.GetNumLocations(),
75            0,
76            "thread breakpoint has no locations associated with it.",
77        )
78
79        # Set the thread-specific breakpoint to stop only on the main thread
80        # before the secondary thread has a chance to execute it.  The main
81        # thread joins the secondary thread, and then the main thread will
82        # execute the code at the breakpoint.  If the thread-specific
83        # breakpoint works, the next stop will be on the main thread.
84        setter_method(self, main_thread, thread_breakpoint)
85
86        process.Continue()
87        next_stop_state = process.GetState()
88        self.assertEqual(
89            next_stop_state,
90            lldb.eStateStopped,
91            "We should have stopped at the thread breakpoint.",
92        )
93        stopped_threads = lldbutil.get_threads_stopped_at_breakpoint(
94            process, thread_breakpoint
95        )
96        self.assertEqual(
97            len(stopped_threads),
98            1,
99            "thread breakpoint stopped at unexpected number of threads",
100        )
101        self.assertEqual(
102            stopped_threads[0].GetThreadID(),
103            main_thread.GetThreadID(),
104            "thread breakpoint stopped at the wrong thread",
105        )
106