Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / test / API / functionalities / thread_plan / TestThreadPlanCommands.py
blob7d03f4e884cbe2648ad72fd7414d4a4167eae305
1 """
2 Test that thread plan listing, and deleting works.
3 """
6 import lldb
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
15 @skipIfWindows
16 def test_thread_plan_actions(self):
17 self.build()
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:
39 self.assertFalse(
40 result.Succeeded(),
41 "command: '%s' succeeded when it should have failed: '%s'"
42 % (command, result.GetError()),
44 return
46 self.assertTrue(
47 result.Succeeded(),
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.
54 result_idx = 0
55 self.assertIn("thread #", result_arr[result_idx], "Found thread header")
56 result_idx += 1
57 self.assertIn(
58 "Active plan stack", result_arr[result_idx], "Found active header"
60 result_idx += 1
61 self.assertIn(
62 "Element 0: Base thread plan", result_arr[result_idx], "Found base plan"
64 result_idx += 1
66 for text in active_plans:
67 self.assertIn(
68 text, result_arr[result_idx], "Didn't find active plan: %s" % (text)
70 result_idx += 1
72 if len(completed_plans) > 0:
73 # First consume any remaining active plans:
74 while not "Completed plan stack:" in result_arr[result_idx]:
75 result_idx += 1
76 if result_idx == num_results:
77 self.fail(
78 "There should have been completed plans, but I never saw the completed stack header"
80 # We are at the Completed header, skip it:
81 result_idx += 1
82 for text in completed_plans:
83 self.assertIn(
84 text,
85 result_arr[result_idx],
86 "Didn't find completed plan: %s" % (text),
88 result_idx += 1
90 if len(discarded_plans) > 0:
91 # First consume any remaining completed plans:
92 while not "Discarded plan stack:" in result_arr[result_idx]:
93 result_idx += 1
94 if result_idx == num_results:
95 self.fail(
96 "There should have been discarded plans, but I never saw the discarded stack header"
99 # We are at the Discarded header, skip it:
100 result_idx += 1
101 for text in discarded_plans:
102 self.assertIn(
103 text,
104 result_arr[result_idx],
105 "Didn't find discarded plan: %s" % (text),
107 result_idx += 1
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
124 self.assertTrue(
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:
150 fake_tid = 0
151 for i in range(100, 10000, 100):
152 fake_tid = current_tid + i
153 thread = process.GetThreadByID(fake_tid)
154 if not thread:
155 break
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:
161 process.Continue()
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
173 self.assertTrue(
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
179 self.assertTrue(
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)
192 self.assertTrue(
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:"])
200 process.Continue()
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")