11893065dSJim Ingham""" 21893065dSJim InghamTest that thread plan listing, and deleting works. 31893065dSJim Ingham""" 41893065dSJim Ingham 51893065dSJim Ingham 61893065dSJim Ingham 71893065dSJim Inghamimport lldb 82d658c56SJim Inghamfrom lldbsuite.test.decorators import * 91893065dSJim Inghamimport lldbsuite.test.lldbutil as lldbutil 101893065dSJim Inghamfrom lldbsuite.test.lldbtest import * 111893065dSJim Ingham 121893065dSJim Ingham 131893065dSJim Inghamclass TestThreadPlanCommands(TestBase): 141893065dSJim Ingham 151893065dSJim Ingham mydir = TestBase.compute_mydir(__file__) 161893065dSJim Ingham 171893065dSJim Ingham NO_DEBUG_INFO_TESTCASE = True 181893065dSJim Ingham 192d658c56SJim Ingham @skipIfWindows 20*4f644ff9SPavel Labath @expectedFailureAll(oslist=["linux"], archs=["aarch64"]) 211893065dSJim Ingham def test_thread_plan_actions(self): 221893065dSJim Ingham self.build() 231893065dSJim Ingham self.main_source_file = lldb.SBFileSpec("main.c") 241893065dSJim Ingham self.thread_plan_test() 251893065dSJim Ingham 261893065dSJim Ingham def check_list_output(self, command, active_plans = [], completed_plans = [], discarded_plans = []): 271893065dSJim Ingham # Check the "thread plan list" output against a list of active & completed and discarded plans. 281893065dSJim Ingham # If all three check arrays are empty, that means the command is expected to fail. 291893065dSJim Ingham 301893065dSJim Ingham interp = self.dbg.GetCommandInterpreter() 311893065dSJim Ingham result = lldb.SBCommandReturnObject() 321893065dSJim Ingham 331893065dSJim Ingham num_active = len(active_plans) 341893065dSJim Ingham num_completed = len(completed_plans) 351893065dSJim Ingham num_discarded = len(discarded_plans) 361893065dSJim Ingham 371893065dSJim Ingham interp.HandleCommand(command, result) 381893065dSJim Ingham print("Command: %s"%(command)) 391893065dSJim Ingham print(result.GetOutput()) 401893065dSJim Ingham 411893065dSJim Ingham if num_active == 0 and num_completed == 0 and num_discarded == 0: 421893065dSJim Ingham self.assertFalse(result.Succeeded(), "command: '%s' succeeded when it should have failed: '%s'"% 431893065dSJim Ingham (command, result.GetError())) 441893065dSJim Ingham return 451893065dSJim Ingham 461893065dSJim Ingham self.assertTrue(result.Succeeded(), "command: '%s' failed: '%s'"%(command, result.GetError())) 471893065dSJim Ingham result_arr = result.GetOutput().splitlines() 481893065dSJim Ingham num_results = len(result_arr) 491893065dSJim Ingham 501893065dSJim Ingham # Match the expected number of elements. 511893065dSJim Ingham # Adjust the count for the number of header lines we aren't matching: 521893065dSJim Ingham fudge = 0 531893065dSJim Ingham 541893065dSJim Ingham if num_completed == 0 and num_discarded == 0: 551893065dSJim Ingham # The fudge is 3: Thread header, Active Plan header and base plan 561893065dSJim Ingham fudge = 3 571893065dSJim Ingham elif num_completed == 0 or num_discarded == 0: 581893065dSJim Ingham # The fudge is 4: The above plus either the Completed or Discarded Plan header: 591893065dSJim Ingham fudge = 4 601893065dSJim Ingham else: 611893065dSJim Ingham # The fudge is 5 since we have both headers: 621893065dSJim Ingham fudge = 5 631893065dSJim Ingham 641893065dSJim Ingham self.assertEqual(num_results, num_active + num_completed + num_discarded + fudge, 6548ba745eSJim Ingham "Too many elements in match arrays for: \n%s\n"%result.GetOutput()) 661893065dSJim Ingham 671893065dSJim Ingham # Now iterate through the results array and pick out the results. 681893065dSJim Ingham result_idx = 0 691893065dSJim Ingham self.assertIn("thread #", result_arr[result_idx], "Found thread header") ; result_idx += 1 701893065dSJim Ingham self.assertIn("Active plan stack", result_arr[result_idx], "Found active header") ; result_idx += 1 711893065dSJim Ingham self.assertIn("Element 0: Base thread plan", result_arr[result_idx], "Found base plan") ; result_idx += 1 721893065dSJim Ingham 731893065dSJim Ingham for text in active_plans: 741893065dSJim Ingham self.assertFalse("Completed plan stack" in result_arr[result_idx], "Found Completed header too early.") 751893065dSJim Ingham self.assertIn(text, result_arr[result_idx], "Didn't find active plan: %s"%(text)) ; result_idx += 1 761893065dSJim Ingham 771893065dSJim Ingham if len(completed_plans) > 0: 781893065dSJim Ingham self.assertIn("Completed plan stack:", result_arr[result_idx], "Found completed plan stack header") ; result_idx += 1 791893065dSJim Ingham for text in completed_plans: 801893065dSJim Ingham self.assertIn(text, result_arr[result_idx], "Didn't find completed plan: %s"%(text)) ; result_idx += 1 811893065dSJim Ingham 821893065dSJim Ingham if len(discarded_plans) > 0: 831893065dSJim Ingham self.assertIn("Discarded plan stack:", result_arr[result_idx], "Found discarded plan stack header") ; result_idx += 1 841893065dSJim Ingham for text in discarded_plans: 851893065dSJim Ingham self.assertIn(text, result_arr[result_idx], "Didn't find completed plan: %s"%(text)) ; result_idx += 1 861893065dSJim Ingham 871893065dSJim Ingham 881893065dSJim Ingham def thread_plan_test(self): 891893065dSJim Ingham (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, 901893065dSJim Ingham "Set a breakpoint here", self.main_source_file) 911893065dSJim Ingham 921893065dSJim Ingham # Now set a breakpoint in call_me and step over. We should have 931893065dSJim Ingham # two public thread plans 941893065dSJim Ingham call_me_bkpt = target.BreakpointCreateBySourceRegex("Set another here", self.main_source_file) 951893065dSJim Ingham self.assertTrue(call_me_bkpt.GetNumLocations() > 0, "Set the breakpoint successfully") 961893065dSJim Ingham thread.StepOver() 971893065dSJim Ingham threads = lldbutil.get_threads_stopped_at_breakpoint(process, call_me_bkpt) 981893065dSJim Ingham self.assertEqual(len(threads), 1, "Hit my breakpoint while stepping over") 991893065dSJim Ingham 1001893065dSJim Ingham current_id = threads[0].GetIndexID() 1011893065dSJim Ingham current_tid = threads[0].GetThreadID() 1021893065dSJim Ingham # Run thread plan list without the -i flag: 1031893065dSJim Ingham command = "thread plan list %d"%(current_id) 1041893065dSJim Ingham self.check_list_output (command, ["Stepping over line main.c"], []) 1051893065dSJim Ingham 1061893065dSJim Ingham # Run thread plan list with the -i flag: 1071893065dSJim Ingham command = "thread plan list -i %d"%(current_id) 1081893065dSJim Ingham self.check_list_output(command, ["Stepping over line main.c", "Stepping out from"]) 1091893065dSJim Ingham 1101893065dSJim Ingham # Run thread plan list providing TID, output should be the same: 1111893065dSJim Ingham command = "thread plan list -t %d"%(current_tid) 1121893065dSJim Ingham self.check_list_output(command, ["Stepping over line main.c"]) 1131893065dSJim Ingham 1141893065dSJim Ingham # Provide both index & tid, and make sure we only print once: 1151893065dSJim Ingham command = "thread plan list -t %d %d"%(current_tid, current_id) 1161893065dSJim Ingham self.check_list_output(command, ["Stepping over line main.c"]) 1171893065dSJim Ingham 1181893065dSJim Ingham # Try a fake TID, and make sure that fails: 1191893065dSJim Ingham fake_tid = 0 1201893065dSJim Ingham for i in range(100, 10000, 100): 1211893065dSJim Ingham fake_tid = current_tid + i 1221893065dSJim Ingham thread = process.GetThreadByID(fake_tid) 1231893065dSJim Ingham if not thread: 1241893065dSJim Ingham break 1251893065dSJim Ingham 1261893065dSJim Ingham command = "thread plan list -t %d"%(fake_tid) 1271893065dSJim Ingham self.check_list_output(command) 1281893065dSJim Ingham 1291893065dSJim Ingham # Now continue, and make sure we printed the completed plan: 1301893065dSJim Ingham process.Continue() 1311893065dSJim Ingham threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonPlanComplete) 1321893065dSJim Ingham self.assertEqual(len(threads), 1, "One thread completed a step") 1331893065dSJim Ingham 1341893065dSJim Ingham # Run thread plan list - there aren't any private plans at this point: 1351893065dSJim Ingham command = "thread plan list %d"%(current_id) 1361893065dSJim Ingham self.check_list_output(command, [], ["Stepping over line main.c"]) 1371893065dSJim Ingham 1381893065dSJim Ingham # Set another breakpoint that we can run to, to try deleting thread plans. 1391893065dSJim Ingham second_step_bkpt = target.BreakpointCreateBySourceRegex("Run here to step over again", 1401893065dSJim Ingham self.main_source_file) 1411893065dSJim Ingham self.assertTrue(second_step_bkpt.GetNumLocations() > 0, "Set the breakpoint successfully") 1421893065dSJim Ingham final_bkpt = target.BreakpointCreateBySourceRegex("Make sure we get here on last continue", 1431893065dSJim Ingham self.main_source_file) 1441893065dSJim Ingham self.assertTrue(final_bkpt.GetNumLocations() > 0, "Set the breakpoint successfully") 1451893065dSJim Ingham 1461893065dSJim Ingham threads = lldbutil.continue_to_breakpoint(process, second_step_bkpt) 1471893065dSJim Ingham self.assertEqual(len(threads), 1, "Hit the second step breakpoint") 1481893065dSJim Ingham 1491893065dSJim Ingham threads[0].StepOver() 1501893065dSJim Ingham threads = lldbutil.get_threads_stopped_at_breakpoint(process, call_me_bkpt) 1511893065dSJim Ingham 1521893065dSJim Ingham result = lldb.SBCommandReturnObject() 1531893065dSJim Ingham interp = self.dbg.GetCommandInterpreter() 1541893065dSJim Ingham interp.HandleCommand("thread plan discard 1", result) 1551893065dSJim Ingham self.assertTrue(result.Succeeded(), "Deleted the step over plan: %s"%(result.GetOutput())) 1561893065dSJim Ingham 1571893065dSJim Ingham # Make sure the plan gets listed in the discarded plans: 1581893065dSJim Ingham command = "thread plan list %d"%(current_id) 1591893065dSJim Ingham self.check_list_output(command, [], [], ["Stepping over line main.c:"]) 1601893065dSJim Ingham 1611893065dSJim Ingham process.Continue() 1621893065dSJim Ingham threads = lldbutil.get_threads_stopped_at_breakpoint(process, final_bkpt) 1631893065dSJim Ingham self.assertEqual(len(threads), 1, "Ran to final breakpoint") 1641893065dSJim Ingham threads = lldbutil.get_stopped_threads(process, lldb.eStopReasonPlanComplete) 1651893065dSJim Ingham self.assertEqual(len(threads), 0, "Did NOT complete the step over plan") 1661893065dSJim Ingham 167