1"""
2Test that breakpoints do not affect stepping.
3Check for correct StopReason when stepping to the line with breakpoint
4which chould 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    def test_step_instruction(self):
55        # Count instructions between breakpoint_1 and breakpoint_4
56        contextList = self.target.FindFunctions('main', lldb.eFunctionNameTypeAuto)
57        self.assertEquals(contextList.GetSize(), 1)
58        symbolContext = contextList.GetContextAtIndex(0)
59        function = symbolContext.GetFunction()
60        self.assertTrue(function)
61        instructions = function.GetInstructions(self.target)
62        addr_1 = self.breakpoint1.GetLocationAtIndex(0).GetAddress()
63        addr_4 = self.breakpoint4.GetLocationAtIndex(0).GetAddress()
64
65        # if third argument is true then the count will be the number of
66        # instructions on which a breakpoint can be set.
67        # start = addr_1, end = addr_4, canSetBreakpoint = True
68        steps_expected = instructions.GetInstructionsCount(addr_1, addr_4, True)
69        step_count = 0
70        # Step from breakpoint_1 to breakpoint_4
71        while True:
72            self.thread.StepInstruction(True)
73            step_count = step_count + 1
74            self.assertEquals(self.process.GetState(), lldb.eStateStopped)
75            self.assertTrue(self.thread.GetStopReason() == lldb.eStopReasonPlanComplete or
76                            self.thread.GetStopReason() == lldb.eStopReasonBreakpoint)
77            if (self.thread.GetStopReason() == lldb.eStopReasonBreakpoint) :
78                # we should not stop on breakpoint_2 and _3 because they have false condition
79                self.assertEquals(self.thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.line4)
80                # breakpoint_2 and _3 should not affect step count
81                self.assertTrue(step_count >= steps_expected)
82                break
83
84        # Run the process until termination
85        self.process.Continue()
86        self.assertEquals(self.process.GetState(), lldb.eStateExited)
87
88    @skipIf(bugnumber="llvm.org/pr31972", hostoslist=["windows"])
89    def test_step_over(self):
90        #lldb.DBG.EnableLog("lldb", ["step","breakpoint"])
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