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 NumberOfThreadsTestCase(TestBase): 13 NO_DEBUG_INFO_TESTCASE = True 14 15 def setUp(self): 16 # Call super's setUp(). 17 TestBase.setUp(self) 18 # Find the line numbers for our break points. 19 self.thread3_notify_all_line = line_number( 20 "main.cpp", "// Set thread3 break point on notify_all at this line." 21 ) 22 self.thread3_before_lock_line = line_number( 23 "main.cpp", "// thread3-before-lock" 24 ) 25 26 def test_number_of_threads(self): 27 """Test number of threads.""" 28 self.build() 29 exe = self.getBuildArtifact("a.out") 30 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 31 32 # This should create a breakpoint with 1 location. 33 lldbutil.run_break_set_by_file_and_line( 34 self, "main.cpp", self.thread3_notify_all_line, num_expected_locations=1 35 ) 36 37 # The breakpoint list should show 1 location. 38 self.expect( 39 "breakpoint list -f", 40 "Breakpoint location shown correctly", 41 substrs=[ 42 "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" 43 % self.thread3_notify_all_line 44 ], 45 ) 46 47 # Run the program. 48 self.runCmd("run", RUN_SUCCEEDED) 49 50 # Stopped once. 51 self.expect( 52 "thread list", 53 STOPPED_DUE_TO_BREAKPOINT, 54 substrs=["stop reason = breakpoint 1."], 55 ) 56 57 # Get the target process 58 target = self.dbg.GetSelectedTarget() 59 process = target.GetProcess() 60 61 # Get the number of threads 62 num_threads = process.GetNumThreads() 63 64 # Using std::thread may involve extra threads, so we assert that there are 65 # at least 4 rather than exactly 4. 66 self.assertGreaterEqual( 67 num_threads, 68 13, 69 "Number of expected threads and actual threads do not match.", 70 ) 71 72 @skipIfDarwin # rdar://33462362 73 @skipIfWindows # This is flakey on Windows: llvm.org/pr37658, llvm.org/pr38373 74 def test_unique_stacks(self): 75 """Test backtrace unique with multiple threads executing the same stack.""" 76 self.build() 77 exe = self.getBuildArtifact("a.out") 78 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 79 80 # Set a break point on the thread3 notify all (should get hit on threads 4-13). 81 lldbutil.run_break_set_by_file_and_line( 82 self, "main.cpp", self.thread3_before_lock_line, num_expected_locations=1 83 ) 84 85 # Run the program. 86 self.runCmd("run", RUN_SUCCEEDED) 87 88 # Stopped once. 89 self.expect( 90 "thread list", 91 STOPPED_DUE_TO_BREAKPOINT, 92 substrs=["stop reason = breakpoint 1."], 93 ) 94 95 process = self.process() 96 97 # Get the number of threads 98 num_threads = process.GetNumThreads() 99 100 # Using std::thread may involve extra threads, so we assert that there are 101 # at least 10 thread3's rather than exactly 10. 102 self.assertGreaterEqual( 103 num_threads, 104 10, 105 "Number of expected threads and actual threads do not match.", 106 ) 107 108 # Attempt to walk each of the thread's executing the thread3 function to 109 # the same breakpoint. 110 def is_thread3(thread): 111 for frame in thread: 112 if frame.GetFunctionName() is None: 113 continue 114 if "thread3" in frame.GetFunctionName(): 115 return True 116 return False 117 118 expect_threads = "" 119 for i in range(num_threads): 120 thread = process.GetThreadAtIndex(i) 121 self.assertTrue(thread.IsValid()) 122 if not is_thread3(thread): 123 continue 124 125 # If we aren't stopped out the thread breakpoint try to resume. 126 if thread.GetStopReason() != lldb.eStopReasonBreakpoint: 127 self.runCmd("thread continue %d" % (i + 1)) 128 self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonBreakpoint) 129 130 expect_threads += " #%d" % (i + 1) 131 132 # Construct our expected back trace string 133 expect_string = "10 thread(s)%s" % (expect_threads) 134 135 # Now that we are stopped, we should have 10 threads waiting in the 136 # thread3 function. All of these threads should show as one stack. 137 self.expect( 138 "thread backtrace unique", 139 "Backtrace with unique stack shown correctly", 140 substrs=[expect_string, "main.cpp:%d" % self.thread3_before_lock_line], 141 ) 142