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 12import os 13 14 15class TestVSCode_setBreakpoints(lldbvscode_testcase.VSCodeTestCaseBase): 16 17 mydir = TestBase.compute_mydir(__file__) 18 19 @skipIfWindows 20 def test_set_and_clear(self): 21 '''Tests setting and clearing source file and line breakpoints. 22 This packet is a bit tricky on the debug adaptor side since there 23 is no "clearBreakpoints" packet. Source file and line breakpoints 24 are set by sending a "setBreakpoints" packet with a source file 25 specified and zero or more source lines. If breakpoints have been 26 set in the source file before, any exising breakpoints must remain 27 set, and any new breakpoints must be created, and any breakpoints 28 that were in previous requests and are not in the current request 29 must be removed. This function tests this setting and clearing 30 and makes sure things happen correctly. It doesn't test hitting 31 breakpoints and the functionality of each breakpoint, like 32 'conditions' and 'hitCondition' settings.''' 33 source_basename = 'main.cpp' 34 source_path = os.path.join(os.getcwd(), source_basename) 35 first_line = line_number('main.cpp', 'break 12') 36 second_line = line_number('main.cpp', 'break 13') 37 third_line = line_number('main.cpp', 'break 14') 38 lines = [first_line, second_line, third_line] 39 40 # Visual Studio Code Debug Adaptors have no way to specify the file 41 # without launching or attaching to a process, so we must start a 42 # process in order to be able to set breakpoints. 43 program = self.getBuildArtifact("a.out") 44 self.build_and_launch(program) 45 46 # Set 3 breakoints and verify that they got set correctly 47 response = self.vscode.request_setBreakpoints(source_path, lines) 48 line_to_id = {} 49 if response: 50 breakpoints = response['body']['breakpoints'] 51 self.assertEquals(len(breakpoints), len(lines), 52 "expect %u source breakpoints" % (len(lines))) 53 for breakpoint in breakpoints: 54 line = breakpoint['line'] 55 # Store the "id" of the breakpoint that was set for later 56 line_to_id[line] = breakpoint['id'] 57 self.assertTrue(line in lines, "line expected in lines array") 58 self.assertTrue(breakpoint['verified'], 59 "expect breakpoint verified") 60 61 # There is no breakpoint delete packet, clients just send another 62 # setBreakpoints packet with the same source file with fewer lines. 63 # Below we remove the second line entry and call the setBreakpoints 64 # function again. We want to verify that any breakpoints that were set 65 # before still have the same "id". This means we didn't clear the 66 # breakpoint and set it again at the same location. We also need to 67 # verify that the second line location was actually removed. 68 lines.remove(second_line) 69 # Set 2 breakoints and verify that the previous breakoints that were 70 # set above are still set. 71 response = self.vscode.request_setBreakpoints(source_path, lines) 72 if response: 73 breakpoints = response['body']['breakpoints'] 74 self.assertEquals(len(breakpoints), len(lines), 75 "expect %u source breakpoints" % (len(lines))) 76 for breakpoint in breakpoints: 77 line = breakpoint['line'] 78 # Verify the same breakpoints are still set within LLDB by 79 # making sure the breakpoint ID didn't change 80 self.assertEquals(line_to_id[line], breakpoint['id'], 81 "verify previous breakpoints stayed the same") 82 self.assertTrue(line in lines, "line expected in lines array") 83 self.assertTrue(breakpoint['verified'], 84 "expect breakpoint still verified") 85 86 # Now get the full list of breakpoints set in the target and verify 87 # we have only 2 breakpoints set. The response above could have told 88 # us about 2 breakpoints, but we want to make sure we don't have the 89 # third one still set in the target 90 response = self.vscode.request_testGetTargetBreakpoints() 91 if response: 92 breakpoints = response['body']['breakpoints'] 93 self.assertEquals(len(breakpoints), len(lines), 94 "expect %u source breakpoints" % (len(lines))) 95 for breakpoint in breakpoints: 96 line = breakpoint['line'] 97 # Verify the same breakpoints are still set within LLDB by 98 # making sure the breakpoint ID didn't change 99 self.assertEquals(line_to_id[line], breakpoint['id'], 100 "verify previous breakpoints stayed the same") 101 self.assertTrue(line in lines, "line expected in lines array") 102 self.assertTrue(breakpoint['verified'], 103 "expect breakpoint still verified") 104 105 # Now clear all breakpoints for the source file by passing down an 106 # empty lines array 107 lines = [] 108 response = self.vscode.request_setBreakpoints(source_path, lines) 109 if response: 110 breakpoints = response['body']['breakpoints'] 111 self.assertEquals(len(breakpoints), len(lines), 112 "expect %u source breakpoints" % (len(lines))) 113 114 # Verify with the target that all breakpoints have been cleared 115 response = self.vscode.request_testGetTargetBreakpoints() 116 if response: 117 breakpoints = response['body']['breakpoints'] 118 self.assertEquals(len(breakpoints), len(lines), 119 "expect %u source breakpoints" % (len(lines))) 120 121 # Now set a breakpoint again in the same source file and verify it 122 # was added. 123 lines = [second_line] 124 response = self.vscode.request_setBreakpoints(source_path, lines) 125 if response: 126 breakpoints = response['body']['breakpoints'] 127 self.assertEquals(len(breakpoints), len(lines), 128 "expect %u source breakpoints" % (len(lines))) 129 for breakpoint in breakpoints: 130 line = breakpoint['line'] 131 self.assertTrue(line in lines, "line expected in lines array") 132 self.assertTrue(breakpoint['verified'], 133 "expect breakpoint still verified") 134 135 # Now get the full list of breakpoints set in the target and verify 136 # we have only 2 breakpoints set. The response above could have told 137 # us about 2 breakpoints, but we want to make sure we don't have the 138 # third one still set in the target 139 response = self.vscode.request_testGetTargetBreakpoints() 140 if response: 141 breakpoints = response['body']['breakpoints'] 142 self.assertEquals(len(breakpoints), len(lines), 143 "expect %u source breakpoints" % (len(lines))) 144 for breakpoint in breakpoints: 145 line = breakpoint['line'] 146 self.assertTrue(line in lines, "line expected in lines array") 147 self.assertTrue(breakpoint['verified'], 148 "expect breakpoint still verified") 149 150 @skipIfWindows 151 def test_functionality(self): 152 '''Tests hitting breakpoints and the functionality of a single 153 breakpoint, like 'conditions' and 'hitCondition' settings.''' 154 source_basename = 'main.cpp' 155 source_path = os.path.join(os.getcwd(), source_basename) 156 loop_line = line_number('main.cpp', '// break loop') 157 158 program = self.getBuildArtifact("a.out") 159 self.build_and_launch(program) 160 # Set a breakpoint at the loop line with no condition and no 161 # hitCondition 162 breakpoint_ids = self.set_source_breakpoints(source_path, [loop_line]) 163 self.assertEquals(len(breakpoint_ids), 1, "expect one breakpoint") 164 self.vscode.request_continue() 165 166 # Verify we hit the breakpoint we just set 167 self.verify_breakpoint_hit(breakpoint_ids) 168 169 # Make sure i is zero at first breakpoint 170 i = int(self.vscode.get_local_variable_value('i')) 171 self.assertEquals(i, 0, 'i != 0 after hitting breakpoint') 172 173 # Update the condition on our breakpoint 174 new_breakpoint_ids = self.set_source_breakpoints(source_path, 175 [loop_line], 176 condition="i==4") 177 self.assertEquals(breakpoint_ids, new_breakpoint_ids, 178 "existing breakpoint should have its condition " 179 "updated") 180 181 self.continue_to_breakpoints(breakpoint_ids) 182 i = int(self.vscode.get_local_variable_value('i')) 183 self.assertEquals(i, 4, 184 'i != 4 showing conditional works') 185 186 new_breakpoint_ids = self.set_source_breakpoints(source_path, 187 [loop_line], 188 hitCondition="2") 189 190 self.assertEquals(breakpoint_ids, new_breakpoint_ids, 191 "existing breakpoint should have its condition " 192 "updated") 193 194 # Continue with a hitContidtion of 2 and expect it to skip 1 value 195 self.continue_to_breakpoints(breakpoint_ids) 196 i = int(self.vscode.get_local_variable_value('i')) 197 self.assertEquals(i, 6, 198 'i != 6 showing hitCondition works') 199 200 # continue after hitting our hitCondition and make sure it only goes 201 # up by 1 202 self.continue_to_breakpoints(breakpoint_ids) 203 i = int(self.vscode.get_local_variable_value('i')) 204 self.assertEquals(i, 7, 205 'i != 7 showing post hitCondition hits every time') 206