1"""
2Test that breakpoints do not affect stepping.
3Check for correct StopReason when stepping to the line with breakpoint
4which should be eStopReasonBreakpoint in general,
5and eStopReasonPlanComplete when breakpoint's condition fails.
6"""
7
8
9import unittest2
10import lldb
11from lldbsuite.test.decorators import *
12from lldbsuite.test.lldbtest import *
13from lldbsuite.test import lldbutil
14
15class StepOverBreakpointsTestCase(TestBase):
16
17    mydir = TestBase.compute_mydir(__file__)
18
19    def setUp(self):
20        TestBase.setUp(self)
21
22        self.build()
23        exe = self.getBuildArtifact("a.out")
24        src = lldb.SBFileSpec("main.cpp")
25
26        # Create a target by the debugger.
27        self.target = self.dbg.CreateTarget(exe)
28        self.assertTrue(self.target, VALID_TARGET)
29
30        # Setup four breakpoints, two of them with false condition
31        self.line1 = line_number('main.cpp', "breakpoint_1")
32        self.line4 = line_number('main.cpp', "breakpoint_4")
33
34        self.breakpoint1 = self.target.BreakpointCreateByLocation(src, self.line1)
35        self.assertTrue(
36            self.breakpoint1 and self.breakpoint1.GetNumLocations() == 1,
37            VALID_BREAKPOINT)
38
39        self.breakpoint2 = self.target.BreakpointCreateBySourceRegex("breakpoint_2", src)
40        self.breakpoint2.GetLocationAtIndex(0).SetCondition('false')
41
42        self.breakpoint3 = self.target.BreakpointCreateBySourceRegex("breakpoint_3", src)
43        self.breakpoint3.GetLocationAtIndex(0).SetCondition('false')
44
45        self.breakpoint4 = self.target.BreakpointCreateByLocation(src, self.line4)
46
47        # Start debugging
48        self.process = self.target.LaunchSimple(
49            None, None, self.get_process_working_directory())
50        self.assertIsNotNone(self.process, PROCESS_IS_VALID)
51        self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint1)
52        self.assertIsNotNone(self.thread, "Didn't stop at breakpoint 1.")
53
54    @skipIfReproducer
55    def test_step_instruction(self):
56        # Count instructions between breakpoint_1 and breakpoint_4
57        contextList = self.target.FindFunctions('main', lldb.eFunctionNameTypeAuto)
58        self.assertEquals(contextList.GetSize(), 1)
59        symbolContext = contextList.GetContextAtIndex(0)
60        function = symbolContext.GetFunction()
61        self.assertTrue(function)
62        instructions = function.GetInstructions(self.target)
63        addr_1 = self.breakpoint1.GetLocationAtIndex(0).GetAddress()
64        addr_4 = self.breakpoint4.GetLocationAtIndex(0).GetAddress()
65
66        # if third argument is true then the count will be the number of
67        # instructions on which a breakpoint can be set.
68        # start = addr_1, end = addr_4, canSetBreakpoint = True
69        steps_expected = instructions.GetInstructionsCount(addr_1, addr_4, True)
70        step_count = 0
71        # Step from breakpoint_1 to breakpoint_4
72        while True:
73            self.thread.StepInstruction(True)
74            step_count = step_count + 1
75            self.assertEquals(self.process.GetState(), lldb.eStateStopped)
76            self.assertTrue(self.thread.GetStopReason() == lldb.eStopReasonPlanComplete or
77                            self.thread.GetStopReason() == lldb.eStopReasonBreakpoint)
78            if (self.thread.GetStopReason() == lldb.eStopReasonBreakpoint) :
79                # we should not stop on breakpoint_2 and _3 because they have false condition
80                self.assertEquals(self.thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.line4)
81                # breakpoint_2 and _3 should not affect step count
82                self.assertTrue(step_count >= steps_expected)
83                break
84
85        # Run the process until termination
86        self.process.Continue()
87        self.assertEquals(self.process.GetState(), lldb.eStateExited)
88
89    @skipIf(bugnumber="llvm.org/pr31972", hostoslist=["windows"])
90    def test_step_over(self):
91
92        self.thread.StepOver()
93        # We should be stopped at the breakpoint_2 line with stop plan complete reason
94        self.assertEquals(self.process.GetState(), lldb.eStateStopped)
95        self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete)
96
97        self.thread.StepOver()
98        # We should be stopped at the breakpoint_3 line with stop plan complete reason
99        self.assertEquals(self.process.GetState(), lldb.eStateStopped)
100        self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete)
101
102        self.thread.StepOver()
103        # We should be stopped at the breakpoint_4
104        self.assertEquals(self.process.GetState(), lldb.eStateStopped)
105        self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonBreakpoint)
106        thread1 = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint4)
107        self.assertEquals(self.thread, thread1, "Didn't stop at breakpoint 4.")
108
109        # Check that stepping does not affect breakpoint's hit count
110        self.assertEquals(self.breakpoint1.GetHitCount(), 1)
111        self.assertEquals(self.breakpoint2.GetHitCount(), 0)
112        self.assertEquals(self.breakpoint3.GetHitCount(), 0)
113        self.assertEquals(self.breakpoint4.GetHitCount(), 1)
114
115        # Run the process until termination
116        self.process.Continue()
117        self.assertEquals(self.process.GetState(), lldb.eStateExited)
118
119