1635f03feSJim Ingham""" 2635f03feSJim InghamTest that we page getting a long backtrace on more than one thread 3635f03feSJim Ingham""" 4635f03feSJim Ingham 5635f03feSJim Ingham 6635f03feSJim Ingham 7635f03feSJim Inghamimport lldb 8635f03feSJim Inghamfrom lldbsuite.test.decorators import * 9635f03feSJim Inghamfrom lldbsuite.test.lldbtest import * 10635f03feSJim Inghamfrom lldbsuite.test import lldbutil 11635f03feSJim Ingham 12635f03feSJim Ingham 13635f03feSJim Inghamclass TestThreadBacktracePage(TestBase): 14635f03feSJim Ingham NO_DEBUG_INFO_TESTCASE = True 15635f03feSJim Ingham 16635f03feSJim Ingham def test_thread_backtrace_one_thread(self): 17635f03feSJim Ingham """Run a simplified version of the test that just hits one breakpoint and 18635f03feSJim Ingham doesn't care about synchronizing the two threads - hopefully this will 19635f03feSJim Ingham run on more systems.""" 20635f03feSJim Ingham 21635f03feSJim Ingham def test_thread_backtrace_one_thread(self): 22635f03feSJim Ingham self.build() 23635f03feSJim Ingham (self.inferior_target, self.process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 24635f03feSJim Ingham self, self.bkpt_string, lldb.SBFileSpec('main.cpp'), only_one_thread = False) 25635f03feSJim Ingham 26635f03feSJim Ingham # We hit the breakpoint on at least one thread. If we hit it on both threads 27635f03feSJim Ingham # simultaneously, we are ready to run our tests. Otherwise, suspend the thread 28635f03feSJim Ingham # that hit the breakpoint, and continue till the second thread hits 29635f03feSJim Ingham # the breakpoint: 30635f03feSJim Ingham 31635f03feSJim Ingham (breakpoint_threads, other_threads) = ([], []) 32635f03feSJim Ingham lldbutil.sort_stopped_threads(self.process, 33635f03feSJim Ingham breakpoint_threads=breakpoint_threads, 34635f03feSJim Ingham other_threads=other_threads) 35635f03feSJim Ingham self.assertGreater(len(breakpoint_threads), 0, "We hit at least one breakpoint thread") 36635f03feSJim Ingham self.assertGreater(len(breakpoint_threads[0].frames), 2, "I can go up") 37635f03feSJim Ingham thread_id = breakpoint_threads[0].idx 38635f03feSJim Ingham name = breakpoint_threads[0].frame[1].name.split("(")[0] 39635f03feSJim Ingham self.check_one_thread(thread_id, name) 40635f03feSJim Ingham 41635f03feSJim Ingham def setUp(self): 42635f03feSJim Ingham # Call super's setUp(). 43635f03feSJim Ingham TestBase.setUp(self) 44635f03feSJim Ingham # Find the line number for our breakpoint. 45635f03feSJim Ingham self.bkpt_string = '// Set breakpoint here' 46635f03feSJim Ingham 47635f03feSJim Ingham def check_one_thread(self, thread_id, func_name): 48635f03feSJim Ingham # Now issue some thread backtrace commands and make sure they 49635f03feSJim Ingham # get the right answer back. 50635f03feSJim Ingham interp = self.dbg.GetCommandInterpreter() 51635f03feSJim Ingham result = lldb.SBCommandReturnObject() 52635f03feSJim Ingham 53635f03feSJim Ingham # Run the real backtrace, remember to pass True for add_to_history since 54635f03feSJim Ingham # we don't generate repeat commands for commands that aren't going into the history. 55635f03feSJim Ingham interp.HandleCommand("thread backtrace --count 10 {0}".format(thread_id), result, True) 56635f03feSJim Ingham self.assertTrue(result.Succeeded(), "bt with count succeeded") 57635f03feSJim Ingham # There should be 11 lines: 58635f03feSJim Ingham lines = result.GetOutput().splitlines() 59635f03feSJim Ingham self.assertEqual(len(lines), 11, "Got the right number of lines") 60635f03feSJim Ingham # First frame is stop_here: 61635f03feSJim Ingham self.assertNotEqual(lines[1].find("stop_here"), -1, "Found Stop Here") 62635f03feSJim Ingham for line in lines[2:10]: 63635f03feSJim Ingham self.assertNotEqual(line.find(func_name), -1, "Name {0} not found in line: {1}".format(func_name, line)) 64635f03feSJim Ingham # The last entry should be 43: 65635f03feSJim Ingham self.assertNotEqual(lines[10].find("count=43"), -1, "First show ends at 43") 66635f03feSJim Ingham 67635f03feSJim Ingham # Now try a repeat, and make sure we get 10 more on this thread: 68635f03feSJim Ingham #import pdb; pdb.set_trace() 69635f03feSJim Ingham interp.HandleCommand("", result, True) 70635f03feSJim Ingham self.assertTrue(result.Succeeded(), "repeat command failed: {0}".format(result.GetError())) 71635f03feSJim Ingham lines = result.GetOutput().splitlines() 72635f03feSJim Ingham self.assertEqual(len(lines), 11, "Repeat got 11 lines") 73635f03feSJim Ingham # Every line should now be the recurse function: 74635f03feSJim Ingham for line in lines[1:10]: 75635f03feSJim Ingham self.assertNotEqual(line.find(func_name), -1, "Name in every line") 76635f03feSJim Ingham self.assertNotEqual(lines[10].find("count=33"), -1, "Last one is now 33") 77635f03feSJim Ingham 78635f03feSJim Ingham def check_two_threads(self, result_str, thread_id_1, name_1, thread_id_2, name_2, start_idx, end_idx): 79635f03feSJim Ingham # We should have 2 occurrences ot the thread header: 80635f03feSJim Ingham self.assertEqual(result_str.count("thread #{0}".format(thread_id_1)), 1, "One for thread 1") 81635f03feSJim Ingham self.assertEqual(result_str.count("thread #{0}".format(thread_id_2)), 1, "One for thread 2") 82635f03feSJim Ingham # We should have 10 occurrences of each name: 83635f03feSJim Ingham self.assertEqual(result_str.count(name_1), 10, "Found 10 of {0}".format(name_1)) 84635f03feSJim Ingham self.assertEqual(result_str.count(name_2), 10, "Found 10 of {0}".format(name_1)) 85635f03feSJim Ingham # There should be two instances of count=<start_idx> and none of count=<start-1>: 86635f03feSJim Ingham self.assertEqual(result_str.count("count={0}".format(start_idx)), 2, "Two instances of start_idx") 87635f03feSJim Ingham self.assertEqual(result_str.count("count={0}".format(start_idx-1)), 0, "No instances of start_idx - 1") 88635f03feSJim Ingham # There should be two instances of count=<end_idx> and none of count=<end_idx+1>: 89635f03feSJim Ingham self.assertEqual(result_str.count("count={0}".format(end_idx)), 2, "Two instances of end_idx") 90635f03feSJim Ingham self.assertEqual(result_str.count("count={0}".format(end_idx+1)), 0, "No instances after end idx") 91635f03feSJim Ingham 92635f03feSJim Ingham # The setup of this test was copied from the step-out test, and I can't tell from 93635f03feSJim Ingham # the comments whether it was getting two threads to the same breakpoint that was 94635f03feSJim Ingham # problematic, or the step-out part. This test stops at the rendevous point so I'm 95635f03feSJim Ingham # removing the skipIfLinux to see if we see any flakiness in just this part of the test. 96635f03feSJim Ingham @skipIfWindows # This test will hang on windows llvm.org/pr21753 97635f03feSJim Ingham @expectedFailureAll(oslist=["windows"]) 98635f03feSJim Ingham @expectedFailureNetBSD 99635f03feSJim Ingham def test_thread_backtrace_two_threads(self): 100635f03feSJim Ingham """Test that repeat works even when backtracing on more than one thread.""" 101635f03feSJim Ingham self.build() 102635f03feSJim Ingham (self.inferior_target, self.process, thread, bkpt) = lldbutil.run_to_source_breakpoint( 103635f03feSJim Ingham self, self.bkpt_string, lldb.SBFileSpec('main.cpp'), only_one_thread = False) 104635f03feSJim Ingham 105635f03feSJim Ingham # We hit the breakpoint on at least one thread. If we hit it on both threads 106635f03feSJim Ingham # simultaneously, we are ready to run our tests. Otherwise, suspend the thread 107635f03feSJim Ingham # that hit the breakpoint, and continue till the second thread hits 108635f03feSJim Ingham # the breakpoint: 109635f03feSJim Ingham 110635f03feSJim Ingham (breakpoint_threads, other_threads) = ([], []) 111635f03feSJim Ingham lldbutil.sort_stopped_threads(self.process, 112635f03feSJim Ingham breakpoint_threads=breakpoint_threads, 113635f03feSJim Ingham other_threads=other_threads) 114635f03feSJim Ingham if len(breakpoint_threads) == 1: 115635f03feSJim Ingham success = thread.Suspend() 116635f03feSJim Ingham self.assertTrue(success, "Couldn't suspend a thread") 117*f8d42c55SPavel Labath breakpoint_threads = lldbutil.continue_to_breakpoint(self.process, 118635f03feSJim Ingham bkpt) 119*f8d42c55SPavel Labath self.assertEqual(len(breakpoint_threads), 2, "Second thread stopped") 120635f03feSJim Ingham 121635f03feSJim Ingham # Figure out which thread is which: 122635f03feSJim Ingham thread_id_1 = breakpoint_threads[0].idx 123635f03feSJim Ingham self.assertGreater(len(breakpoint_threads[0].frames), 2, "I can go up") 124635f03feSJim Ingham name_1 = breakpoint_threads[0].frame[1].name.split("(")[0] 125635f03feSJim Ingham 126635f03feSJim Ingham thread_id_2 = breakpoint_threads[1].idx 127635f03feSJim Ingham self.assertGreater(len(breakpoint_threads[1].frames), 2, "I can go up") 128635f03feSJim Ingham name_2 = breakpoint_threads[1].frame[1].name.split("(")[0] 129635f03feSJim Ingham 130635f03feSJim Ingham # Check that backtrace and repeat works on one thread, then works on the second 131635f03feSJim Ingham # when we switch to it: 132635f03feSJim Ingham self.check_one_thread(thread_id_1, name_1) 133635f03feSJim Ingham self.check_one_thread(thread_id_2, name_2) 134635f03feSJim Ingham 135635f03feSJim Ingham # The output is looking right at this point, let's just do a couple more quick checks 136635f03feSJim Ingham # to see we handle two threads and a start count: 137635f03feSJim Ingham interp = self.dbg.GetCommandInterpreter() 138635f03feSJim Ingham result = lldb.SBCommandReturnObject() 139635f03feSJim Ingham 140635f03feSJim Ingham interp.HandleCommand("thread backtrace --count 10 --start 10 {0} {1}".format(thread_id_1, thread_id_2), result, True) 141635f03feSJim Ingham self.assertTrue(result.Succeeded(), "command succeeded for two threads") 142635f03feSJim Ingham 143635f03feSJim Ingham result.Clear() 144635f03feSJim Ingham interp.HandleCommand("", result, True) 145635f03feSJim Ingham self.assertTrue(result.Succeeded(), "repeat command succeeded for two threads") 146635f03feSJim Ingham result_str = result.GetOutput() 147635f03feSJim Ingham self.check_two_threads(result_str, thread_id_1, name_1, thread_id_2, name_2, 23, 32) 148635f03feSJim Ingham 149635f03feSJim Ingham # Finally make sure the repeat repeats: 150635f03feSJim Ingham result.Clear() 151635f03feSJim Ingham interp.HandleCommand("", result, True) 152635f03feSJim Ingham self.assertTrue(result.Succeeded(), "repeat command succeeded for two threads") 153635f03feSJim Ingham result_str = result.GetOutput() 154635f03feSJim Ingham self.check_two_threads(result_str, thread_id_1, name_1, thread_id_2, name_2, 13, 22) 155