1"""
2Test lldb-vscode setBreakpoints request
3"""
4
5
6import unittest2
7import vscode
8from lldbsuite.test.decorators import *
9from lldbsuite.test.lldbtest import *
10from lldbsuite.test import lldbutil
11import lldbvscode_testcase
12
13
14class TestVSCode_setFunctionBreakpoints(
15        lldbvscode_testcase.VSCodeTestCaseBase):
16
17    mydir = TestBase.compute_mydir(__file__)
18
19    @skipIfWindows
20    @skipIfRemote
21    def test_set_and_clear(self):
22        '''Tests setting and clearing function breakpoints.
23           This packet is a bit tricky on the debug adaptor side since there
24           is no "clearFunction Breakpoints" packet. Function breakpoints
25           are set by sending a "setFunctionBreakpoints" packet with zero or
26           more function names. If function breakpoints have been set before,
27           any existing breakpoints must remain set, and any new breakpoints
28           must be created, and any breakpoints that were in previous requests
29           and are not in the current request must be removed. This function
30           tests this setting and clearing and makes sure things happen
31           correctly. It doesn't test hitting breakpoints and the functionality
32           of each breakpoint, like 'conditions' and 'hitCondition' settings.
33        '''
34        # Visual Studio Code Debug Adaptors have no way to specify the file
35        # without launching or attaching to a process, so we must start a
36        # process in order to be able to set breakpoints.
37        program = self.getBuildArtifact("a.out")
38        self.build_and_launch(program)
39        bp_id_12 = None
40        functions = ['twelve']
41        # Set a function breakpoint at 'twelve'
42        response = self.vscode.request_setFunctionBreakpoints(functions)
43        if response:
44            breakpoints = response['body']['breakpoints']
45            self.assertEquals(len(breakpoints), len(functions),
46                            "expect %u source breakpoints" % (len(functions)))
47            for breakpoint in breakpoints:
48                bp_id_12 = breakpoint['id']
49                self.assertTrue(breakpoint['verified'],
50                                "expect breakpoint verified")
51
52        # Add an extra name and make sure we have two breakpoints after this
53        functions.append('thirteen')
54        response = self.vscode.request_setFunctionBreakpoints(functions)
55        if response:
56            breakpoints = response['body']['breakpoints']
57            self.assertEquals(len(breakpoints), len(functions),
58                            "expect %u source breakpoints" % (len(functions)))
59            for breakpoint in breakpoints:
60                self.assertTrue(breakpoint['verified'],
61                                "expect breakpoint verified")
62
63        # There is no breakpoint delete packet, clients just send another
64        # setFunctionBreakpoints packet with the different function names.
65        functions.remove('thirteen')
66        response = self.vscode.request_setFunctionBreakpoints(functions)
67        if response:
68            breakpoints = response['body']['breakpoints']
69            self.assertEquals(len(breakpoints), len(functions),
70                            "expect %u source breakpoints" % (len(functions)))
71            for breakpoint in breakpoints:
72                bp_id = breakpoint['id']
73                self.assertEquals(bp_id, bp_id_12,
74                                'verify "twelve" breakpoint ID is same')
75                self.assertTrue(breakpoint['verified'],
76                                "expect breakpoint still verified")
77
78        # Now get the full list of breakpoints set in the target and verify
79        # we have only 1 breakpoints set. The response above could have told
80        # us about 1 breakpoints, but we want to make sure we don't have the
81        # second one still set in the target
82        response = self.vscode.request_testGetTargetBreakpoints()
83        if response:
84            breakpoints = response['body']['breakpoints']
85            self.assertEquals(len(breakpoints), len(functions),
86                            "expect %u source breakpoints" % (len(functions)))
87            for breakpoint in breakpoints:
88                bp_id = breakpoint['id']
89                self.assertEquals(bp_id, bp_id_12,
90                                'verify "twelve" breakpoint ID is same')
91                self.assertTrue(breakpoint['verified'],
92                                "expect breakpoint still verified")
93
94        # Now clear all breakpoints for the source file by passing down an
95        # empty lines array
96        functions = []
97        response = self.vscode.request_setFunctionBreakpoints(functions)
98        if response:
99            breakpoints = response['body']['breakpoints']
100            self.assertEquals(len(breakpoints), len(functions),
101                            "expect %u source breakpoints" % (len(functions)))
102
103        # Verify with the target that all breakpoints have been cleared
104        response = self.vscode.request_testGetTargetBreakpoints()
105        if response:
106            breakpoints = response['body']['breakpoints']
107            self.assertEquals(len(breakpoints), len(functions),
108                            "expect %u source breakpoints" % (len(functions)))
109
110    @skipIfWindows
111    @skipIfRemote
112    def test_functionality(self):
113        '''Tests hitting breakpoints and the functionality of a single
114           breakpoint, like 'conditions' and 'hitCondition' settings.'''
115
116        program = self.getBuildArtifact("a.out")
117        self.build_and_launch(program)
118        # Set a breakpoint on "twelve" with no condition and no hitCondition
119        functions = ['twelve']
120        breakpoint_ids = self.set_function_breakpoints(functions)
121
122        self.assertEquals(len(breakpoint_ids), len(functions),
123                        "expect one breakpoint")
124
125        # Verify we hit the breakpoint we just set
126        self.continue_to_breakpoints(breakpoint_ids)
127
128        # Make sure i is zero at first breakpoint
129        i = int(self.vscode.get_local_variable_value('i'))
130        self.assertEquals(i, 0, 'i != 0 after hitting breakpoint')
131
132        # Update the condition on our breakpoint
133        new_breakpoint_ids = self.set_function_breakpoints(functions,
134                                                           condition="i==4")
135        self.assertEquals(breakpoint_ids, new_breakpoint_ids,
136                        "existing breakpoint should have its condition "
137                        "updated")
138
139        self.continue_to_breakpoints(breakpoint_ids)
140        i = int(self.vscode.get_local_variable_value('i'))
141        self.assertEquals(i, 4,
142                        'i != 4 showing conditional works')
143        new_breakpoint_ids = self.set_function_breakpoints(functions,
144                                                           hitCondition="2")
145
146        self.assertEquals(breakpoint_ids, new_breakpoint_ids,
147                        "existing breakpoint should have its condition "
148                        "updated")
149
150        # Continue with a hitCondition of 2 and expect it to skip 1 value
151        self.continue_to_breakpoints(breakpoint_ids)
152        i = int(self.vscode.get_local_variable_value('i'))
153        self.assertEquals(i, 6,
154                        'i != 6 showing hitCondition works')
155
156        # continue after hitting our hitCondition and make sure it only goes
157        # up by 1
158        self.continue_to_breakpoints(breakpoint_ids)
159        i = int(self.vscode.get_local_variable_value('i'))
160        self.assertEquals(i, 7,
161                        'i != 7 showing post hitCondition hits every time')
162