2 Test that we page getting a long backtrace on more than one thread
7 from lldbsuite
.test
.decorators
import *
8 from lldbsuite
.test
.lldbtest
import *
9 from lldbsuite
.test
import lldbutil
12 class TestThreadBacktracePage(TestBase
):
13 NO_DEBUG_INFO_TESTCASE
= True
15 def test_thread_backtrace_one_thread(self
):
16 """Run a simplified version of the test that just hits one breakpoint and
17 doesn't care about synchronizing the two threads - hopefully this will
18 run on more systems."""
25 ) = lldbutil
.run_to_source_breakpoint(
26 self
, self
.bkpt_string
, lldb
.SBFileSpec("main.cpp"), only_one_thread
=False
29 # We hit the breakpoint on at least one thread. If we hit it on both threads
30 # simultaneously, we are ready to run our tests. Otherwise, suspend the thread
31 # that hit the breakpoint, and continue till the second thread hits
34 (breakpoint_threads
, other_threads
) = ([], [])
35 lldbutil
.sort_stopped_threads(
37 breakpoint_threads
=breakpoint_threads
,
38 other_threads
=other_threads
,
41 len(breakpoint_threads
), 0, "We hit at least one breakpoint thread"
43 self
.assertGreater(len(breakpoint_threads
[0].frames
), 2, "I can go up")
44 thread_id
= breakpoint_threads
[0].idx
45 name
= breakpoint_threads
[0].frame
[1].name
.split("(")[0]
46 self
.check_one_thread(thread_id
, name
)
49 # Call super's setUp().
51 # Find the line number for our breakpoint.
52 self
.bkpt_string
= "// Set breakpoint here"
54 def check_one_thread(self
, thread_id
, func_name
):
55 # Now issue some thread backtrace commands and make sure they
56 # get the right answer back.
57 interp
= self
.dbg
.GetCommandInterpreter()
58 result
= lldb
.SBCommandReturnObject()
60 # Run the real backtrace, remember to pass True for add_to_history since
61 # we don't generate repeat commands for commands that aren't going into the history.
63 "thread backtrace --count 10 {0}".format(thread_id
), result
, True
65 self
.assertTrue(result
.Succeeded(), "bt with count succeeded")
66 # There should be 11 lines:
67 lines
= result
.GetOutput().splitlines()
68 self
.assertEqual(len(lines
), 11, "Got the right number of lines")
69 # First frame is stop_here:
70 self
.assertNotEqual(lines
[1].find("stop_here"), -1, "Found Stop Here")
71 for line
in lines
[2:10]:
75 "Name {0} not found in line: {1}".format(func_name
, line
),
77 # The last entry should be 43:
78 self
.assertNotEqual(lines
[10].find("count=43"), -1, "First show ends at 43")
80 # Now try a repeat, and make sure we get 10 more on this thread:
81 # import pdb; pdb.set_trace()
82 interp
.HandleCommand("", result
, True)
84 result
.Succeeded(), "repeat command failed: {0}".format(result
.GetError())
86 lines
= result
.GetOutput().splitlines()
87 self
.assertEqual(len(lines
), 11, "Repeat got 11 lines")
88 # Every line should now be the recurse function:
89 for line
in lines
[1:10]:
90 self
.assertNotEqual(line
.find(func_name
), -1, "Name in every line")
91 self
.assertNotEqual(lines
[10].find("count=33"), -1, "Last one is now 33")
93 def check_two_threads(
94 self
, result_str
, thread_id_1
, name_1
, thread_id_2
, name_2
, start_idx
, end_idx
96 # We should have 2 occurrences ot the thread header:
98 result_str
.count("thread #{0}".format(thread_id_1
)), 1, "One for thread 1"
101 result_str
.count("thread #{0}".format(thread_id_2
)), 1, "One for thread 2"
103 # We should have 10 occurrences of each name:
104 self
.assertEqual(result_str
.count(name_1
), 10, "Found 10 of {0}".format(name_1
))
105 self
.assertEqual(result_str
.count(name_2
), 10, "Found 10 of {0}".format(name_1
))
106 # There should be two instances of count=<start_idx> and none of count=<start-1>:
108 result_str
.count("count={0}".format(start_idx
)),
110 "Two instances of start_idx",
113 result_str
.count("count={0}".format(start_idx
- 1)),
115 "No instances of start_idx - 1",
117 # There should be two instances of count=<end_idx> and none of count=<end_idx+1>:
119 result_str
.count("count={0}".format(end_idx
)), 2, "Two instances of end_idx"
122 result_str
.count("count={0}".format(end_idx
+ 1)),
124 "No instances after end idx",
127 # The setup of this test was copied from the step-out test, and I can't tell from
128 # the comments whether it was getting two threads to the same breakpoint that was
129 # problematic, or the step-out part. This test stops at the rendevous point so I'm
130 # removing the skipIfLinux to see if we see any flakiness in just this part of the test.
131 @skipIfWindows # This test will hang on windows llvm.org/pr21753
132 @expectedFailureAll(oslist
=["windows"])
133 @expectedFailureNetBSD
134 def test_thread_backtrace_two_threads(self
):
135 """Test that repeat works even when backtracing on more than one thread."""
138 self
.inferior_target
,
142 ) = lldbutil
.run_to_source_breakpoint(
143 self
, self
.bkpt_string
, lldb
.SBFileSpec("main.cpp"), only_one_thread
=False
146 # We hit the breakpoint on at least one thread. If we hit it on both threads
147 # simultaneously, we are ready to run our tests. Otherwise, suspend the thread
148 # that hit the breakpoint, and continue till the second thread hits
151 (breakpoint_threads
, other_threads
) = ([], [])
152 lldbutil
.sort_stopped_threads(
154 breakpoint_threads
=breakpoint_threads
,
155 other_threads
=other_threads
,
157 if len(breakpoint_threads
) == 1:
158 success
= thread
.Suspend()
159 self
.assertTrue(success
, "Couldn't suspend a thread")
160 breakpoint_threads
= lldbutil
.continue_to_breakpoint(self
.process
, bkpt
)
161 self
.assertEqual(len(breakpoint_threads
), 2, "Second thread stopped")
163 # Figure out which thread is which:
164 thread_id_1
= breakpoint_threads
[0].idx
165 self
.assertGreater(len(breakpoint_threads
[0].frames
), 2, "I can go up")
166 name_1
= breakpoint_threads
[0].frame
[1].name
.split("(")[0]
168 thread_id_2
= breakpoint_threads
[1].idx
169 self
.assertGreater(len(breakpoint_threads
[1].frames
), 2, "I can go up")
170 name_2
= breakpoint_threads
[1].frame
[1].name
.split("(")[0]
172 # Check that backtrace and repeat works on one thread, then works on the second
173 # when we switch to it:
174 self
.check_one_thread(thread_id_1
, name_1
)
175 self
.check_one_thread(thread_id_2
, name_2
)
177 # The output is looking right at this point, let's just do a couple more quick checks
178 # to see we handle two threads and a start count:
179 interp
= self
.dbg
.GetCommandInterpreter()
180 result
= lldb
.SBCommandReturnObject()
182 interp
.HandleCommand(
183 "thread backtrace --count 10 --start 10 {0} {1}".format(
184 thread_id_1
, thread_id_2
189 self
.assertTrue(result
.Succeeded(), "command succeeded for two threads")
192 interp
.HandleCommand("", result
, True)
193 self
.assertTrue(result
.Succeeded(), "repeat command succeeded for two threads")
194 result_str
= result
.GetOutput()
195 self
.check_two_threads(
196 result_str
, thread_id_1
, name_1
, thread_id_2
, name_2
, 23, 32
199 # Finally make sure the repeat repeats:
201 interp
.HandleCommand("", result
, True)
202 self
.assertTrue(result
.Succeeded(), "repeat command succeeded for two threads")
203 result_str
= result
.GetOutput()
204 self
.check_two_threads(
205 result_str
, thread_id_1
, name_1
, thread_id_2
, name_2
, 13, 22