1""" 2Test lldb-vscode setBreakpoints request 3""" 4 5from __future__ import print_function 6 7import unittest2 8import vscode 9from lldbsuite.test.decorators import * 10from lldbsuite.test.lldbtest import * 11from lldbsuite.test import lldbutil 12import lldbvscode_testcase 13 14 15def make_buffer_verify_dict(start_idx, count, offset=0): 16 verify_dict = {} 17 for i in range(start_idx, start_idx + count): 18 verify_dict['[%i]' % (i)] = {'type': 'int', 'value': str(i+offset)} 19 return verify_dict 20 21 22class TestVSCode_variables(lldbvscode_testcase.VSCodeTestCaseBase): 23 24 mydir = TestBase.compute_mydir(__file__) 25 26 def verify_values(self, verify_dict, actual, varref_dict=None): 27 if 'equals' in verify_dict: 28 verify = verify_dict['equals'] 29 for key in verify: 30 verify_value = verify[key] 31 actual_value = actual[key] 32 self.assertEqual(verify_value, actual_value, 33 '"%s" keys don\'t match (%s != %s)' % ( 34 key, actual_value, verify_value)) 35 if 'startswith' in verify_dict: 36 verify = verify_dict['startswith'] 37 for key in verify: 38 verify_value = verify[key] 39 actual_value = actual[key] 40 startswith = actual_value.startswith(verify_value) 41 self.assertTrue(startswith, 42 ('"%s" value "%s" doesn\'t start with' 43 ' "%s")') % ( 44 key, actual_value, 45 verify_value)) 46 hasVariablesReference = 'variablesReference' in actual 47 varRef = None 48 if hasVariablesReference: 49 # Remember variable references in case we want to test further 50 # by using the evaluate name. 51 varRef = actual['variablesReference'] 52 if varRef != 0 and varref_dict is not None: 53 varref_dict[actual['evaluateName']] = varRef 54 if ('hasVariablesReference' in verify_dict and 55 verify_dict['hasVariablesReference']): 56 self.assertTrue(hasVariablesReference, 57 "verify variable reference") 58 if 'children' in verify_dict: 59 self.assertTrue(hasVariablesReference and varRef is not None and 60 varRef != 0, 61 ("children verify values specified for " 62 "variable without children")) 63 64 response = self.vscode.request_variables(varRef) 65 self.verify_variables(verify_dict['children'], 66 response['body']['variables'], 67 varref_dict) 68 69 def verify_variables(self, verify_dict, variables, varref_dict=None): 70 for variable in variables: 71 name = variable['name'] 72 self.assertIn(name, verify_dict, 73 'variable "%s" in verify dictionary' % (name)) 74 self.verify_values(verify_dict[name], variable, varref_dict) 75 76 @skipIfWindows 77 @skipIfRemote 78 def test_scopes_variables_setVariable_evaluate(self): 79 ''' 80 Tests the "scopes", "variables", "setVariable", and "evaluate" 81 packets. 82 ''' 83 program = self.getBuildArtifact("a.out") 84 self.build_and_launch(program) 85 source = 'main.cpp' 86 breakpoint1_line = line_number(source, '// breakpoint 1') 87 lines = [breakpoint1_line] 88 # Set breakpoint in the thread function so we can step the threads 89 breakpoint_ids = self.set_source_breakpoints(source, lines) 90 self.assertEqual(len(breakpoint_ids), len(lines), 91 "expect correct number of breakpoints") 92 self.continue_to_breakpoints(breakpoint_ids) 93 locals = self.vscode.get_local_variables() 94 globals = self.vscode.get_global_variables() 95 buffer_children = make_buffer_verify_dict(0, 32) 96 verify_locals = { 97 'argc': { 98 'equals': {'type': 'int', 'value': '1'} 99 }, 100 'argv': { 101 'equals': {'type': 'const char **'}, 102 'startswith': {'value': '0x'}, 103 'hasVariablesReference': True 104 }, 105 'pt': { 106 'equals': {'type': 'PointType'}, 107 'hasVariablesReference': True, 108 'children': { 109 'x': {'equals': {'type': 'int', 'value': '11'}}, 110 'y': {'equals': {'type': 'int', 'value': '22'}}, 111 'buffer': {'children': buffer_children} 112 } 113 }, 114 'x': { 115 'equals': {'type': 'int'} 116 } 117 } 118 verify_globals = { 119 's_local': { 120 'equals': {'type': 'float', 'value': '2.25'} 121 }, 122 '::g_global': { 123 'equals': {'type': 'int', 'value': '123'} 124 }, 125 's_global': { 126 'equals': {'type': 'int', 'value': '234'} 127 }, 128 } 129 varref_dict = {} 130 self.verify_variables(verify_locals, locals, varref_dict) 131 self.verify_variables(verify_globals, globals, varref_dict) 132 # pprint.PrettyPrinter(indent=4).pprint(varref_dict) 133 # We need to test the functionality of the "variables" request as it 134 # has optional parameters like "start" and "count" to limit the number 135 # of variables that are fetched 136 varRef = varref_dict['pt.buffer'] 137 response = self.vscode.request_variables(varRef) 138 self.verify_variables(buffer_children, response['body']['variables']) 139 # Verify setting start=0 in the arguments still gets all children 140 response = self.vscode.request_variables(varRef, start=0) 141 self.verify_variables(buffer_children, response['body']['variables']) 142 # Verify setting count=0 in the arguments still gets all children. 143 # If count is zero, it means to get all children. 144 response = self.vscode.request_variables(varRef, count=0) 145 self.verify_variables(buffer_children, response['body']['variables']) 146 # Verify setting count to a value that is too large in the arguments 147 # still gets all children, and no more 148 response = self.vscode.request_variables(varRef, count=1000) 149 self.verify_variables(buffer_children, response['body']['variables']) 150 # Verify setting the start index and count gets only the children we 151 # want 152 response = self.vscode.request_variables(varRef, start=5, count=5) 153 self.verify_variables(make_buffer_verify_dict(5, 5), 154 response['body']['variables']) 155 # Verify setting the start index to a value that is out of range 156 # results in an empty list 157 response = self.vscode.request_variables(varRef, start=32, count=1) 158 self.assertEqual(len(response['body']['variables']), 0, 159 'verify we get no variable back for invalid start') 160 161 # Test evaluate 162 expressions = { 163 'pt.x': { 164 'equals': {'result': '11', 'type': 'int'}, 165 'hasVariablesReference': False 166 }, 167 'pt.buffer[2]': { 168 'equals': {'result': '2', 'type': 'int'}, 169 'hasVariablesReference': False 170 }, 171 'pt': { 172 'equals': {'type': 'PointType'}, 173 'startswith': {'result': 'PointType @ 0x'}, 174 'hasVariablesReference': True 175 }, 176 'pt.buffer': { 177 'equals': {'type': 'int [32]'}, 178 'startswith': {'result': 'int [32] @ 0x'}, 179 'hasVariablesReference': True 180 }, 181 'argv': { 182 'equals': {'type': 'const char **'}, 183 'startswith': {'result': '0x'}, 184 'hasVariablesReference': True 185 }, 186 'argv[0]': { 187 'equals': {'type': 'const char *'}, 188 'startswith': {'result': '0x'}, 189 'hasVariablesReference': True 190 }, 191 '2+3': { 192 'equals': {'result': '5', 'type': 'int'}, 193 'hasVariablesReference': False 194 }, 195 } 196 for expression in expressions: 197 response = self.vscode.request_evaluate(expression) 198 self.verify_values(expressions[expression], response['body']) 199 200 # Test setting variables 201 self.set_local('argc', 123) 202 argc = self.get_local_as_int('argc') 203 self.assertEqual(argc, 123, 204 'verify argc was set to 123 (123 != %i)' % (argc)) 205 206 self.set_local('argv', 0x1234) 207 argv = self.get_local_as_int('argv') 208 self.assertEqual(argv, 0x1234, 209 'verify argv was set to 0x1234 (0x1234 != %#x)' % ( 210 argv)) 211 212 # Set a variable value whose name is synthetic, like a variable index 213 # and verify the value by reading it 214 self.vscode.request_setVariable(varRef, "[0]", 100) 215 response = self.vscode.request_variables(varRef, start=0, count=1) 216 self.verify_variables(make_buffer_verify_dict(0, 1, 100), 217 response['body']['variables']) 218 219 # Set a variable value whose name is a real child value, like "pt.x" 220 # and verify the value by reading it 221 varRef = varref_dict['pt'] 222 self.vscode.request_setVariable(varRef, "x", 111) 223 response = self.vscode.request_variables(varRef, start=0, count=1) 224 value = response['body']['variables'][0]['value'] 225 self.assertEqual(value, '111', 226 'verify pt.x got set to 111 (111 != %s)' % (value)) 227 228 # We check shadowed variables and that a new get_local_variables request 229 # gets the right data 230 breakpoint2_line = line_number(source, '// breakpoint 2') 231 lines = [breakpoint2_line] 232 breakpoint_ids = self.set_source_breakpoints(source, lines) 233 self.assertEqual(len(breakpoint_ids), len(lines), 234 "expect correct number of breakpoints") 235 self.continue_to_breakpoints(breakpoint_ids) 236 237 verify_locals['argc']['equals']['value'] = '123' 238 verify_locals['pt']['children']['x']['equals']['value'] = '111' 239 verify_locals['x @ main.cpp:17'] = {'equals': {'type': 'int', 'value': '89'}} 240 verify_locals['x @ main.cpp:19'] = {'equals': {'type': 'int', 'value': '42'}} 241 verify_locals['x @ main.cpp:21'] = {'equals': {'type': 'int', 'value': '72'}} 242 243 self.verify_variables(verify_locals, self.vscode.get_local_variables()) 244 245 # Now we verify that we correctly change the name of a variable with and without differentiator suffix 246 self.assertFalse(self.vscode.request_setVariable(1, "x2", 9)['success']) 247 self.assertFalse(self.vscode.request_setVariable(1, "x @ main.cpp:0", 9)['success']) 248 249 self.assertTrue(self.vscode.request_setVariable(1, "x @ main.cpp:17", 17)['success']) 250 self.assertTrue(self.vscode.request_setVariable(1, "x @ main.cpp:19", 19)['success']) 251 self.assertTrue(self.vscode.request_setVariable(1, "x @ main.cpp:21", 21)['success']) 252 253 # The following should have no effect 254 self.assertFalse(self.vscode.request_setVariable(1, "x @ main.cpp:21", "invalid")['success']) 255 256 verify_locals['x @ main.cpp:17']['equals']['value'] = '17' 257 verify_locals['x @ main.cpp:19']['equals']['value'] = '19' 258 verify_locals['x @ main.cpp:21']['equals']['value'] = '21' 259 260 self.verify_variables(verify_locals, self.vscode.get_local_variables()) 261 262 # The plain x variable shold refer to the innermost x 263 self.assertTrue(self.vscode.request_setVariable(1, "x", 22)['success']) 264 verify_locals['x @ main.cpp:21']['equals']['value'] = '22' 265 266 self.verify_variables(verify_locals, self.vscode.get_local_variables()) 267 268 # In breakpoint 3, there should be no shadowed variables 269 breakpoint3_line = line_number(source, '// breakpoint 3') 270 lines = [breakpoint3_line] 271 breakpoint_ids = self.set_source_breakpoints(source, lines) 272 self.assertEqual(len(breakpoint_ids), len(lines), 273 "expect correct number of breakpoints") 274 self.continue_to_breakpoints(breakpoint_ids) 275 276 locals = self.vscode.get_local_variables() 277 names = [var['name'] for var in locals] 278 # The first shadowed x shouldn't have a suffix anymore 279 verify_locals['x'] = {'equals': {'type': 'int', 'value': '17'}} 280 self.assertNotIn('x @ main.cpp:17', names) 281 self.assertNotIn('x @ main.cpp:19', names) 282 self.assertNotIn('x @ main.cpp:21', names) 283 284 self.verify_variables(verify_locals, locals) 285