1""" 2Test number of threads. 3""" 4 5 6 7import lldb 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11 12 13class ExitDuringStepTestCase(TestBase): 14 15 mydir = TestBase.compute_mydir(__file__) 16 17 @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 18 def test(self): 19 """Test thread exit during step handling.""" 20 self.build(dictionary=self.getBuildFlags()) 21 self.exit_during_step_base( 22 "thread step-inst -m all-threads", 23 'stop reason = instruction step', 24 True) 25 26 @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 27 def test_step_over(self): 28 """Test thread exit during step-over handling.""" 29 self.build(dictionary=self.getBuildFlags()) 30 self.exit_during_step_base( 31 "thread step-over -m all-threads", 32 'stop reason = step over', 33 False) 34 35 @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 36 def test_step_in(self): 37 """Test thread exit during step-in handling.""" 38 self.build(dictionary=self.getBuildFlags()) 39 self.exit_during_step_base( 40 "thread step-in -m all-threads", 41 'stop reason = step in', 42 False) 43 44 def setUp(self): 45 # Call super's setUp(). 46 TestBase.setUp(self) 47 # Find the line numbers to break and continue. 48 self.breakpoint = line_number('main.cpp', '// Set breakpoint here') 49 self.continuepoint = line_number('main.cpp', '// Continue from here') 50 51 def exit_during_step_base(self, step_cmd, step_stop_reason, by_instruction): 52 """Test thread exit during step handling.""" 53 exe = self.getBuildArtifact("a.out") 54 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 55 56 # This should create a breakpoint in the main thread. 57 self.bp_num = lldbutil.run_break_set_by_file_and_line( 58 self, "main.cpp", self.breakpoint, num_expected_locations=1) 59 60 # The breakpoint list should show 1 location. 61 self.expect( 62 "breakpoint list -f", 63 "Breakpoint location shown correctly", 64 substrs=[ 65 "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" % 66 self.breakpoint]) 67 68 # Run the program. 69 self.runCmd("run", RUN_SUCCEEDED) 70 71 # The stop reason of the thread should be breakpoint. 72 self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, 73 substrs=['stopped', 74 'stop reason = breakpoint']) 75 76 # Get the target process 77 target = self.dbg.GetSelectedTarget() 78 process = target.GetProcess() 79 80 num_threads = process.GetNumThreads() 81 # Make sure we see all three threads 82 self.assertGreaterEqual( 83 num_threads, 84 3, 85 'Number of expected threads and actual threads do not match.') 86 87 stepping_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( 88 process, self.bp_num) 89 self.assertIsNotNone( 90 stepping_thread, 91 "Could not find a thread stopped at the breakpoint") 92 93 current_line = self.breakpoint 94 stepping_frame = stepping_thread.GetFrameAtIndex(0) 95 self.assertEqual( 96 current_line, 97 stepping_frame.GetLineEntry().GetLine(), 98 "Starting line for stepping doesn't match breakpoint line.") 99 100 # Keep stepping until we've reached our designated continue point 101 while current_line != self.continuepoint: 102 # Since we're using the command interpreter to issue the thread command 103 # (on the selected thread) we need to ensure the selected thread is the 104 # stepping thread. 105 if stepping_thread != process.GetSelectedThread(): 106 process.SetSelectedThread(stepping_thread) 107 108 self.runCmd(step_cmd) 109 110 frame = stepping_thread.GetFrameAtIndex(0) 111 112 current_line = frame.GetLineEntry().GetLine() 113 114 if by_instruction and current_line == 0: 115 continue 116 117 self.assertGreaterEqual( 118 current_line, 119 self.breakpoint, 120 "Stepped to unexpected line, " + 121 str(current_line)) 122 self.assertLessEqual( 123 current_line, 124 self.continuepoint, 125 "Stepped to unexpected line, " + 126 str(current_line)) 127 128 self.runCmd("thread list") 129 130 # Update the number of threads 131 new_num_threads = process.GetNumThreads() 132 133 # Check to see that we reduced the number of threads as expected 134 self.assertEqual( 135 new_num_threads, 136 num_threads - 1, 137 'Number of threads did not reduce by 1 after thread exit.') 138 139 self.expect("thread list", 'Process state is stopped due to step', 140 substrs=['stopped', 141 step_stop_reason]) 142 143 # Run to completion 144 self.runCmd("continue") 145 146 # At this point, the inferior process should have exited. 147 self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) 148