Skip to content

Commit

Permalink
Convert the ThreadPlanCommands test to use a scripted plan
Browse files Browse the repository at this point in the history
that pushes a step over plan.  Relax the listing checker
so it will look past any entries after the ones listed in
the input patterns.  Then for the internal plans just check
for the StepOver plan that our scripted plan pushes, and look past
any others.

This should make the test more robust on systems that don't use the
step-in then push a step-out plan to step over a function.
  • Loading branch information
jimingham committed Apr 11, 2020
1 parent f7de4b5 commit aa4b37b
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 29 deletions.
59 changes: 30 additions & 29 deletions lldb/test/API/functionalities/thread_plan/TestThreadPlanCommands.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,74 +46,75 @@ 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
self.assertIn("Active plan stack", result_arr[result_idx], "Found active header") ; result_idx += 1
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")

current_id = threads[0].GetIndexID()
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
Expand All @@ -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",
Expand Down
22 changes: 22 additions & 0 deletions lldb/test/API/functionalities/thread_plan/wrap_step_over.py
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit aa4b37b

Please sign in to comment.