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    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
91        self.thread.StepOver()
92        # We should be stopped at the breakpoint_2 line with stop plan complete reason
93        self.assertEquals(self.process.GetState(), lldb.eStateStopped)
94        self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete)
95
96        self.thread.StepOver()
97        # We should be stopped at the breakpoint_3 line with stop plan complete reason
98        self.assertEquals(self.process.GetState(), lldb.eStateStopped)
99        self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete)
100
101        self.thread.StepOver()
102        # We should be stopped at the breakpoint_4
103        self.assertEquals(self.process.GetState(), lldb.eStateStopped)
104        self.assertEquals(self.thread.GetStopReason(), lldb.eStopReasonBreakpoint)
105        thread1 = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint4)
106        self.assertEquals(self.thread, thread1, "Didn't stop at breakpoint 4.")
107
108        # Check that stepping does not affect breakpoint's hit count
109        self.assertEquals(self.breakpoint1.GetHitCount(), 1)
110        self.assertEquals(self.breakpoint2.GetHitCount(), 0)
111        self.assertEquals(self.breakpoint3.GetHitCount(), 0)
112        self.assertEquals(self.breakpoint4.GetHitCount(), 1)
113
114        # Run the process until termination
115        self.process.Continue()
116        self.assertEquals(self.process.GetState(), lldb.eStateExited)
117
118