2 Test that thread plan listing, and deleting works.
7 from lldbsuite
.test
.decorators
import *
8 import lldbsuite
.test
.lldbutil
as lldbutil
9 from lldbsuite
.test
.lldbtest
import *
12 class TestThreadPlanCommands(TestBase
):
13 NO_DEBUG_INFO_TESTCASE
= True
16 def test_thread_plan_actions(self
):
18 self
.main_source_file
= lldb
.SBFileSpec("main.c")
19 self
.thread_plan_test()
21 def check_list_output(
22 self
, command
, active_plans
=[], completed_plans
=[], discarded_plans
=[]
24 # Check the "thread plan list" output against a list of active & completed and discarded plans.
25 # If all three check arrays are empty, that means the command is expected to fail.
27 interp
= self
.dbg
.GetCommandInterpreter()
28 result
= lldb
.SBCommandReturnObject()
30 num_active
= len(active_plans
)
31 num_completed
= len(completed_plans
)
32 num_discarded
= len(discarded_plans
)
34 interp
.HandleCommand(command
, result
)
35 print("Command: %s" % (command
))
36 print(result
.GetOutput())
38 if num_active
== 0 and num_completed
== 0 and num_discarded
== 0:
41 "command: '%s' succeeded when it should have failed: '%s'"
42 % (command
, result
.GetError()),
48 "command: '%s' failed: '%s'" % (command
, result
.GetError()),
50 result_arr
= result
.GetOutput().splitlines()
51 num_results
= len(result_arr
)
53 # Now iterate through the results array and pick out the results.
55 self
.assertIn("thread #", result_arr
[result_idx
], "Found thread header")
58 "Active plan stack", result_arr
[result_idx
], "Found active header"
62 "Element 0: Base thread plan", result_arr
[result_idx
], "Found base plan"
66 for text
in active_plans
:
68 text
, result_arr
[result_idx
], "Didn't find active plan: %s" % (text
)
72 if len(completed_plans
) > 0:
73 # First consume any remaining active plans:
74 while not "Completed plan stack:" in result_arr
[result_idx
]:
76 if result_idx
== num_results
:
78 "There should have been completed plans, but I never saw the completed stack header"
80 # We are at the Completed header, skip it:
82 for text
in completed_plans
:
85 result_arr
[result_idx
],
86 "Didn't find completed plan: %s" % (text
),
90 if len(discarded_plans
) > 0:
91 # First consume any remaining completed plans:
92 while not "Discarded plan stack:" in result_arr
[result_idx
]:
94 if result_idx
== num_results
:
96 "There should have been discarded plans, but I never saw the discarded stack header"
99 # We are at the Discarded header, skip it:
101 for text
in discarded_plans
:
104 result_arr
[result_idx
],
105 "Didn't find discarded plan: %s" % (text
),
109 def thread_plan_test(self
):
110 (target
, process
, thread
, bkpt
) = lldbutil
.run_to_source_breakpoint(
111 self
, "Set a breakpoint here", self
.main_source_file
114 # We need to have an internal plan so we can test listing one.
115 # The most consistent way to do that is to use a scripted thread plan
116 # that uses a sub-plan. Source that in now.
117 source_path
= os
.path
.join(self
.getSourceDir(), "wrap_step_over.py")
118 self
.runCmd("command script import '%s'" % (source_path
))
120 # Now set a breakpoint that we will hit by running our scripted step.
121 call_me_bkpt
= target
.BreakpointCreateBySourceRegex(
122 "Set another here", self
.main_source_file
125 call_me_bkpt
.GetNumLocations() > 0, "Set the breakpoint successfully"
127 thread
.StepUsingScriptedThreadPlan("wrap_step_over.WrapStepOver")
128 threads
= lldbutil
.get_threads_stopped_at_breakpoint(process
, call_me_bkpt
)
129 self
.assertEqual(len(threads
), 1, "Hit my breakpoint while stepping over")
131 current_id
= threads
[0].GetIndexID()
132 current_tid
= threads
[0].GetThreadID()
133 # Run thread plan list without the -i flag:
134 command
= "thread plan list %d" % (current_id
)
135 self
.check_list_output(command
, ["wrap_step_over.WrapStepOver"], [])
137 # Run thread plan list with the -i flag:
138 command
= "thread plan list -i %d" % (current_id
)
139 self
.check_list_output(command
, ["WrapStepOver", "Stepping over line main.c"])
141 # Run thread plan list providing TID, output should be the same:
142 command
= "thread plan list -t %d" % (current_tid
)
143 self
.check_list_output(command
, ["wrap_step_over.WrapStepOver"])
145 # Provide both index & tid, and make sure we only print once:
146 command
= "thread plan list -t %d %d" % (current_tid
, current_id
)
147 self
.check_list_output(command
, ["wrap_step_over.WrapStepOver"])
149 # Try a fake TID, and make sure that fails:
151 for i
in range(100, 10000, 100):
152 fake_tid
= current_tid
+ i
153 thread
= process
.GetThreadByID(fake_tid
)
157 command
= "thread plan list -t %d" % (fake_tid
)
158 self
.check_list_output(command
)
160 # Now continue, and make sure we printed the completed plan:
162 threads
= lldbutil
.get_stopped_threads(process
, lldb
.eStopReasonPlanComplete
)
163 self
.assertEqual(len(threads
), 1, "One thread completed a step")
165 # Run thread plan list - there aren't any private plans at this point:
166 command
= "thread plan list %d" % (current_id
)
167 self
.check_list_output(command
, [], ["wrap_step_over.WrapStepOver"])
169 # Set another breakpoint that we can run to, to try deleting thread plans.
170 second_step_bkpt
= target
.BreakpointCreateBySourceRegex(
171 "Run here to step over again", self
.main_source_file
174 second_step_bkpt
.GetNumLocations() > 0, "Set the breakpoint successfully"
176 final_bkpt
= target
.BreakpointCreateBySourceRegex(
177 "Make sure we get here on last continue", self
.main_source_file
180 final_bkpt
.GetNumLocations() > 0, "Set the breakpoint successfully"
183 threads
= lldbutil
.continue_to_breakpoint(process
, second_step_bkpt
)
184 self
.assertEqual(len(threads
), 1, "Hit the second step breakpoint")
186 threads
[0].StepOver()
187 threads
= lldbutil
.get_threads_stopped_at_breakpoint(process
, call_me_bkpt
)
189 result
= lldb
.SBCommandReturnObject()
190 interp
= self
.dbg
.GetCommandInterpreter()
191 interp
.HandleCommand("thread plan discard 1", result
)
193 result
.Succeeded(), "Deleted the step over plan: %s" % (result
.GetOutput())
196 # Make sure the plan gets listed in the discarded plans:
197 command
= "thread plan list %d" % (current_id
)
198 self
.check_list_output(command
, [], [], ["Stepping over line main.c:"])
201 threads
= lldbutil
.get_threads_stopped_at_breakpoint(process
, final_bkpt
)
202 self
.assertEqual(len(threads
), 1, "Ran to final breakpoint")
203 threads
= lldbutil
.get_stopped_threads(process
, lldb
.eStopReasonPlanComplete
)
204 self
.assertEqual(len(threads
), 0, "Did NOT complete the step over plan")