140 lines · python
1"""2Test that breakpoints (reason = breakpoint) have more priority than3plan completion (reason = step in/out/over) when reporting stop reason after step,4in particular 'step out' and 'step over', and in addition 'step in'.5Check for correct StopReason when stepping to the line with breakpoint,6which should be eStopReasonBreakpoint in general,7and eStopReasonPlanComplete when breakpoint's condition fails or it is disabled.8"""9 10 11import unittest12import lldb13from lldbsuite.test.decorators import *14from lldbsuite.test.lldbtest import *15from lldbsuite.test import lldbutil16 17 18class ThreadPlanUserBreakpointsTestCase(TestBase):19 def setUp(self):20 TestBase.setUp(self)21 22 # Build and run to starting breakpoint23 self.build()24 src = lldb.SBFileSpec("main.cpp")25 (self.target, self.process, self.thread, _) = lldbutil.run_to_source_breakpoint(26 self, "// Start from here", src27 )28 29 # Setup two more breakpoints30 self.breakpoints = [31 self.target.BreakpointCreateBySourceRegex("breakpoint_%i" % i, src)32 for i in range(2)33 ]34 self.assertTrue(35 all(bp and bp.GetNumLocations() == 1 for bp in self.breakpoints),36 VALID_BREAKPOINT,37 )38 39 def check_correct_stop_reason(self, breakpoint_idx, condition):40 self.assertState(self.process.GetState(), lldb.eStateStopped)41 if condition:42 # All breakpoints active, stop reason is breakpoint43 thread1 = lldbutil.get_one_thread_stopped_at_breakpoint(44 self.process, self.breakpoints[breakpoint_idx]45 )46 self.assertEqual(47 self.thread, thread1, "Didn't stop at breakpoint %i." % breakpoint_idx48 )49 else:50 # Breakpoints are inactive, stop reason is plan complete51 self.assertEqual(52 self.thread.GetStopReason(),53 lldb.eStopReasonPlanComplete,54 "Expected stop reason to be step into/over/out for inactive breakpoint %i line."55 % breakpoint_idx,56 )57 58 def change_breakpoints(self, action):59 for bp in self.breakpoints:60 action(bp)61 62 def check_thread_plan_user_breakpoint(self, condition, set_up_breakpoint_func):63 # Make breakpoints active/inactive in different ways64 self.change_breakpoints(lambda bp: set_up_breakpoint_func(condition, bp))65 66 self.thread.StepInto()67 # We should be stopped at the breakpoint_0 line with the correct stop reason68 self.check_correct_stop_reason(0, condition)69 70 # This step-over creates a step-out from `func_1` plan71 self.thread.StepOver()72 # We should be stopped at the breakpoint_1 line with the correct stop reason73 self.check_correct_stop_reason(1, condition)74 75 # Check explicit step-out76 # Make sure we install the breakpoint at the right address:77 # step-out might stop on different lines, if the compiler78 # did or did not emit more instructions after the return79 return_addr = self.thread.GetFrameAtIndex(1).GetPC()80 step_out_breakpoint = self.target.BreakpointCreateByAddress(return_addr)81 self.assertTrue(step_out_breakpoint, VALID_BREAKPOINT)82 set_up_breakpoint_func(condition, step_out_breakpoint)83 self.breakpoints.append(step_out_breakpoint)84 self.thread.StepOut()85 # We should be stopped somewhere in the main frame with the correct stop reason86 self.check_correct_stop_reason(2, condition)87 88 # Run the process until termination89 self.process.Continue()90 self.assertState(self.process.GetState(), lldb.eStateExited)91 92 def set_up_breakpoints_condition(self, condition, bp):93 # Set breakpoint condition to true/false94 conditionStr = "true" if condition else "false"95 bp.SetCondition(conditionStr)96 97 def set_up_breakpoints_enable(self, condition, bp):98 # Enable/disable breakpoint99 bp.SetEnabled(condition)100 101 def set_up_breakpoints_callback(self, condition, bp):102 # Set breakpoint callback to return True/False103 bp.SetScriptCallbackBody("return %s" % condition)104 105 def test_thread_plan_user_breakpoint_conditional_active(self):106 # Test with breakpoints having true condition107 self.check_thread_plan_user_breakpoint(108 condition=True, set_up_breakpoint_func=self.set_up_breakpoints_condition109 )110 111 def test_thread_plan_user_breakpoint_conditional_inactive(self):112 # Test with breakpoints having false condition113 self.check_thread_plan_user_breakpoint(114 condition=False, set_up_breakpoint_func=self.set_up_breakpoints_condition115 )116 117 def test_thread_plan_user_breakpoint_unconditional_active(self):118 # Test with breakpoints enabled unconditionally119 self.check_thread_plan_user_breakpoint(120 condition=True, set_up_breakpoint_func=self.set_up_breakpoints_enable121 )122 123 def test_thread_plan_user_breakpoint_unconditional_inactive(self):124 # Test with breakpoints disabled unconditionally125 self.check_thread_plan_user_breakpoint(126 condition=False, set_up_breakpoint_func=self.set_up_breakpoints_enable127 )128 129 def test_thread_plan_user_breakpoint_callback_active(self):130 # Test with breakpoints with callback that returns 'True'131 self.check_thread_plan_user_breakpoint(132 condition=True, set_up_breakpoint_func=self.set_up_breakpoints_callback133 )134 135 def test_thread_plan_user_breakpoint_callback_inactive(self):136 # Test with breakpoints with callback that returns 'False'137 self.check_thread_plan_user_breakpoint(138 condition=False, set_up_breakpoint_func=self.set_up_breakpoints_callback139 )140