334 lines · python
1"""2Test thread states.3"""4 5 6import unittest7import lldb8from lldbsuite.test.decorators import *9from lldbsuite.test.lldbtest import *10from lldbsuite.test import lldbutil11 12 13class ThreadStateTestCase(TestBase):14 @expectedFailureAll(15 oslist=["linux"],16 bugnumber="llvm.org/pr15824 thread states not properly maintained",17 )18 @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>19 @expectedFailureAll(20 oslist=["freebsd"],21 bugnumber="llvm.org/pr18190 thread states not properly maintained",22 )23 @expectedFailureNetBSD24 def test_state_after_breakpoint(self):25 """Test thread state after breakpoint."""26 self.build()27 self.thread_state_after_breakpoint_test()28 29 @skipIfDarwin # 'llvm.org/pr23669', cause Python crash randomly30 @expectedFailureAll(31 oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr23669"32 )33 def test_state_after_continue(self):34 """Test thread state after continue."""35 self.build()36 self.thread_state_after_continue_test()37 38 @skipIfDarwin # 'llvm.org/pr23669', cause Python crash randomly39 @expectedFailureDarwin("llvm.org/pr23669")40 @expectedFailureNetBSD41 # This actually passes on Windows on Arm but it's hard to describe that42 # and xfail it everywhere else.43 @skipIfWindows44 # thread states not properly maintained45 @unittest.expectedFailure # llvm.org/pr1671246 def test_state_after_expression(self):47 """Test thread state after expression."""48 self.build()49 self.thread_state_after_expression_test()50 51 # thread states not properly maintained52 @unittest.expectedFailure # llvm.org/pr15824 and <rdar://problem/28557237>53 @expectedFailureAll(54 oslist=["windows"],55 bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly",56 )57 @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>58 @expectedFailureNetBSD59 def test_process_state(self):60 """Test thread states (comprehensive)."""61 self.build()62 self.thread_states_test()63 64 def setUp(self):65 # Call super's setUp().66 TestBase.setUp(self)67 # Find the line numbers for our breakpoints.68 self.break_1 = line_number("main.cpp", "// Set first breakpoint here")69 self.break_2 = line_number("main.cpp", "// Set second breakpoint here")70 71 def thread_state_after_breakpoint_test(self):72 """Test thread state after breakpoint."""73 exe = self.getBuildArtifact("a.out")74 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)75 76 # This should create a breakpoint in the main thread.77 bp = lldbutil.run_break_set_by_file_and_line(78 self, "main.cpp", self.break_1, num_expected_locations=179 )80 81 # Run the program.82 self.runCmd("run", RUN_SUCCEEDED)83 84 # Get the target process85 target = self.dbg.GetSelectedTarget()86 process = target.GetProcess()87 88 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)89 self.assertIsNotNone(thread)90 91 # Make sure the thread is in the stopped state.92 self.assertTrue(93 thread.IsStopped(), "Thread state isn't 'stopped' during breakpoint 1."94 )95 self.assertFalse(96 thread.IsSuspended(), "Thread state is 'suspended' during breakpoint 1."97 )98 99 # Kill the process100 self.runCmd("process kill")101 102 def wait_for_running_event(self, process):103 listener = self.dbg.GetListener()104 lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning])105 106 def thread_state_after_continue_test(self):107 """Test thread state after continue."""108 exe = self.getBuildArtifact("a.out")109 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)110 111 # This should create a breakpoint in the main thread.112 lldbutil.run_break_set_by_file_and_line(113 self, "main.cpp", self.break_1, num_expected_locations=1114 )115 lldbutil.run_break_set_by_file_and_line(116 self, "main.cpp", self.break_2, num_expected_locations=1117 )118 119 # Run the program.120 self.runCmd("run", RUN_SUCCEEDED)121 122 # Get the target process123 target = self.dbg.GetSelectedTarget()124 process = target.GetProcess()125 126 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)127 self.assertIsNotNone(thread)128 129 # Continue, the inferior will go into an infinite loop waiting for130 # 'g_test' to change.131 self.dbg.SetAsync(True)132 self.runCmd("continue")133 self.wait_for_running_event(process)134 135 # Check the thread state. It should be running.136 self.assertFalse(137 thread.IsStopped(), "Thread state is 'stopped' when it should be running."138 )139 self.assertFalse(140 thread.IsSuspended(),141 "Thread state is 'suspended' when it should be running.",142 )143 144 # Go back to synchronous interactions145 self.dbg.SetAsync(False)146 147 # Kill the process148 self.runCmd("process kill")149 150 def thread_state_after_expression_test(self):151 """Test thread state after expression."""152 exe = self.getBuildArtifact("a.out")153 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)154 155 # This should create a breakpoint in the main thread.156 lldbutil.run_break_set_by_file_and_line(157 self, "main.cpp", self.break_1, num_expected_locations=1158 )159 lldbutil.run_break_set_by_file_and_line(160 self, "main.cpp", self.break_2, num_expected_locations=1161 )162 163 # Run the program.164 self.runCmd("run", RUN_SUCCEEDED)165 166 # Get the target process167 target = self.dbg.GetSelectedTarget()168 process = target.GetProcess()169 170 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)171 self.assertIsNotNone(thread)172 173 # Get the inferior out of its loop174 self.runCmd("expression g_test = 1")175 176 # Check the thread state177 self.assertTrue(178 thread.IsStopped(),179 "Thread state isn't 'stopped' after expression evaluation.",180 )181 self.assertFalse(182 thread.IsSuspended(),183 "Thread state is 'suspended' after expression evaluation.",184 )185 186 # Let the process run to completion187 self.runCmd("process continue")188 189 @expectedFailureAll(190 oslist=["windows"],191 bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly",192 )193 @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>194 @no_debug_info_test195 def test_process_interrupt(self):196 """Test process interrupt and continue."""197 self.build()198 exe = self.getBuildArtifact("a.out")199 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)200 201 # This should create a breakpoint in the main thread.202 bpno = lldbutil.run_break_set_by_file_and_line(203 self, "main.cpp", self.break_1, num_expected_locations=1204 )205 206 # Run the program.207 self.runCmd("run", RUN_SUCCEEDED)208 209 # Get the target process210 target = self.dbg.GetSelectedTarget()211 process = target.GetProcess()212 213 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)214 self.assertIsNotNone(thread)215 216 # Remove the breakpoint to avoid the single-step-over-bkpt dance in the217 # "continue" below218 self.assertTrue(target.BreakpointDelete(bpno))219 220 # Continue, the inferior will go into an infinite loop waiting for221 # 'g_test' to change.222 self.dbg.SetAsync(True)223 self.runCmd("continue")224 self.wait_for_running_event(process)225 226 # Go back to synchronous interactions227 self.dbg.SetAsync(False)228 229 # Stop the process230 self.runCmd("process interrupt")231 232 self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal)233 234 # Get the inferior out of its loop235 self.runCmd("expression g_test = 1")236 237 # Run to completion238 self.runCmd("continue")239 240 def thread_states_test(self):241 """Test thread states (comprehensive)."""242 exe = self.getBuildArtifact("a.out")243 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)244 245 # This should create a breakpoint in the main thread.246 lldbutil.run_break_set_by_file_and_line(247 self, "main.cpp", self.break_1, num_expected_locations=1248 )249 lldbutil.run_break_set_by_file_and_line(250 self, "main.cpp", self.break_2, num_expected_locations=1251 )252 253 # Run the program.254 self.runCmd("run", RUN_SUCCEEDED)255 256 # Get the target process257 target = self.dbg.GetSelectedTarget()258 process = target.GetProcess()259 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)260 self.assertIsNotNone(thread)261 262 # Make sure the thread is in the stopped state.263 self.assertTrue(264 thread.IsStopped(), "Thread state isn't 'stopped' during breakpoint 1."265 )266 self.assertFalse(267 thread.IsSuspended(), "Thread state is 'suspended' during breakpoint 1."268 )269 270 # Continue, the inferior will go into an infinite loop waiting for271 # 'g_test' to change.272 self.dbg.SetAsync(True)273 self.runCmd("continue")274 self.wait_for_running_event(process)275 276 # Check the thread state. It should be running.277 self.assertFalse(278 thread.IsStopped(), "Thread state is 'stopped' when it should be running."279 )280 self.assertFalse(281 thread.IsSuspended(),282 "Thread state is 'suspended' when it should be running.",283 )284 285 # Go back to synchronous interactions286 self.dbg.SetAsync(False)287 288 # Stop the process289 self.runCmd("process interrupt")290 291 self.assertStopReason(thread.GetState(), lldb.eStopReasonSignal)292 293 # Check the thread state294 self.assertTrue(295 thread.IsStopped(), "Thread state isn't 'stopped' after process stop."296 )297 self.assertFalse(298 thread.IsSuspended(), "Thread state is 'suspended' after process stop."299 )300 301 # Get the inferior out of its loop302 self.runCmd("expression g_test = 1")303 304 # Check the thread state305 self.assertTrue(306 thread.IsStopped(),307 "Thread state isn't 'stopped' after expression evaluation.",308 )309 self.assertFalse(310 thread.IsSuspended(),311 "Thread state is 'suspended' after expression evaluation.",312 )313 314 self.assertStopReason(thread.GetState(), lldb.eStopReasonSignal)315 316 # Run to breakpoint 2317 self.runCmd("continue")318 319 self.assertStopReason(thread.GetState(), lldb.eStopReasonBreakpoint)320 321 # Make sure both threads are stopped322 self.assertTrue(323 thread.IsStopped(), "Thread state isn't 'stopped' during breakpoint 2."324 )325 self.assertFalse(326 thread.IsSuspended(), "Thread state is 'suspended' during breakpoint 2."327 )328 329 # Run to completion330 self.runCmd("continue")331 332 # At this point, the inferior process should have exited.333 self.assertState(process.GetState(), lldb.eStateExited, PROCESS_EXITED)334