1635f03feSJim Ingham""" 2635f03feSJim InghamTest that we page getting a long backtrace on more than one thread 3635f03feSJim Ingham""" 4635f03feSJim Ingham 5635f03feSJim Ingham 6635f03feSJim Inghamimport lldb 7635f03feSJim Inghamfrom lldbsuite.test.decorators import * 8635f03feSJim Inghamfrom lldbsuite.test.lldbtest import * 9635f03feSJim Inghamfrom lldbsuite.test import lldbutil 10635f03feSJim Ingham 11635f03feSJim Ingham 12635f03feSJim Inghamclass TestThreadBacktracePage(TestBase): 13635f03feSJim Ingham NO_DEBUG_INFO_TESTCASE = True 14635f03feSJim Ingham 15635f03feSJim Ingham def test_thread_backtrace_one_thread(self): 16635f03feSJim Ingham """Run a simplified version of the test that just hits one breakpoint and 17635f03feSJim Ingham doesn't care about synchronizing the two threads - hopefully this will 18635f03feSJim Ingham run on more systems.""" 19635f03feSJim Ingham self.build() 20*2238dcc3SJonas Devlieghere ( 21*2238dcc3SJonas Devlieghere self.inferior_target, 22*2238dcc3SJonas Devlieghere self.process, 23*2238dcc3SJonas Devlieghere thread, 24*2238dcc3SJonas Devlieghere bkpt, 25*2238dcc3SJonas Devlieghere ) = lldbutil.run_to_source_breakpoint( 26*2238dcc3SJonas Devlieghere self, self.bkpt_string, lldb.SBFileSpec("main.cpp"), only_one_thread=False 27*2238dcc3SJonas Devlieghere ) 28635f03feSJim Ingham 29635f03feSJim Ingham # We hit the breakpoint on at least one thread. If we hit it on both threads 30635f03feSJim Ingham # simultaneously, we are ready to run our tests. Otherwise, suspend the thread 31635f03feSJim Ingham # that hit the breakpoint, and continue till the second thread hits 32635f03feSJim Ingham # the breakpoint: 33635f03feSJim Ingham 34635f03feSJim Ingham (breakpoint_threads, other_threads) = ([], []) 35*2238dcc3SJonas Devlieghere lldbutil.sort_stopped_threads( 36*2238dcc3SJonas Devlieghere self.process, 37635f03feSJim Ingham breakpoint_threads=breakpoint_threads, 38*2238dcc3SJonas Devlieghere other_threads=other_threads, 39*2238dcc3SJonas Devlieghere ) 40*2238dcc3SJonas Devlieghere self.assertGreater( 41*2238dcc3SJonas Devlieghere len(breakpoint_threads), 0, "We hit at least one breakpoint thread" 42*2238dcc3SJonas Devlieghere ) 43635f03feSJim Ingham self.assertGreater(len(breakpoint_threads[0].frames), 2, "I can go up") 44635f03feSJim Ingham thread_id = breakpoint_threads[0].idx 45635f03feSJim Ingham name = breakpoint_threads[0].frame[1].name.split("(")[0] 46635f03feSJim Ingham self.check_one_thread(thread_id, name) 47635f03feSJim Ingham 48635f03feSJim Ingham def setUp(self): 49635f03feSJim Ingham # Call super's setUp(). 50635f03feSJim Ingham TestBase.setUp(self) 51635f03feSJim Ingham # Find the line number for our breakpoint. 52*2238dcc3SJonas Devlieghere self.bkpt_string = "// Set breakpoint here" 53635f03feSJim Ingham 54635f03feSJim Ingham def check_one_thread(self, thread_id, func_name): 55635f03feSJim Ingham # Now issue some thread backtrace commands and make sure they 56635f03feSJim Ingham # get the right answer back. 57635f03feSJim Ingham interp = self.dbg.GetCommandInterpreter() 58635f03feSJim Ingham result = lldb.SBCommandReturnObject() 59635f03feSJim Ingham 60635f03feSJim Ingham # Run the real backtrace, remember to pass True for add_to_history since 61635f03feSJim Ingham # we don't generate repeat commands for commands that aren't going into the history. 62*2238dcc3SJonas Devlieghere interp.HandleCommand( 63*2238dcc3SJonas Devlieghere "thread backtrace --count 10 {0}".format(thread_id), result, True 64*2238dcc3SJonas Devlieghere ) 65635f03feSJim Ingham self.assertTrue(result.Succeeded(), "bt with count succeeded") 66635f03feSJim Ingham # There should be 11 lines: 67635f03feSJim Ingham lines = result.GetOutput().splitlines() 68635f03feSJim Ingham self.assertEqual(len(lines), 11, "Got the right number of lines") 69635f03feSJim Ingham # First frame is stop_here: 70635f03feSJim Ingham self.assertNotEqual(lines[1].find("stop_here"), -1, "Found Stop Here") 71635f03feSJim Ingham for line in lines[2:10]: 72*2238dcc3SJonas Devlieghere self.assertNotEqual( 73*2238dcc3SJonas Devlieghere line.find(func_name), 74*2238dcc3SJonas Devlieghere -1, 75*2238dcc3SJonas Devlieghere "Name {0} not found in line: {1}".format(func_name, line), 76*2238dcc3SJonas Devlieghere ) 77635f03feSJim Ingham # The last entry should be 43: 78635f03feSJim Ingham self.assertNotEqual(lines[10].find("count=43"), -1, "First show ends at 43") 79635f03feSJim Ingham 80635f03feSJim Ingham # Now try a repeat, and make sure we get 10 more on this thread: 81635f03feSJim Ingham # import pdb; pdb.set_trace() 82635f03feSJim Ingham interp.HandleCommand("", result, True) 83*2238dcc3SJonas Devlieghere self.assertTrue( 84*2238dcc3SJonas Devlieghere result.Succeeded(), "repeat command failed: {0}".format(result.GetError()) 85*2238dcc3SJonas Devlieghere ) 86635f03feSJim Ingham lines = result.GetOutput().splitlines() 87635f03feSJim Ingham self.assertEqual(len(lines), 11, "Repeat got 11 lines") 88635f03feSJim Ingham # Every line should now be the recurse function: 89635f03feSJim Ingham for line in lines[1:10]: 90635f03feSJim Ingham self.assertNotEqual(line.find(func_name), -1, "Name in every line") 91635f03feSJim Ingham self.assertNotEqual(lines[10].find("count=33"), -1, "Last one is now 33") 92635f03feSJim Ingham 93*2238dcc3SJonas Devlieghere def check_two_threads( 94*2238dcc3SJonas Devlieghere self, result_str, thread_id_1, name_1, thread_id_2, name_2, start_idx, end_idx 95*2238dcc3SJonas Devlieghere ): 96635f03feSJim Ingham # We should have 2 occurrences ot the thread header: 97*2238dcc3SJonas Devlieghere self.assertEqual( 98*2238dcc3SJonas Devlieghere result_str.count("thread #{0}".format(thread_id_1)), 1, "One for thread 1" 99*2238dcc3SJonas Devlieghere ) 100*2238dcc3SJonas Devlieghere self.assertEqual( 101*2238dcc3SJonas Devlieghere result_str.count("thread #{0}".format(thread_id_2)), 1, "One for thread 2" 102*2238dcc3SJonas Devlieghere ) 103635f03feSJim Ingham # We should have 10 occurrences of each name: 104635f03feSJim Ingham self.assertEqual(result_str.count(name_1), 10, "Found 10 of {0}".format(name_1)) 105635f03feSJim Ingham self.assertEqual(result_str.count(name_2), 10, "Found 10 of {0}".format(name_1)) 106635f03feSJim Ingham # There should be two instances of count=<start_idx> and none of count=<start-1>: 107*2238dcc3SJonas Devlieghere self.assertEqual( 108*2238dcc3SJonas Devlieghere result_str.count("count={0}".format(start_idx)), 109*2238dcc3SJonas Devlieghere 2, 110*2238dcc3SJonas Devlieghere "Two instances of start_idx", 111*2238dcc3SJonas Devlieghere ) 112*2238dcc3SJonas Devlieghere self.assertEqual( 113*2238dcc3SJonas Devlieghere result_str.count("count={0}".format(start_idx - 1)), 114*2238dcc3SJonas Devlieghere 0, 115*2238dcc3SJonas Devlieghere "No instances of start_idx - 1", 116*2238dcc3SJonas Devlieghere ) 117635f03feSJim Ingham # There should be two instances of count=<end_idx> and none of count=<end_idx+1>: 118*2238dcc3SJonas Devlieghere self.assertEqual( 119*2238dcc3SJonas Devlieghere result_str.count("count={0}".format(end_idx)), 2, "Two instances of end_idx" 120*2238dcc3SJonas Devlieghere ) 121*2238dcc3SJonas Devlieghere self.assertEqual( 122*2238dcc3SJonas Devlieghere result_str.count("count={0}".format(end_idx + 1)), 123*2238dcc3SJonas Devlieghere 0, 124*2238dcc3SJonas Devlieghere "No instances after end idx", 125*2238dcc3SJonas Devlieghere ) 126635f03feSJim Ingham 127635f03feSJim Ingham # The setup of this test was copied from the step-out test, and I can't tell from 128635f03feSJim Ingham # the comments whether it was getting two threads to the same breakpoint that was 129635f03feSJim Ingham # problematic, or the step-out part. This test stops at the rendevous point so I'm 130635f03feSJim Ingham # removing the skipIfLinux to see if we see any flakiness in just this part of the test. 131635f03feSJim Ingham @skipIfWindows # This test will hang on windows llvm.org/pr21753 132635f03feSJim Ingham @expectedFailureAll(oslist=["windows"]) 133635f03feSJim Ingham @expectedFailureNetBSD 134635f03feSJim Ingham def test_thread_backtrace_two_threads(self): 135635f03feSJim Ingham """Test that repeat works even when backtracing on more than one thread.""" 136635f03feSJim Ingham self.build() 137*2238dcc3SJonas Devlieghere ( 138*2238dcc3SJonas Devlieghere self.inferior_target, 139*2238dcc3SJonas Devlieghere self.process, 140*2238dcc3SJonas Devlieghere thread, 141*2238dcc3SJonas Devlieghere bkpt, 142*2238dcc3SJonas Devlieghere ) = lldbutil.run_to_source_breakpoint( 143*2238dcc3SJonas Devlieghere self, self.bkpt_string, lldb.SBFileSpec("main.cpp"), only_one_thread=False 144*2238dcc3SJonas Devlieghere ) 145635f03feSJim Ingham 146635f03feSJim Ingham # We hit the breakpoint on at least one thread. If we hit it on both threads 147635f03feSJim Ingham # simultaneously, we are ready to run our tests. Otherwise, suspend the thread 148635f03feSJim Ingham # that hit the breakpoint, and continue till the second thread hits 149635f03feSJim Ingham # the breakpoint: 150635f03feSJim Ingham 151635f03feSJim Ingham (breakpoint_threads, other_threads) = ([], []) 152*2238dcc3SJonas Devlieghere lldbutil.sort_stopped_threads( 153*2238dcc3SJonas Devlieghere self.process, 154635f03feSJim Ingham breakpoint_threads=breakpoint_threads, 155*2238dcc3SJonas Devlieghere other_threads=other_threads, 156*2238dcc3SJonas Devlieghere ) 157635f03feSJim Ingham if len(breakpoint_threads) == 1: 158635f03feSJim Ingham success = thread.Suspend() 159635f03feSJim Ingham self.assertTrue(success, "Couldn't suspend a thread") 160*2238dcc3SJonas Devlieghere breakpoint_threads = lldbutil.continue_to_breakpoint(self.process, bkpt) 161f8d42c55SPavel Labath self.assertEqual(len(breakpoint_threads), 2, "Second thread stopped") 162635f03feSJim Ingham 163635f03feSJim Ingham # Figure out which thread is which: 164635f03feSJim Ingham thread_id_1 = breakpoint_threads[0].idx 165635f03feSJim Ingham self.assertGreater(len(breakpoint_threads[0].frames), 2, "I can go up") 166635f03feSJim Ingham name_1 = breakpoint_threads[0].frame[1].name.split("(")[0] 167635f03feSJim Ingham 168635f03feSJim Ingham thread_id_2 = breakpoint_threads[1].idx 169635f03feSJim Ingham self.assertGreater(len(breakpoint_threads[1].frames), 2, "I can go up") 170635f03feSJim Ingham name_2 = breakpoint_threads[1].frame[1].name.split("(")[0] 171635f03feSJim Ingham 172635f03feSJim Ingham # Check that backtrace and repeat works on one thread, then works on the second 173635f03feSJim Ingham # when we switch to it: 174635f03feSJim Ingham self.check_one_thread(thread_id_1, name_1) 175635f03feSJim Ingham self.check_one_thread(thread_id_2, name_2) 176635f03feSJim Ingham 177635f03feSJim Ingham # The output is looking right at this point, let's just do a couple more quick checks 178635f03feSJim Ingham # to see we handle two threads and a start count: 179635f03feSJim Ingham interp = self.dbg.GetCommandInterpreter() 180635f03feSJim Ingham result = lldb.SBCommandReturnObject() 181635f03feSJim Ingham 182*2238dcc3SJonas Devlieghere interp.HandleCommand( 183*2238dcc3SJonas Devlieghere "thread backtrace --count 10 --start 10 {0} {1}".format( 184*2238dcc3SJonas Devlieghere thread_id_1, thread_id_2 185*2238dcc3SJonas Devlieghere ), 186*2238dcc3SJonas Devlieghere result, 187*2238dcc3SJonas Devlieghere True, 188*2238dcc3SJonas Devlieghere ) 189635f03feSJim Ingham self.assertTrue(result.Succeeded(), "command succeeded for two threads") 190635f03feSJim Ingham 191635f03feSJim Ingham result.Clear() 192635f03feSJim Ingham interp.HandleCommand("", result, True) 193635f03feSJim Ingham self.assertTrue(result.Succeeded(), "repeat command succeeded for two threads") 194635f03feSJim Ingham result_str = result.GetOutput() 195*2238dcc3SJonas Devlieghere self.check_two_threads( 196*2238dcc3SJonas Devlieghere result_str, thread_id_1, name_1, thread_id_2, name_2, 23, 32 197*2238dcc3SJonas Devlieghere ) 198635f03feSJim Ingham 199635f03feSJim Ingham # Finally make sure the repeat repeats: 200635f03feSJim Ingham result.Clear() 201635f03feSJim Ingham interp.HandleCommand("", result, True) 202635f03feSJim Ingham self.assertTrue(result.Succeeded(), "repeat command succeeded for two threads") 203635f03feSJim Ingham result_str = result.GetOutput() 204*2238dcc3SJonas Devlieghere self.check_two_threads( 205*2238dcc3SJonas Devlieghere result_str, thread_id_1, name_1, thread_id_2, name_2, 13, 22 206*2238dcc3SJonas Devlieghere ) 207