1""" 2Test lldb-dap setBreakpoints request 3""" 4 5import os 6 7import dap_server 8import lldbdap_testcase 9from lldbsuite.test import lldbutil 10from lldbsuite.test.decorators import * 11from lldbsuite.test.lldbtest import * 12 13 14def make_buffer_verify_dict(start_idx, count, offset=0): 15 verify_dict = {} 16 for i in range(start_idx, start_idx + count): 17 verify_dict["[%i]" % (i)] = {"type": "int", "value": str(i + offset)} 18 return verify_dict 19 20 21class TestDAP_variables(lldbdap_testcase.DAPTestCaseBase): 22 def verify_values(self, verify_dict, actual, varref_dict=None, expression=None): 23 if "equals" in verify_dict: 24 verify = verify_dict["equals"] 25 for key in verify: 26 verify_value = verify[key] 27 actual_value = actual[key] 28 self.assertEqual( 29 verify_value, 30 actual_value, 31 '"%s" keys don\'t match (%s != %s) from:\n%s' 32 % (key, actual_value, verify_value, actual), 33 ) 34 if "startswith" in verify_dict: 35 verify = verify_dict["startswith"] 36 for key in verify: 37 verify_value = verify[key] 38 actual_value = actual[key] 39 startswith = actual_value.startswith(verify_value) 40 self.assertTrue( 41 startswith, 42 ('"%s" value "%s" doesn\'t start with "%s")') 43 % (key, actual_value, verify_value), 44 ) 45 if "matches" in verify_dict: 46 verify = verify_dict["matches"] 47 for key in verify: 48 verify_value = verify[key] 49 actual_value = actual[key] 50 self.assertRegex( 51 actual_value, 52 verify_value, 53 ('"%s" value "%s" doesn\'t match pattern "%s")') 54 % (key, actual_value, verify_value), 55 ) 56 if "contains" in verify_dict: 57 verify = verify_dict["contains"] 58 for key in verify: 59 contains_array = verify[key] 60 actual_value = actual[key] 61 self.assertIsInstance(contains_array, list) 62 for verify_value in contains_array: 63 self.assertIn(verify_value, actual_value) 64 if "missing" in verify_dict: 65 missing = verify_dict["missing"] 66 for key in missing: 67 self.assertNotIn( 68 key, actual, 'key "%s" is not expected in %s' % (key, actual) 69 ) 70 hasVariablesReference = "variablesReference" in actual 71 varRef = None 72 if hasVariablesReference: 73 # Remember variable references in case we want to test further 74 # by using the evaluate name. 75 varRef = actual["variablesReference"] 76 if varRef != 0 and varref_dict is not None: 77 if expression is None: 78 evaluateName = actual["evaluateName"] 79 else: 80 evaluateName = expression 81 varref_dict[evaluateName] = varRef 82 if ( 83 "hasVariablesReference" in verify_dict 84 and verify_dict["hasVariablesReference"] 85 ): 86 self.assertTrue(hasVariablesReference, "verify variable reference") 87 if "children" in verify_dict: 88 self.assertTrue( 89 hasVariablesReference and varRef is not None and varRef != 0, 90 ("children verify values specified for " "variable without children"), 91 ) 92 93 response = self.dap_server.request_variables(varRef) 94 self.verify_variables( 95 verify_dict["children"], response["body"]["variables"], varref_dict 96 ) 97 98 def verify_variables(self, verify_dict, variables, varref_dict=None): 99 for variable in variables: 100 name = variable["name"] 101 if not name.startswith("std::"): 102 self.assertIn( 103 name, verify_dict, 'variable "%s" in verify dictionary' % (name) 104 ) 105 self.verify_values(verify_dict[name], variable, varref_dict) 106 107 def darwin_dwarf_missing_obj(self, initCommands): 108 self.build(debug_info="dwarf") 109 program = self.getBuildArtifact("a.out") 110 main_obj = self.getBuildArtifact("main.o") 111 self.assertTrue(os.path.exists(main_obj)) 112 # Delete the main.o file that contains the debug info so we force an 113 # error when we run to main and try to get variables 114 os.unlink(main_obj) 115 116 self.create_debug_adaptor() 117 self.assertTrue(os.path.exists(program), "executable must exist") 118 119 self.launch(program=program, initCommands=initCommands) 120 121 functions = ["main"] 122 breakpoint_ids = self.set_function_breakpoints(functions) 123 self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint") 124 self.continue_to_breakpoints(breakpoint_ids) 125 126 locals = self.dap_server.get_local_variables() 127 128 verify_locals = { 129 "<error>": { 130 "equals": {"type": "const char *"}, 131 "contains": { 132 "value": [ 133 "debug map object file ", 134 'main.o" containing debug info does not exist, debug info will not be loaded', 135 ] 136 }, 137 }, 138 } 139 varref_dict = {} 140 self.verify_variables(verify_locals, locals, varref_dict) 141 142 def do_test_scopes_variables_setVariable_evaluate( 143 self, enableAutoVariableSummaries: bool 144 ): 145 """ 146 Tests the "scopes", "variables", "setVariable", and "evaluate" 147 packets. 148 """ 149 program = self.getBuildArtifact("a.out") 150 self.build_and_launch( 151 program, enableAutoVariableSummaries=enableAutoVariableSummaries 152 ) 153 source = "main.cpp" 154 breakpoint1_line = line_number(source, "// breakpoint 1") 155 lines = [breakpoint1_line] 156 # Set breakpoint in the thread function so we can step the threads 157 breakpoint_ids = self.set_source_breakpoints(source, lines) 158 self.assertEqual( 159 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 160 ) 161 self.continue_to_breakpoints(breakpoint_ids) 162 locals = self.dap_server.get_local_variables() 163 globals = self.dap_server.get_global_variables() 164 buffer_children = make_buffer_verify_dict(0, 16) 165 verify_locals = { 166 "argc": { 167 "equals": { 168 "type": "int", 169 "value": "1", 170 }, 171 "$__lldb_extensions": { 172 "equals": { 173 "value": "1", 174 }, 175 "declaration": { 176 "equals": {"line": 12, "column": 14}, 177 "contains": {"path": ["lldb-dap", "variables", "main.cpp"]}, 178 }, 179 }, 180 }, 181 "argv": { 182 "equals": {"type": "const char **"}, 183 "startswith": {"value": "0x"}, 184 "hasVariablesReference": True, 185 }, 186 "pt": { 187 "equals": { 188 "type": "PointType", 189 }, 190 "hasVariablesReference": True, 191 "children": { 192 "x": {"equals": {"type": "int", "value": "11"}}, 193 "y": {"equals": {"type": "int", "value": "22"}}, 194 "buffer": {"children": buffer_children}, 195 }, 196 }, 197 "x": {"equals": {"type": "int"}}, 198 } 199 if enableAutoVariableSummaries: 200 verify_locals["pt"]["$__lldb_extensions"] = { 201 "equals": {"autoSummary": "{x:11, y:22}"} 202 } 203 verify_globals = { 204 "s_local": {"equals": {"type": "float", "value": "2.25"}}, 205 "::g_global": {"equals": {"type": "int", "value": "123"}}, 206 "s_global": {"equals": {"type": "int", "value": "234"}}, 207 } 208 varref_dict = {} 209 self.verify_variables(verify_locals, locals, varref_dict) 210 self.verify_variables(verify_globals, globals, varref_dict) 211 # pprint.PrettyPrinter(indent=4).pprint(varref_dict) 212 # We need to test the functionality of the "variables" request as it 213 # has optional parameters like "start" and "count" to limit the number 214 # of variables that are fetched 215 varRef = varref_dict["pt.buffer"] 216 response = self.dap_server.request_variables(varRef) 217 self.verify_variables(buffer_children, response["body"]["variables"]) 218 # Verify setting start=0 in the arguments still gets all children 219 response = self.dap_server.request_variables(varRef, start=0) 220 self.verify_variables(buffer_children, response["body"]["variables"]) 221 # Verify setting count=0 in the arguments still gets all children. 222 # If count is zero, it means to get all children. 223 response = self.dap_server.request_variables(varRef, count=0) 224 self.verify_variables(buffer_children, response["body"]["variables"]) 225 # Verify setting count to a value that is too large in the arguments 226 # still gets all children, and no more 227 response = self.dap_server.request_variables(varRef, count=1000) 228 self.verify_variables(buffer_children, response["body"]["variables"]) 229 # Verify setting the start index and count gets only the children we 230 # want 231 response = self.dap_server.request_variables(varRef, start=5, count=5) 232 self.verify_variables( 233 make_buffer_verify_dict(5, 5), response["body"]["variables"] 234 ) 235 # Verify setting the start index to a value that is out of range 236 # results in an empty list 237 response = self.dap_server.request_variables(varRef, start=32, count=1) 238 self.assertEqual( 239 len(response["body"]["variables"]), 240 0, 241 "verify we get no variable back for invalid start", 242 ) 243 244 # Test evaluate 245 expressions = { 246 "pt.x": { 247 "equals": {"result": "11", "type": "int"}, 248 "hasVariablesReference": False, 249 }, 250 "pt.buffer[2]": { 251 "equals": {"result": "2", "type": "int"}, 252 "hasVariablesReference": False, 253 }, 254 "pt": { 255 "equals": {"type": "PointType"}, 256 "startswith": { 257 "result": ( 258 "{x:11, y:22, buffer:{...}}" 259 if enableAutoVariableSummaries 260 else "PointType @ 0x" 261 ) 262 }, 263 "hasVariablesReference": True, 264 }, 265 "pt.buffer": { 266 "equals": {"type": "int[16]"}, 267 "startswith": { 268 "result": ( 269 "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}" 270 if enableAutoVariableSummaries 271 else "int[16] @ 0x" 272 ) 273 }, 274 "hasVariablesReference": True, 275 }, 276 "argv": { 277 "equals": {"type": "const char **"}, 278 "startswith": {"result": "0x"}, 279 "hasVariablesReference": True, 280 }, 281 "argv[0]": { 282 "equals": {"type": "const char *"}, 283 "startswith": {"result": "0x"}, 284 "hasVariablesReference": True, 285 }, 286 "2+3": { 287 "equals": {"result": "5", "type": "int"}, 288 "hasVariablesReference": False, 289 }, 290 } 291 for expression in expressions: 292 response = self.dap_server.request_evaluate(expression) 293 self.verify_values(expressions[expression], response["body"]) 294 295 # Test setting variables 296 self.set_local("argc", 123) 297 argc = self.get_local_as_int("argc") 298 self.assertEqual(argc, 123, "verify argc was set to 123 (123 != %i)" % (argc)) 299 300 self.set_local("argv", 0x1234) 301 argv = self.get_local_as_int("argv") 302 self.assertEqual( 303 argv, 0x1234, "verify argv was set to 0x1234 (0x1234 != %#x)" % (argv) 304 ) 305 306 # Set a variable value whose name is synthetic, like a variable index 307 # and verify the value by reading it 308 self.dap_server.request_setVariable(varRef, "[0]", 100) 309 response = self.dap_server.request_variables(varRef, start=0, count=1) 310 self.verify_variables( 311 make_buffer_verify_dict(0, 1, 100), response["body"]["variables"] 312 ) 313 314 # Set a variable value whose name is a real child value, like "pt.x" 315 # and verify the value by reading it 316 varRef = varref_dict["pt"] 317 self.dap_server.request_setVariable(varRef, "x", 111) 318 response = self.dap_server.request_variables(varRef, start=0, count=1) 319 value = response["body"]["variables"][0]["value"] 320 self.assertEqual( 321 value, "111", "verify pt.x got set to 111 (111 != %s)" % (value) 322 ) 323 324 # We check shadowed variables and that a new get_local_variables request 325 # gets the right data 326 breakpoint2_line = line_number(source, "// breakpoint 2") 327 lines = [breakpoint2_line] 328 breakpoint_ids = self.set_source_breakpoints(source, lines) 329 self.assertEqual( 330 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 331 ) 332 self.continue_to_breakpoints(breakpoint_ids) 333 334 verify_locals["argc"]["equals"]["value"] = "123" 335 verify_locals["pt"]["children"]["x"]["equals"]["value"] = "111" 336 verify_locals["x @ main.cpp:17"] = {"equals": {"type": "int", "value": "89"}} 337 verify_locals["x @ main.cpp:19"] = {"equals": {"type": "int", "value": "42"}} 338 verify_locals["x @ main.cpp:21"] = {"equals": {"type": "int", "value": "72"}} 339 340 self.verify_variables(verify_locals, self.dap_server.get_local_variables()) 341 342 # Now we verify that we correctly change the name of a variable with and without differentiator suffix 343 self.assertFalse(self.dap_server.request_setVariable(1, "x2", 9)["success"]) 344 self.assertFalse( 345 self.dap_server.request_setVariable(1, "x @ main.cpp:0", 9)["success"] 346 ) 347 348 self.assertTrue( 349 self.dap_server.request_setVariable(1, "x @ main.cpp:17", 17)["success"] 350 ) 351 self.assertTrue( 352 self.dap_server.request_setVariable(1, "x @ main.cpp:19", 19)["success"] 353 ) 354 self.assertTrue( 355 self.dap_server.request_setVariable(1, "x @ main.cpp:21", 21)["success"] 356 ) 357 358 # The following should have no effect 359 self.assertFalse( 360 self.dap_server.request_setVariable(1, "x @ main.cpp:21", "invalid")[ 361 "success" 362 ] 363 ) 364 365 verify_locals["x @ main.cpp:17"]["equals"]["value"] = "17" 366 verify_locals["x @ main.cpp:19"]["equals"]["value"] = "19" 367 verify_locals["x @ main.cpp:21"]["equals"]["value"] = "21" 368 369 self.verify_variables(verify_locals, self.dap_server.get_local_variables()) 370 371 # The plain x variable shold refer to the innermost x 372 self.assertTrue(self.dap_server.request_setVariable(1, "x", 22)["success"]) 373 verify_locals["x @ main.cpp:21"]["equals"]["value"] = "22" 374 375 self.verify_variables(verify_locals, self.dap_server.get_local_variables()) 376 377 # In breakpoint 3, there should be no shadowed variables 378 breakpoint3_line = line_number(source, "// breakpoint 3") 379 lines = [breakpoint3_line] 380 breakpoint_ids = self.set_source_breakpoints(source, lines) 381 self.assertEqual( 382 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 383 ) 384 self.continue_to_breakpoints(breakpoint_ids) 385 386 locals = self.dap_server.get_local_variables() 387 names = [var["name"] for var in locals] 388 # The first shadowed x shouldn't have a suffix anymore 389 verify_locals["x"] = {"equals": {"type": "int", "value": "17"}} 390 self.assertNotIn("x @ main.cpp:17", names) 391 self.assertNotIn("x @ main.cpp:19", names) 392 self.assertNotIn("x @ main.cpp:21", names) 393 394 self.verify_variables(verify_locals, locals) 395 396 @skipIfWindows 397 @skipIfRemote 398 def test_scopes_variables_setVariable_evaluate(self): 399 self.do_test_scopes_variables_setVariable_evaluate( 400 enableAutoVariableSummaries=False 401 ) 402 403 @skipIfWindows 404 @skipIfRemote 405 def test_scopes_variables_setVariable_evaluate_with_descriptive_summaries(self): 406 self.do_test_scopes_variables_setVariable_evaluate( 407 enableAutoVariableSummaries=True 408 ) 409 410 def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: bool): 411 """ 412 Tests the evaluated expression expands successfully after "scopes" packets 413 and permanent expressions persist. 414 """ 415 program = self.getBuildArtifact("a.out") 416 self.build_and_launch( 417 program, enableAutoVariableSummaries=enableAutoVariableSummaries 418 ) 419 source = "main.cpp" 420 breakpoint1_line = line_number(source, "// breakpoint 1") 421 lines = [breakpoint1_line] 422 # Set breakpoint in the thread function so we can step the threads 423 breakpoint_ids = self.set_source_breakpoints(source, lines) 424 self.assertEqual( 425 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 426 ) 427 self.continue_to_breakpoints(breakpoint_ids) 428 429 # Verify locals 430 locals = self.dap_server.get_local_variables() 431 buffer_children = make_buffer_verify_dict(0, 32) 432 verify_locals = { 433 "argc": { 434 "equals": {"type": "int", "value": "1"}, 435 "missing": ["indexedVariables"], 436 }, 437 "argv": { 438 "equals": {"type": "const char **"}, 439 "startswith": {"value": "0x"}, 440 "hasVariablesReference": True, 441 "missing": ["indexedVariables"], 442 }, 443 "pt": { 444 "equals": {"type": "PointType"}, 445 "hasVariablesReference": True, 446 "missing": ["indexedVariables"], 447 "children": { 448 "x": { 449 "equals": {"type": "int", "value": "11"}, 450 "missing": ["indexedVariables"], 451 }, 452 "y": { 453 "equals": {"type": "int", "value": "22"}, 454 "missing": ["indexedVariables"], 455 }, 456 "buffer": { 457 "children": buffer_children, 458 "equals": {"indexedVariables": 16}, 459 }, 460 }, 461 }, 462 "x": { 463 "equals": {"type": "int"}, 464 "missing": ["indexedVariables"], 465 }, 466 } 467 self.verify_variables(verify_locals, locals) 468 469 # Evaluate expandable expression twice: once permanent (from repl) 470 # the other temporary (from other UI). 471 expandable_expression = { 472 "name": "pt", 473 "context": { 474 "repl": { 475 "equals": {"type": "PointType"}, 476 "equals": { 477 "result": """(PointType) $0 = { 478 x = 11 479 y = 22 480 buffer = { 481 [0] = 0 482 [1] = 1 483 [2] = 2 484 [3] = 3 485 [4] = 4 486 [5] = 5 487 [6] = 6 488 [7] = 7 489 [8] = 8 490 [9] = 9 491 [10] = 10 492 [11] = 11 493 [12] = 12 494 [13] = 13 495 [14] = 14 496 [15] = 15 497 } 498}""" 499 }, 500 "missing": ["indexedVariables"], 501 "hasVariablesReference": True, 502 }, 503 "hover": { 504 "equals": {"type": "PointType"}, 505 "startswith": { 506 "result": ( 507 "{x:11, y:22, buffer:{...}}" 508 if enableAutoVariableSummaries 509 else "PointType @ 0x" 510 ) 511 }, 512 "missing": ["indexedVariables"], 513 "hasVariablesReference": True, 514 }, 515 "watch": { 516 "equals": {"type": "PointType"}, 517 "startswith": { 518 "result": ( 519 "{x:11, y:22, buffer:{...}}" 520 if enableAutoVariableSummaries 521 else "PointType @ 0x" 522 ) 523 }, 524 "missing": ["indexedVariables"], 525 "hasVariablesReference": True, 526 }, 527 "variables": { 528 "equals": {"type": "PointType"}, 529 "startswith": { 530 "result": ( 531 "{x:11, y:22, buffer:{...}}" 532 if enableAutoVariableSummaries 533 else "PointType @ 0x" 534 ) 535 }, 536 "missing": ["indexedVariables"], 537 "hasVariablesReference": True, 538 }, 539 }, 540 "children": { 541 "x": {"equals": {"type": "int", "value": "11"}}, 542 "y": {"equals": {"type": "int", "value": "22"}}, 543 "buffer": {"children": buffer_children}, 544 }, 545 } 546 547 # Evaluate from known contexts. 548 expr_varref_dict = {} 549 for context, verify_dict in expandable_expression["context"].items(): 550 response = self.dap_server.request_evaluate( 551 expandable_expression["name"], 552 frameIndex=0, 553 threadId=None, 554 context=context, 555 ) 556 self.verify_values( 557 verify_dict, 558 response["body"], 559 expr_varref_dict, 560 expandable_expression["name"], 561 ) 562 563 # Evaluate locals again. 564 locals = self.dap_server.get_local_variables() 565 self.verify_variables(verify_locals, locals) 566 567 # Verify the evaluated expressions before second locals evaluation 568 # can be expanded. 569 var_ref = expr_varref_dict[expandable_expression["name"]] 570 response = self.dap_server.request_variables(var_ref) 571 self.verify_variables( 572 expandable_expression["children"], response["body"]["variables"] 573 ) 574 575 # Continue to breakpoint 3, permanent variable should still exist 576 # after resume. 577 breakpoint3_line = line_number(source, "// breakpoint 3") 578 lines = [breakpoint3_line] 579 breakpoint_ids = self.set_source_breakpoints(source, lines) 580 self.assertEqual( 581 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 582 ) 583 self.continue_to_breakpoints(breakpoint_ids) 584 585 var_ref = expr_varref_dict[expandable_expression["name"]] 586 response = self.dap_server.request_variables(var_ref) 587 self.verify_variables( 588 expandable_expression["children"], response["body"]["variables"] 589 ) 590 591 # Test that frame scopes have corresponding presentation hints. 592 frame_id = self.dap_server.get_stackFrame()["id"] 593 scopes = self.dap_server.request_scopes(frame_id)["body"]["scopes"] 594 595 scope_names = [scope["name"] for scope in scopes] 596 self.assertIn("Locals", scope_names) 597 self.assertIn("Registers", scope_names) 598 599 for scope in scopes: 600 if scope["name"] == "Locals": 601 self.assertEqual(scope.get("presentationHint"), "locals") 602 if scope["name"] == "Registers": 603 self.assertEqual(scope.get("presentationHint"), "registers") 604 605 @skipIfWindows 606 @skipIfRemote 607 def test_scopes_and_evaluate_expansion(self): 608 self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=False) 609 610 @skipIfWindows 611 @skipIfRemote 612 def test_scopes_and_evaluate_expansion_with_descriptive_summaries(self): 613 self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=True) 614 615 def do_test_indexedVariables(self, enableSyntheticChildDebugging: bool): 616 """ 617 Tests that arrays and lldb.SBValue objects that have synthetic child 618 providers have "indexedVariables" key/value pairs. This helps the IDE 619 not to fetch too many children all at once. 620 """ 621 program = self.getBuildArtifact("a.out") 622 self.build_and_launch( 623 program, enableSyntheticChildDebugging=enableSyntheticChildDebugging 624 ) 625 source = "main.cpp" 626 breakpoint1_line = line_number(source, "// breakpoint 4") 627 lines = [breakpoint1_line] 628 # Set breakpoint in the thread function so we can step the threads 629 breakpoint_ids = self.set_source_breakpoints(source, lines) 630 self.assertEqual( 631 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 632 ) 633 self.continue_to_breakpoints(breakpoint_ids) 634 635 # Verify locals 636 locals = self.dap_server.get_local_variables() 637 # The vector variables might have one additional entry from the fake 638 # "[raw]" child. 639 raw_child_count = 1 if enableSyntheticChildDebugging else 0 640 verify_locals = { 641 "small_array": {"equals": {"indexedVariables": 5}}, 642 "large_array": {"equals": {"indexedVariables": 200}}, 643 "small_vector": {"equals": {"indexedVariables": 5 + raw_child_count}}, 644 "large_vector": {"equals": {"indexedVariables": 200 + raw_child_count}}, 645 "pt": {"missing": ["indexedVariables"]}, 646 } 647 self.verify_variables(verify_locals, locals) 648 649 # We also verify that we produce a "[raw]" fake child with the real 650 # SBValue for the synthetic type. 651 verify_children = { 652 "[0]": {"equals": {"type": "int", "value": "0"}}, 653 "[1]": {"equals": {"type": "int", "value": "0"}}, 654 "[2]": {"equals": {"type": "int", "value": "0"}}, 655 "[3]": {"equals": {"type": "int", "value": "0"}}, 656 "[4]": {"equals": {"type": "int", "value": "0"}}, 657 } 658 if enableSyntheticChildDebugging: 659 verify_children["[raw]"] = ({"contains": {"type": ["vector"]}},) 660 661 children = self.dap_server.request_variables(locals[2]["variablesReference"])[ 662 "body" 663 ]["variables"] 664 self.verify_variables(verify_children, children) 665 666 @skipIfWindows 667 @skipIfRemote 668 def test_indexedVariables(self): 669 self.do_test_indexedVariables(enableSyntheticChildDebugging=False) 670 671 @skipIfWindows 672 @skipIfRemote 673 def test_indexedVariables_with_raw_child_for_synthetics(self): 674 self.do_test_indexedVariables(enableSyntheticChildDebugging=True) 675 676 @skipIfWindows 677 @skipIfRemote 678 def test_registers(self): 679 """ 680 Test that registers whose byte size is the size of a pointer on 681 the current system get formatted as lldb::eFormatAddressInfo. This 682 will show the pointer value followed by a description of the address 683 itself. To test this we attempt to find the PC value in the general 684 purpose registers, and since we will be stopped in main.cpp, verify 685 that the value for the PC starts with a pointer and is followed by 686 a description that contains main.cpp. 687 """ 688 program = self.getBuildArtifact("a.out") 689 self.build_and_launch(program) 690 source = "main.cpp" 691 breakpoint1_line = line_number(source, "// breakpoint 1") 692 lines = [breakpoint1_line] 693 # Set breakpoint in the thread function so we can step the threads 694 breakpoint_ids = self.set_source_breakpoints(source, lines) 695 self.assertEqual( 696 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 697 ) 698 self.continue_to_breakpoints(breakpoint_ids) 699 700 pc_name = None 701 arch = self.getArchitecture() 702 if arch == "x86_64": 703 pc_name = "rip" 704 elif arch == "x86": 705 pc_name = "rip" 706 elif arch.startswith("arm"): 707 pc_name = "pc" 708 709 if pc_name is None: 710 return 711 # Verify locals 712 reg_sets = self.dap_server.get_registers() 713 for reg_set in reg_sets: 714 if reg_set["name"] == "General Purpose Registers": 715 varRef = reg_set["variablesReference"] 716 regs = self.dap_server.request_variables(varRef)["body"]["variables"] 717 for reg in regs: 718 if reg["name"] == pc_name: 719 value = reg["value"] 720 self.assertTrue(value.startswith("0x")) 721 self.assertIn("a.out`main + ", value) 722 self.assertIn("at main.cpp:", value) 723 724 @no_debug_info_test 725 @skipUnlessDarwin 726 def test_darwin_dwarf_missing_obj(self): 727 """ 728 Test that if we build a binary with DWARF in .o files and we remove 729 the .o file for main.cpp, that we get a variable named "<error>" 730 whose value matches the appriopriate error. Errors when getting 731 variables are returned in the LLDB API when the user should be 732 notified of issues that can easily be solved by rebuilding or 733 changing compiler options and are designed to give better feedback 734 to the user. 735 """ 736 self.darwin_dwarf_missing_obj(None) 737 738 @no_debug_info_test 739 @skipUnlessDarwin 740 def test_darwin_dwarf_missing_obj_with_symbol_ondemand_enabled(self): 741 """ 742 Test that if we build a binary with DWARF in .o files and we remove 743 the .o file for main.cpp, that we get a variable named "<error>" 744 whose value matches the appriopriate error. Test with symbol_ondemand_enabled. 745 """ 746 initCommands = ["settings set symbols.load-on-demand true"] 747 self.darwin_dwarf_missing_obj(initCommands) 748 749 @no_debug_info_test 750 @skipIfWindows 751 @skipIfRemote 752 def test_value_format(self): 753 """ 754 Test that toggle variables value format between decimal and hexical works. 755 """ 756 program = self.getBuildArtifact("a.out") 757 self.build_and_launch(program) 758 source = "main.cpp" 759 breakpoint1_line = line_number(source, "// breakpoint 1") 760 lines = [breakpoint1_line] 761 762 breakpoint_ids = self.set_source_breakpoints(source, lines) 763 self.assertEqual( 764 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 765 ) 766 self.continue_to_breakpoints(breakpoint_ids) 767 768 # Verify locals value format decimal 769 is_hex = False 770 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 771 self.assertEqual(var_pt_x["value"], "11") 772 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 773 self.assertEqual(var_pt_y["value"], "22") 774 775 # Verify locals value format hexical 776 is_hex = True 777 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 778 self.assertEqual(var_pt_x["value"], "0x0000000b") 779 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 780 self.assertEqual(var_pt_y["value"], "0x00000016") 781 782 # Toggle and verify locals value format decimal again 783 is_hex = False 784 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 785 self.assertEqual(var_pt_x["value"], "11") 786 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 787 self.assertEqual(var_pt_y["value"], "22") 788