"""
Test that breakpoints (reason = breakpoint) have more priority than
plan completion (reason = step in/out/over) when reporting stop reason after step,
in particular 'step out' and 'step over', and in addition 'step in'.
Check for correct StopReason when stepping to the line with breakpoint,
which should be eStopReasonBreakpoint in general,
and eStopReasonPlanComplete when breakpoint's condition fails or it is disabled.
"""
import unittest
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class ThreadPlanUserBreakpointsTestCase(TestBase):
def setUp(self):
TestBase.setUp(self)
self.build()
src = lldb.SBFileSpec("main.cpp")
(self.target, self.process, self.thread, _) = lldbutil.run_to_source_breakpoint(
self, "// Start from here", src
)
self.breakpoints = [
self.target.BreakpointCreateBySourceRegex("breakpoint_%i" % i, src)
for i in range(2)
]
self.assertTrue(
all(bp and bp.GetNumLocations() == 1 for bp in self.breakpoints),
VALID_BREAKPOINT,
)
def check_correct_stop_reason(self, breakpoint_idx, condition):
self.assertState(self.process.GetState(), lldb.eStateStopped)
if condition:
thread1 = lldbutil.get_one_thread_stopped_at_breakpoint(
self.process, self.breakpoints[breakpoint_idx]
)
self.assertEqual(
self.thread, thread1, "Didn't stop at breakpoint %i." % breakpoint_idx
)
else:
self.assertEqual(
self.thread.GetStopReason(),
lldb.eStopReasonPlanComplete,
"Expected stop reason to be step into/over/out for inactive breakpoint %i line."
% breakpoint_idx,
)
def change_breakpoints(self, action):
for bp in self.breakpoints:
action(bp)
def check_thread_plan_user_breakpoint(self, condition, set_up_breakpoint_func):
self.change_breakpoints(lambda bp: set_up_breakpoint_func(condition, bp))
self.thread.StepInto()
self.check_correct_stop_reason(0, condition)
self.thread.StepOver()
self.check_correct_stop_reason(1, condition)
return_addr = self.thread.GetFrameAtIndex(1).GetPC()
step_out_breakpoint = self.target.BreakpointCreateByAddress(return_addr)
self.assertTrue(step_out_breakpoint, VALID_BREAKPOINT)
set_up_breakpoint_func(condition, step_out_breakpoint)
self.breakpoints.append(step_out_breakpoint)
self.thread.StepOut()
self.check_correct_stop_reason(2, condition)
self.process.Continue()
self.assertState(self.process.GetState(), lldb.eStateExited)
def set_up_breakpoints_condition(self, condition, bp):
conditionStr = "true" if condition else "false"
bp.SetCondition(conditionStr)
def set_up_breakpoints_enable(self, condition, bp):
bp.SetEnabled(condition)
def set_up_breakpoints_callback(self, condition, bp):
bp.SetScriptCallbackBody("return %s" % condition)
def test_thread_plan_user_breakpoint_conditional_active(self):
self.check_thread_plan_user_breakpoint(
condition=True, set_up_breakpoint_func=self.set_up_breakpoints_condition
)
def test_thread_plan_user_breakpoint_conditional_inactive(self):
self.check_thread_plan_user_breakpoint(
condition=False, set_up_breakpoint_func=self.set_up_breakpoints_condition
)
def test_thread_plan_user_breakpoint_unconditional_active(self):
self.check_thread_plan_user_breakpoint(
condition=True, set_up_breakpoint_func=self.set_up_breakpoints_enable
)
def test_thread_plan_user_breakpoint_unconditional_inactive(self):
self.check_thread_plan_user_breakpoint(
condition=False, set_up_breakpoint_func=self.set_up_breakpoints_enable
)
def test_thread_plan_user_breakpoint_callback_active(self):
self.check_thread_plan_user_breakpoint(
condition=True, set_up_breakpoint_func=self.set_up_breakpoints_callback
)
def test_thread_plan_user_breakpoint_callback_inactive(self):
self.check_thread_plan_user_breakpoint(
condition=False, set_up_breakpoint_func=self.set_up_breakpoints_callback
)