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