diff --git a/lldb/test/API/functionalities/thread_plan/TestThreadPlanCommands.py b/lldb/test/API/functionalities/thread_plan/TestThreadPlanCommands.py index ddc88cce75f1d6..ff3b04d49e557a 100644 --- a/lldb/test/API/functionalities/thread_plan/TestThreadPlanCommands.py +++ b/lldb/test/API/functionalities/thread_plan/TestThreadPlanCommands.py @@ -46,24 +46,7 @@ def check_list_output(self, command, active_plans = [], completed_plans = [], di self.assertTrue(result.Succeeded(), "command: '%s' failed: '%s'"%(command, result.GetError())) result_arr = result.GetOutput().splitlines() num_results = len(result_arr) - - # Match the expected number of elements. - # Adjust the count for the number of header lines we aren't matching: - fudge = 0 - if num_completed == 0 and num_discarded == 0: - # The fudge is 3: Thread header, Active Plan header and base plan - fudge = 3 - elif num_completed == 0 or num_discarded == 0: - # The fudge is 4: The above plus either the Completed or Discarded Plan header: - fudge = 4 - else: - # The fudge is 5 since we have both headers: - fudge = 5 - - self.assertEqual(num_results, num_active + num_completed + num_discarded + fudge, - "Too many elements in match arrays for: \n%s\n"%result.GetOutput()) - # Now iterate through the results array and pick out the results. result_idx = 0 self.assertIn("thread #", result_arr[result_idx], "Found thread header") ; result_idx += 1 @@ -71,29 +54,47 @@ def check_list_output(self, command, active_plans = [], completed_plans = [], di self.assertIn("Element 0: Base thread plan", result_arr[result_idx], "Found base plan") ; result_idx += 1 for text in active_plans: - self.assertFalse("Completed plan stack" in result_arr[result_idx], "Found Completed header too early.") self.assertIn(text, result_arr[result_idx], "Didn't find active plan: %s"%(text)) ; result_idx += 1 + if len(completed_plans) > 0: - self.assertIn("Completed plan stack:", result_arr[result_idx], "Found completed plan stack header") ; result_idx += 1 + # First consume any remaining active plans: + while not "Completed plan stack:" in result_arr[result_idx]: + result_idx += 1 + if result_idx == num_results: + self.fail("There should have been completed plans, but I never saw the completed stack header") + # We are at the Completed header, skip it: + result_idx += 1 for text in completed_plans: self.assertIn(text, result_arr[result_idx], "Didn't find completed plan: %s"%(text)) ; result_idx += 1 if len(discarded_plans) > 0: - self.assertIn("Discarded plan stack:", result_arr[result_idx], "Found discarded plan stack header") ; result_idx += 1 + # First consume any remaining completed plans: + while not "Discarded plan stack:" in result_arr[result_idx]: + result_idx += 1 + if result_idx == num_results: + self.fail("There should have been discarded plans, but I never saw the discarded stack header") + + # We are at the Discarded header, skip it: + result_idx += 1 for text in discarded_plans: - self.assertIn(text, result_arr[result_idx], "Didn't find completed plan: %s"%(text)) ; result_idx += 1 + self.assertIn(text, result_arr[result_idx], "Didn't find discarded plan: %s"%(text)) ; result_idx += 1 def thread_plan_test(self): (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) - # Now set a breakpoint in call_me and step over. We should have - # two public thread plans + # We need to have an internal plan so we can test listing one. + # The most consistent way to do that is to use a scripted thread plan + # that uses a sub-plan. Source that in now. + source_path = os.path.join(self.getSourceDir(), "wrap_step_over.py") + self.runCmd("command script import '%s'"%(source_path)) + + # Now set a breakpoint that we will hit by running our scripted step. call_me_bkpt = target.BreakpointCreateBySourceRegex("Set another here", self.main_source_file) self.assertTrue(call_me_bkpt.GetNumLocations() > 0, "Set the breakpoint successfully") - thread.StepOver() + thread.StepUsingScriptedThreadPlan("wrap_step_over.WrapStepOver") threads = lldbutil.get_threads_stopped_at_breakpoint(process, call_me_bkpt) self.assertEqual(len(threads), 1, "Hit my breakpoint while stepping over") @@ -101,19 +102,19 @@ def thread_plan_test(self): current_tid = threads[0].GetThreadID() # Run thread plan list without the -i flag: command = "thread plan list %d"%(current_id) - self.check_list_output (command, ["Stepping over line main.c"], []) + self.check_list_output (command, ["wrap_step_over.WrapStepOver"], []) # Run thread plan list with the -i flag: command = "thread plan list -i %d"%(current_id) - self.check_list_output(command, ["Stepping over line main.c", "Stepping out from"]) + self.check_list_output(command, ["WrapStepOver", "Stepping over line main.c"]) # Run thread plan list providing TID, output should be the same: command = "thread plan list -t %d"%(current_tid) - self.check_list_output(command, ["Stepping over line main.c"]) + self.check_list_output(command, ["wrap_step_over.WrapStepOver"]) # Provide both index & tid, and make sure we only print once: command = "thread plan list -t %d %d"%(current_tid, current_id) - self.check_list_output(command, ["Stepping over line main.c"]) + self.check_list_output(command, ["wrap_step_over.WrapStepOver"]) # Try a fake TID, and make sure that fails: fake_tid = 0 @@ -133,7 +134,7 @@ def thread_plan_test(self): # Run thread plan list - there aren't any private plans at this point: command = "thread plan list %d"%(current_id) - self.check_list_output(command, [], ["Stepping over line main.c"]) + self.check_list_output(command, [], ["wrap_step_over.WrapStepOver"]) # Set another breakpoint that we can run to, to try deleting thread plans. second_step_bkpt = target.BreakpointCreateBySourceRegex("Run here to step over again", diff --git a/lldb/test/API/functionalities/thread_plan/wrap_step_over.py b/lldb/test/API/functionalities/thread_plan/wrap_step_over.py new file mode 100644 index 00000000000000..a7b39764ceca0b --- /dev/null +++ b/lldb/test/API/functionalities/thread_plan/wrap_step_over.py @@ -0,0 +1,22 @@ +import lldb + +class WrapStepOver(): + def __init__(self, thread_plan, args_data, dict): + self.plan = thread_plan + frame_0 = thread_plan.GetThread().frames[0] + line_entry = frame_0.line_entry + start_addr = line_entry.addr + end_addr = line_entry.end_addr + range_size = int(end_addr) - int(start_addr) + error = lldb.SBError() + self.sub_plan = thread_plan.QueueThreadPlanForStepOverRange(start_addr, range_size) + + def should_step(self): + return False + + def should_stop(self, event): + if self.sub_plan.IsPlanComplete(): + self.plan.SetPlanComplete(True) + return True + else: + return False