1""" 2Test thread states. 3""" 4 5 6import unittest 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 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 @expectedFailureNetBSD 24 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 randomly 30 @expectedFailureAll( 31 oslist=lldbplatformutil.getDarwinOSTriples(), bugnumber="llvm.org/pr23669" 32 ) 33 @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24660") 34 def test_state_after_continue(self): 35 """Test thread state after continue.""" 36 self.build() 37 self.thread_state_after_continue_test() 38 39 @skipIfDarwin # 'llvm.org/pr23669', cause Python crash randomly 40 @expectedFailureDarwin("llvm.org/pr23669") 41 @expectedFailureNetBSD 42 # This actually passes on Windows on Arm but it's hard to describe that 43 # and xfail it everywhere else. 44 @skipIfWindows 45 # thread states not properly maintained 46 @unittest.expectedFailure # llvm.org/pr16712 47 def test_state_after_expression(self): 48 """Test thread state after expression.""" 49 self.build() 50 self.thread_state_after_expression_test() 51 52 # thread states not properly maintained 53 @unittest.expectedFailure # llvm.org/pr15824 and <rdar://problem/28557237> 54 @expectedFailureAll( 55 oslist=["windows"], 56 bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly", 57 ) 58 @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237> 59 @expectedFailureNetBSD 60 def test_process_state(self): 61 """Test thread states (comprehensive).""" 62 self.build() 63 self.thread_states_test() 64 65 def setUp(self): 66 # Call super's setUp(). 67 TestBase.setUp(self) 68 # Find the line numbers for our breakpoints. 69 self.break_1 = line_number("main.cpp", "// Set first breakpoint here") 70 self.break_2 = line_number("main.cpp", "// Set second breakpoint here") 71 72 def thread_state_after_breakpoint_test(self): 73 """Test thread state after breakpoint.""" 74 exe = self.getBuildArtifact("a.out") 75 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 76 77 # This should create a breakpoint in the main thread. 78 bp = lldbutil.run_break_set_by_file_and_line( 79 self, "main.cpp", self.break_1, num_expected_locations=1 80 ) 81 82 # Run the program. 83 self.runCmd("run", RUN_SUCCEEDED) 84 85 # Get the target process 86 target = self.dbg.GetSelectedTarget() 87 process = target.GetProcess() 88 89 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 90 self.assertIsNotNone(thread) 91 92 # Make sure the thread is in the stopped state. 93 self.assertTrue( 94 thread.IsStopped(), "Thread state isn't 'stopped' during breakpoint 1." 95 ) 96 self.assertFalse( 97 thread.IsSuspended(), "Thread state is 'suspended' during breakpoint 1." 98 ) 99 100 # Kill the process 101 self.runCmd("process kill") 102 103 def wait_for_running_event(self, process): 104 listener = self.dbg.GetListener() 105 lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning]) 106 107 def thread_state_after_continue_test(self): 108 """Test thread state after continue.""" 109 exe = self.getBuildArtifact("a.out") 110 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 111 112 # This should create a breakpoint in the main thread. 113 lldbutil.run_break_set_by_file_and_line( 114 self, "main.cpp", self.break_1, num_expected_locations=1 115 ) 116 lldbutil.run_break_set_by_file_and_line( 117 self, "main.cpp", self.break_2, num_expected_locations=1 118 ) 119 120 # Run the program. 121 self.runCmd("run", RUN_SUCCEEDED) 122 123 # Get the target process 124 target = self.dbg.GetSelectedTarget() 125 process = target.GetProcess() 126 127 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 128 self.assertIsNotNone(thread) 129 130 # Continue, the inferior will go into an infinite loop waiting for 131 # 'g_test' to change. 132 self.dbg.SetAsync(True) 133 self.runCmd("continue") 134 self.wait_for_running_event(process) 135 136 # Check the thread state. It should be running. 137 self.assertFalse( 138 thread.IsStopped(), "Thread state is 'stopped' when it should be running." 139 ) 140 self.assertFalse( 141 thread.IsSuspended(), 142 "Thread state is 'suspended' when it should be running.", 143 ) 144 145 # Go back to synchronous interactions 146 self.dbg.SetAsync(False) 147 148 # Kill the process 149 self.runCmd("process kill") 150 151 def thread_state_after_expression_test(self): 152 """Test thread state after expression.""" 153 exe = self.getBuildArtifact("a.out") 154 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 155 156 # This should create a breakpoint in the main thread. 157 lldbutil.run_break_set_by_file_and_line( 158 self, "main.cpp", self.break_1, num_expected_locations=1 159 ) 160 lldbutil.run_break_set_by_file_and_line( 161 self, "main.cpp", self.break_2, num_expected_locations=1 162 ) 163 164 # Run the program. 165 self.runCmd("run", RUN_SUCCEEDED) 166 167 # Get the target process 168 target = self.dbg.GetSelectedTarget() 169 process = target.GetProcess() 170 171 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 172 self.assertIsNotNone(thread) 173 174 # Get the inferior out of its loop 175 self.runCmd("expression g_test = 1") 176 177 # Check the thread state 178 self.assertTrue( 179 thread.IsStopped(), 180 "Thread state isn't 'stopped' after expression evaluation.", 181 ) 182 self.assertFalse( 183 thread.IsSuspended(), 184 "Thread state is 'suspended' after expression evaluation.", 185 ) 186 187 # Let the process run to completion 188 self.runCmd("process continue") 189 190 @expectedFailureAll( 191 oslist=["windows"], 192 bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly", 193 ) 194 @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237> 195 @no_debug_info_test 196 def test_process_interrupt(self): 197 """Test process interrupt and continue.""" 198 self.build() 199 exe = self.getBuildArtifact("a.out") 200 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 201 202 # This should create a breakpoint in the main thread. 203 bpno = lldbutil.run_break_set_by_file_and_line( 204 self, "main.cpp", self.break_1, num_expected_locations=1 205 ) 206 207 # Run the program. 208 self.runCmd("run", RUN_SUCCEEDED) 209 210 # Get the target process 211 target = self.dbg.GetSelectedTarget() 212 process = target.GetProcess() 213 214 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 215 self.assertIsNotNone(thread) 216 217 # Remove the breakpoint to avoid the single-step-over-bkpt dance in the 218 # "continue" below 219 self.assertTrue(target.BreakpointDelete(bpno)) 220 221 # Continue, the inferior will go into an infinite loop waiting for 222 # 'g_test' to change. 223 self.dbg.SetAsync(True) 224 self.runCmd("continue") 225 self.wait_for_running_event(process) 226 227 # Go back to synchronous interactions 228 self.dbg.SetAsync(False) 229 230 # Stop the process 231 self.runCmd("process interrupt") 232 233 self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonSignal) 234 235 # Get the inferior out of its loop 236 self.runCmd("expression g_test = 1") 237 238 # Run to completion 239 self.runCmd("continue") 240 241 def thread_states_test(self): 242 """Test thread states (comprehensive).""" 243 exe = self.getBuildArtifact("a.out") 244 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 245 246 # This should create a breakpoint in the main thread. 247 lldbutil.run_break_set_by_file_and_line( 248 self, "main.cpp", self.break_1, num_expected_locations=1 249 ) 250 lldbutil.run_break_set_by_file_and_line( 251 self, "main.cpp", self.break_2, num_expected_locations=1 252 ) 253 254 # Run the program. 255 self.runCmd("run", RUN_SUCCEEDED) 256 257 # Get the target process 258 target = self.dbg.GetSelectedTarget() 259 process = target.GetProcess() 260 thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) 261 self.assertIsNotNone(thread) 262 263 # Make sure the thread is in the stopped state. 264 self.assertTrue( 265 thread.IsStopped(), "Thread state isn't 'stopped' during breakpoint 1." 266 ) 267 self.assertFalse( 268 thread.IsSuspended(), "Thread state is 'suspended' during breakpoint 1." 269 ) 270 271 # Continue, the inferior will go into an infinite loop waiting for 272 # 'g_test' to change. 273 self.dbg.SetAsync(True) 274 self.runCmd("continue") 275 self.wait_for_running_event(process) 276 277 # Check the thread state. It should be running. 278 self.assertFalse( 279 thread.IsStopped(), "Thread state is 'stopped' when it should be running." 280 ) 281 self.assertFalse( 282 thread.IsSuspended(), 283 "Thread state is 'suspended' when it should be running.", 284 ) 285 286 # Go back to synchronous interactions 287 self.dbg.SetAsync(False) 288 289 # Stop the process 290 self.runCmd("process interrupt") 291 292 self.assertStopReason(thread.GetState(), lldb.eStopReasonSignal) 293 294 # Check the thread state 295 self.assertTrue( 296 thread.IsStopped(), "Thread state isn't 'stopped' after process stop." 297 ) 298 self.assertFalse( 299 thread.IsSuspended(), "Thread state is 'suspended' after process stop." 300 ) 301 302 # Get the inferior out of its loop 303 self.runCmd("expression g_test = 1") 304 305 # Check the thread state 306 self.assertTrue( 307 thread.IsStopped(), 308 "Thread state isn't 'stopped' after expression evaluation.", 309 ) 310 self.assertFalse( 311 thread.IsSuspended(), 312 "Thread state is 'suspended' after expression evaluation.", 313 ) 314 315 self.assertStopReason(thread.GetState(), lldb.eStopReasonSignal) 316 317 # Run to breakpoint 2 318 self.runCmd("continue") 319 320 self.assertStopReason(thread.GetState(), lldb.eStopReasonBreakpoint) 321 322 # Make sure both threads are stopped 323 self.assertTrue( 324 thread.IsStopped(), "Thread state isn't 'stopped' during breakpoint 2." 325 ) 326 self.assertFalse( 327 thread.IsSuspended(), "Thread state is 'suspended' during breakpoint 2." 328 ) 329 330 # Run to completion 331 self.runCmd("continue") 332 333 # At this point, the inferior process should have exited. 334 self.assertState(process.GetState(), lldb.eStateExited, PROCESS_EXITED) 335