1""" 2Test number of threads. 3""" 4 5 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9import lldbsuite.test.lldbutil as lldbutil 10 11 12class ThreadExitTestCase(TestBase): 13 def setUp(self): 14 # Call super's setUp(). 15 TestBase.setUp(self) 16 # Find the line numbers for our breakpoints. 17 self.break_1 = line_number("main.cpp", "// Set first breakpoint here") 18 self.break_2 = line_number("main.cpp", "// Set second breakpoint here") 19 self.break_3 = line_number("main.cpp", "// Set third breakpoint here") 20 self.break_4 = line_number("main.cpp", "// Set fourth breakpoint here") 21 22 @skipIfWindows # This is flakey on Windows: llvm.org/pr38373 23 def test(self): 24 """Test thread exit handling.""" 25 self.build() 26 exe = self.getBuildArtifact("a.out") 27 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 28 29 # This should create a breakpoint with 1 location. 30 bp1_id = lldbutil.run_break_set_by_file_and_line( 31 self, "main.cpp", self.break_1, num_expected_locations=1 32 ) 33 bp2_id = lldbutil.run_break_set_by_file_and_line( 34 self, "main.cpp", self.break_2, num_expected_locations=1 35 ) 36 bp3_id = lldbutil.run_break_set_by_file_and_line( 37 self, "main.cpp", self.break_3, num_expected_locations=1 38 ) 39 bp4_id = lldbutil.run_break_set_by_file_and_line( 40 self, "main.cpp", self.break_4, num_expected_locations=1 41 ) 42 43 # The breakpoint list should show 1 locations. 44 self.expect( 45 "breakpoint list -f", 46 "Breakpoint location shown correctly", 47 substrs=[ 48 "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" 49 % self.break_1, 50 "2: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" 51 % self.break_2, 52 "3: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" 53 % self.break_3, 54 "4: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" 55 % self.break_4, 56 ], 57 ) 58 59 # Run the program. 60 self.runCmd("run", RUN_SUCCEEDED) 61 # Get the target process 62 target = self.dbg.GetSelectedTarget() 63 process = target.GetProcess() 64 65 stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( 66 process, bp1_id 67 ) 68 self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 1") 69 70 # Get the number of threads 71 num_threads = process.GetNumThreads() 72 self.assertGreaterEqual( 73 num_threads, 74 2, 75 "Number of expected threads and actual threads do not match at breakpoint 1.", 76 ) 77 78 # Run to the second breakpoint 79 self.runCmd("continue") 80 stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( 81 process, bp2_id 82 ) 83 self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 2") 84 85 # Update the number of threads 86 new_num_threads = process.GetNumThreads() 87 self.assertEqual( 88 new_num_threads, 89 num_threads + 1, 90 "Number of expected threads did not increase by 1 at bp 2.", 91 ) 92 93 # Run to the third breakpoint 94 self.runCmd("continue") 95 stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( 96 process, bp3_id 97 ) 98 self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 3") 99 100 # Update the number of threads 101 new_num_threads = process.GetNumThreads() 102 self.assertEqual( 103 new_num_threads, 104 num_threads, 105 "Number of expected threads is not equal to original number of threads at bp 3.", 106 ) 107 108 # Run to the fourth breakpoint 109 self.runCmd("continue") 110 stopped_thread = lldbutil.get_one_thread_stopped_at_breakpoint_id( 111 process, bp4_id 112 ) 113 self.assertIsNotNone(stopped_thread, "Process is not stopped at breakpoint 4") 114 115 # Update the number of threads 116 new_num_threads = process.GetNumThreads() 117 self.assertEqual( 118 new_num_threads, 119 num_threads - 1, 120 "Number of expected threads did not decrease by 1 at bp 4.", 121 ) 122 123 # Run to completion 124 self.runCmd("continue") 125 126 # At this point, the inferior process should have exited. 127 self.assertState(process.GetState(), lldb.eStateExited, PROCESS_EXITED) 128