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