1"""
2Test that we handle breakpoints on consecutive instructions correctly.
3"""
4
5
6
7import unittest2
8import lldb
9from lldbsuite.test.decorators import *
10from lldbsuite.test.lldbtest import *
11from lldbsuite.test import lldbutil
12
13
14class ConsecutiveBreakpointsTestCase(TestBase):
15
16    mydir = TestBase.compute_mydir(__file__)
17
18    def prepare_test(self):
19        self.build()
20
21        (self.target, self.process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(
22                self, "Set breakpoint here", lldb.SBFileSpec("main.cpp"))
23
24        # Set breakpoint to the next instruction
25        frame = self.thread.GetFrameAtIndex(0)
26
27        address = frame.GetPCAddress()
28        instructions = self.target.ReadInstructions(address, 2)
29        self.assertEquals(len(instructions), 2)
30        self.bkpt_address = instructions[1].GetAddress()
31        self.breakpoint2 = self.target.BreakpointCreateByAddress(
32            self.bkpt_address.GetLoadAddress(self.target))
33        self.assertTrue(
34            self.breakpoint2 and self.breakpoint2.GetNumLocations() == 1,
35            VALID_BREAKPOINT)
36
37    def finish_test(self):
38        # Run the process until termination
39        self.process.Continue()
40        self.assertEquals(self.process.GetState(), lldb.eStateExited)
41
42    @no_debug_info_test
43    def test_continue(self):
44        """Test that continue stops at the second breakpoint."""
45        self.prepare_test()
46
47        self.process.Continue()
48        self.assertEquals(self.process.GetState(), lldb.eStateStopped)
49        # We should be stopped at the second breakpoint
50        self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(
51            self.process, self.breakpoint2)
52        self.assertIsNotNone(
53            self.thread,
54            "Expected one thread to be stopped at breakpoint 2")
55
56        self.finish_test()
57
58    @no_debug_info_test
59    def test_single_step(self):
60        """Test that single step stops at the second breakpoint."""
61        self.prepare_test()
62
63        step_over = False
64        self.thread.StepInstruction(step_over)
65
66        self.assertEquals(self.process.GetState(), lldb.eStateStopped)
67        self.assertEquals(
68            self.thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress(
69                self.target), self.bkpt_address.GetLoadAddress(
70                self.target))
71        self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(
72            self.process, self.breakpoint2)
73        self.assertIsNotNone(
74            self.thread,
75            "Expected one thread to be stopped at breakpoint 2")
76
77        self.finish_test()
78
79    @no_debug_info_test
80    def test_single_step_thread_specific(self):
81        """Test that single step stops, even though the second breakpoint is not valid."""
82        self.prepare_test()
83
84        # Choose a thread other than the current one. A non-existing thread is
85        # fine.
86        thread_index = self.process.GetNumThreads() + 1
87        self.assertFalse(self.process.GetThreadAtIndex(thread_index).IsValid())
88        self.breakpoint2.SetThreadIndex(thread_index)
89
90        step_over = False
91        self.thread.StepInstruction(step_over)
92
93        self.assertEquals(self.process.GetState(), lldb.eStateStopped)
94        self.assertEquals(
95            self.thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress(
96                self.target), self.bkpt_address.GetLoadAddress(
97                self.target))
98        self.assertEquals(
99            self.thread.GetStopReason(),
100            lldb.eStopReasonPlanComplete,
101            "Stop reason should be 'plan complete'")
102
103        self.finish_test()
104