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 204 verify_globals = { 205 "s_local": {"equals": {"type": "float", "value": "2.25"}}, 206 } 207 s_global = {"equals": {"type": "int", "value": "234"}} 208 g_global = {"equals": {"type": "int", "value": "123"}} 209 if lldbplatformutil.getHostPlatform() == "windows": 210 verify_globals["::s_global"] = s_global 211 verify_globals["g_global"] = g_global 212 else: 213 verify_globals["s_global"] = s_global 214 verify_globals["::g_global"] = g_global 215 216 varref_dict = {} 217 self.verify_variables(verify_locals, locals, varref_dict) 218 self.verify_variables(verify_globals, globals, varref_dict) 219 # pprint.PrettyPrinter(indent=4).pprint(varref_dict) 220 # We need to test the functionality of the "variables" request as it 221 # has optional parameters like "start" and "count" to limit the number 222 # of variables that are fetched 223 varRef = varref_dict["pt.buffer"] 224 response = self.dap_server.request_variables(varRef) 225 self.verify_variables(buffer_children, response["body"]["variables"]) 226 # Verify setting start=0 in the arguments still gets all children 227 response = self.dap_server.request_variables(varRef, start=0) 228 self.verify_variables(buffer_children, response["body"]["variables"]) 229 # Verify setting count=0 in the arguments still gets all children. 230 # If count is zero, it means to get all children. 231 response = self.dap_server.request_variables(varRef, count=0) 232 self.verify_variables(buffer_children, response["body"]["variables"]) 233 # Verify setting count to a value that is too large in the arguments 234 # still gets all children, and no more 235 response = self.dap_server.request_variables(varRef, count=1000) 236 self.verify_variables(buffer_children, response["body"]["variables"]) 237 # Verify setting the start index and count gets only the children we 238 # want 239 response = self.dap_server.request_variables(varRef, start=5, count=5) 240 self.verify_variables( 241 make_buffer_verify_dict(5, 5), response["body"]["variables"] 242 ) 243 # Verify setting the start index to a value that is out of range 244 # results in an empty list 245 response = self.dap_server.request_variables(varRef, start=32, count=1) 246 self.assertEqual( 247 len(response["body"]["variables"]), 248 0, 249 "verify we get no variable back for invalid start", 250 ) 251 252 # Test evaluate 253 expressions = { 254 "pt.x": { 255 "equals": {"result": "11", "type": "int"}, 256 "hasVariablesReference": False, 257 }, 258 "pt.buffer[2]": { 259 "equals": {"result": "2", "type": "int"}, 260 "hasVariablesReference": False, 261 }, 262 "pt": { 263 "equals": {"type": "PointType"}, 264 "startswith": { 265 "result": ( 266 "{x:11, y:22, buffer:{...}}" 267 if enableAutoVariableSummaries 268 else "PointType @ 0x" 269 ) 270 }, 271 "hasVariablesReference": True, 272 }, 273 "pt.buffer": { 274 "equals": {"type": "int[16]"}, 275 "startswith": { 276 "result": ( 277 "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}" 278 if enableAutoVariableSummaries 279 else "int[16] @ 0x" 280 ) 281 }, 282 "hasVariablesReference": True, 283 }, 284 "argv": { 285 "equals": {"type": "const char **"}, 286 "startswith": {"result": "0x"}, 287 "hasVariablesReference": True, 288 }, 289 "argv[0]": { 290 "equals": {"type": "const char *"}, 291 "startswith": {"result": "0x"}, 292 "hasVariablesReference": True, 293 }, 294 "2+3": { 295 "equals": {"result": "5", "type": "int"}, 296 "hasVariablesReference": False, 297 }, 298 } 299 for expression in expressions: 300 response = self.dap_server.request_evaluate(expression) 301 self.verify_values(expressions[expression], response["body"]) 302 303 # Test setting variables 304 self.set_local("argc", 123) 305 argc = self.get_local_as_int("argc") 306 self.assertEqual(argc, 123, "verify argc was set to 123 (123 != %i)" % (argc)) 307 308 self.set_local("argv", 0x1234) 309 argv = self.get_local_as_int("argv") 310 self.assertEqual( 311 argv, 0x1234, "verify argv was set to 0x1234 (0x1234 != %#x)" % (argv) 312 ) 313 314 # Set a variable value whose name is synthetic, like a variable index 315 # and verify the value by reading it 316 self.dap_server.request_setVariable(varRef, "[0]", 100) 317 response = self.dap_server.request_variables(varRef, start=0, count=1) 318 self.verify_variables( 319 make_buffer_verify_dict(0, 1, 100), response["body"]["variables"] 320 ) 321 322 # Set a variable value whose name is a real child value, like "pt.x" 323 # and verify the value by reading it 324 varRef = varref_dict["pt"] 325 self.dap_server.request_setVariable(varRef, "x", 111) 326 response = self.dap_server.request_variables(varRef, start=0, count=1) 327 value = response["body"]["variables"][0]["value"] 328 self.assertEqual( 329 value, "111", "verify pt.x got set to 111 (111 != %s)" % (value) 330 ) 331 332 # We check shadowed variables and that a new get_local_variables request 333 # gets the right data 334 breakpoint2_line = line_number(source, "// breakpoint 2") 335 lines = [breakpoint2_line] 336 breakpoint_ids = self.set_source_breakpoints(source, lines) 337 self.assertEqual( 338 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 339 ) 340 self.continue_to_breakpoints(breakpoint_ids) 341 342 verify_locals["argc"]["equals"]["value"] = "123" 343 verify_locals["pt"]["children"]["x"]["equals"]["value"] = "111" 344 verify_locals["x @ main.cpp:17"] = {"equals": {"type": "int", "value": "89"}} 345 verify_locals["x @ main.cpp:19"] = {"equals": {"type": "int", "value": "42"}} 346 verify_locals["x @ main.cpp:21"] = {"equals": {"type": "int", "value": "72"}} 347 348 self.verify_variables(verify_locals, self.dap_server.get_local_variables()) 349 350 # Now we verify that we correctly change the name of a variable with and without differentiator suffix 351 self.assertFalse(self.dap_server.request_setVariable(1, "x2", 9)["success"]) 352 self.assertFalse( 353 self.dap_server.request_setVariable(1, "x @ main.cpp:0", 9)["success"] 354 ) 355 356 self.assertTrue( 357 self.dap_server.request_setVariable(1, "x @ main.cpp:17", 17)["success"] 358 ) 359 self.assertTrue( 360 self.dap_server.request_setVariable(1, "x @ main.cpp:19", 19)["success"] 361 ) 362 self.assertTrue( 363 self.dap_server.request_setVariable(1, "x @ main.cpp:21", 21)["success"] 364 ) 365 366 # The following should have no effect 367 self.assertFalse( 368 self.dap_server.request_setVariable(1, "x @ main.cpp:21", "invalid")[ 369 "success" 370 ] 371 ) 372 373 verify_locals["x @ main.cpp:17"]["equals"]["value"] = "17" 374 verify_locals["x @ main.cpp:19"]["equals"]["value"] = "19" 375 verify_locals["x @ main.cpp:21"]["equals"]["value"] = "21" 376 377 self.verify_variables(verify_locals, self.dap_server.get_local_variables()) 378 379 # The plain x variable shold refer to the innermost x 380 self.assertTrue(self.dap_server.request_setVariable(1, "x", 22)["success"]) 381 verify_locals["x @ main.cpp:21"]["equals"]["value"] = "22" 382 383 self.verify_variables(verify_locals, self.dap_server.get_local_variables()) 384 385 # In breakpoint 3, there should be no shadowed variables 386 breakpoint3_line = line_number(source, "// breakpoint 3") 387 lines = [breakpoint3_line] 388 breakpoint_ids = self.set_source_breakpoints(source, lines) 389 self.assertEqual( 390 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 391 ) 392 self.continue_to_breakpoints(breakpoint_ids) 393 394 locals = self.dap_server.get_local_variables() 395 names = [var["name"] for var in locals] 396 # The first shadowed x shouldn't have a suffix anymore 397 verify_locals["x"] = {"equals": {"type": "int", "value": "17"}} 398 self.assertNotIn("x @ main.cpp:17", names) 399 self.assertNotIn("x @ main.cpp:19", names) 400 self.assertNotIn("x @ main.cpp:21", names) 401 402 self.verify_variables(verify_locals, locals) 403 404 def test_scopes_variables_setVariable_evaluate(self): 405 self.do_test_scopes_variables_setVariable_evaluate( 406 enableAutoVariableSummaries=False 407 ) 408 409 def test_scopes_variables_setVariable_evaluate_with_descriptive_summaries(self): 410 self.do_test_scopes_variables_setVariable_evaluate( 411 enableAutoVariableSummaries=True 412 ) 413 414 def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: bool): 415 """ 416 Tests the evaluated expression expands successfully after "scopes" packets 417 and permanent expressions persist. 418 """ 419 program = self.getBuildArtifact("a.out") 420 self.build_and_launch( 421 program, enableAutoVariableSummaries=enableAutoVariableSummaries 422 ) 423 source = "main.cpp" 424 breakpoint1_line = line_number(source, "// breakpoint 1") 425 lines = [breakpoint1_line] 426 # Set breakpoint in the thread function so we can step the threads 427 breakpoint_ids = self.set_source_breakpoints(source, lines) 428 self.assertEqual( 429 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 430 ) 431 self.continue_to_breakpoints(breakpoint_ids) 432 433 # Verify locals 434 locals = self.dap_server.get_local_variables() 435 buffer_children = make_buffer_verify_dict(0, 32) 436 verify_locals = { 437 "argc": { 438 "equals": {"type": "int", "value": "1"}, 439 "missing": ["indexedVariables"], 440 }, 441 "argv": { 442 "equals": {"type": "const char **"}, 443 "startswith": {"value": "0x"}, 444 "hasVariablesReference": True, 445 "missing": ["indexedVariables"], 446 }, 447 "pt": { 448 "equals": {"type": "PointType"}, 449 "hasVariablesReference": True, 450 "missing": ["indexedVariables"], 451 "children": { 452 "x": { 453 "equals": {"type": "int", "value": "11"}, 454 "missing": ["indexedVariables"], 455 }, 456 "y": { 457 "equals": {"type": "int", "value": "22"}, 458 "missing": ["indexedVariables"], 459 }, 460 "buffer": { 461 "children": buffer_children, 462 "equals": {"indexedVariables": 16}, 463 }, 464 }, 465 }, 466 "x": { 467 "equals": {"type": "int"}, 468 "missing": ["indexedVariables"], 469 }, 470 } 471 self.verify_variables(verify_locals, locals) 472 473 # Evaluate expandable expression twice: once permanent (from repl) 474 # the other temporary (from other UI). 475 expandable_expression = { 476 "name": "pt", 477 "context": { 478 "repl": { 479 "equals": {"type": "PointType"}, 480 "equals": { 481 "result": """(PointType) $0 = { 482 x = 11 483 y = 22 484 buffer = { 485 [0] = 0 486 [1] = 1 487 [2] = 2 488 [3] = 3 489 [4] = 4 490 [5] = 5 491 [6] = 6 492 [7] = 7 493 [8] = 8 494 [9] = 9 495 [10] = 10 496 [11] = 11 497 [12] = 12 498 [13] = 13 499 [14] = 14 500 [15] = 15 501 } 502}""" 503 }, 504 "missing": ["indexedVariables"], 505 "hasVariablesReference": True, 506 }, 507 "hover": { 508 "equals": {"type": "PointType"}, 509 "startswith": { 510 "result": ( 511 "{x:11, y:22, buffer:{...}}" 512 if enableAutoVariableSummaries 513 else "PointType @ 0x" 514 ) 515 }, 516 "missing": ["indexedVariables"], 517 "hasVariablesReference": True, 518 }, 519 "watch": { 520 "equals": {"type": "PointType"}, 521 "startswith": { 522 "result": ( 523 "{x:11, y:22, buffer:{...}}" 524 if enableAutoVariableSummaries 525 else "PointType @ 0x" 526 ) 527 }, 528 "missing": ["indexedVariables"], 529 "hasVariablesReference": True, 530 }, 531 "variables": { 532 "equals": {"type": "PointType"}, 533 "startswith": { 534 "result": ( 535 "{x:11, y:22, buffer:{...}}" 536 if enableAutoVariableSummaries 537 else "PointType @ 0x" 538 ) 539 }, 540 "missing": ["indexedVariables"], 541 "hasVariablesReference": True, 542 }, 543 }, 544 "children": { 545 "x": {"equals": {"type": "int", "value": "11"}}, 546 "y": {"equals": {"type": "int", "value": "22"}}, 547 "buffer": {"children": buffer_children}, 548 }, 549 } 550 551 # Evaluate from known contexts. 552 expr_varref_dict = {} 553 for context, verify_dict in expandable_expression["context"].items(): 554 response = self.dap_server.request_evaluate( 555 expandable_expression["name"], 556 frameIndex=0, 557 threadId=None, 558 context=context, 559 ) 560 self.verify_values( 561 verify_dict, 562 response["body"], 563 expr_varref_dict, 564 expandable_expression["name"], 565 ) 566 567 # Evaluate locals again. 568 locals = self.dap_server.get_local_variables() 569 self.verify_variables(verify_locals, locals) 570 571 # Verify the evaluated expressions before second locals evaluation 572 # can be expanded. 573 var_ref = expr_varref_dict[expandable_expression["name"]] 574 response = self.dap_server.request_variables(var_ref) 575 self.verify_variables( 576 expandable_expression["children"], response["body"]["variables"] 577 ) 578 579 # Continue to breakpoint 3, permanent variable should still exist 580 # after resume. 581 breakpoint3_line = line_number(source, "// breakpoint 3") 582 lines = [breakpoint3_line] 583 breakpoint_ids = self.set_source_breakpoints(source, lines) 584 self.assertEqual( 585 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 586 ) 587 self.continue_to_breakpoints(breakpoint_ids) 588 589 var_ref = expr_varref_dict[expandable_expression["name"]] 590 response = self.dap_server.request_variables(var_ref) 591 self.verify_variables( 592 expandable_expression["children"], response["body"]["variables"] 593 ) 594 595 # Test that frame scopes have corresponding presentation hints. 596 frame_id = self.dap_server.get_stackFrame()["id"] 597 scopes = self.dap_server.request_scopes(frame_id)["body"]["scopes"] 598 599 scope_names = [scope["name"] for scope in scopes] 600 self.assertIn("Locals", scope_names) 601 self.assertIn("Registers", scope_names) 602 603 for scope in scopes: 604 if scope["name"] == "Locals": 605 self.assertEqual(scope.get("presentationHint"), "locals") 606 if scope["name"] == "Registers": 607 self.assertEqual(scope.get("presentationHint"), "registers") 608 609 def test_scopes_and_evaluate_expansion(self): 610 self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=False) 611 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 def test_indexedVariables(self): 668 self.do_test_indexedVariables(enableSyntheticChildDebugging=False) 669 670 @skipIfWindows 671 def test_indexedVariables_with_raw_child_for_synthetics(self): 672 self.do_test_indexedVariables(enableSyntheticChildDebugging=True) 673 674 @skipIfWindows 675 @skipIfAsan # FIXME this fails with a non-asan issue on green dragon. 676 def test_registers(self): 677 """ 678 Test that registers whose byte size is the size of a pointer on 679 the current system get formatted as lldb::eFormatAddressInfo. This 680 will show the pointer value followed by a description of the address 681 itself. To test this we attempt to find the PC value in the general 682 purpose registers, and since we will be stopped in main.cpp, verify 683 that the value for the PC starts with a pointer and is followed by 684 a description that contains main.cpp. 685 """ 686 program = self.getBuildArtifact("a.out") 687 self.build_and_launch(program) 688 source = "main.cpp" 689 breakpoint1_line = line_number(source, "// breakpoint 1") 690 lines = [breakpoint1_line] 691 # Set breakpoint in the thread function so we can step the threads 692 breakpoint_ids = self.set_source_breakpoints(source, lines) 693 self.assertEqual( 694 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 695 ) 696 self.continue_to_breakpoints(breakpoint_ids) 697 698 pc_name = None 699 arch = self.getArchitecture() 700 if arch == "x86_64": 701 pc_name = "rip" 702 elif arch == "x86": 703 pc_name = "rip" 704 elif arch.startswith("arm"): 705 pc_name = "pc" 706 707 if pc_name is None: 708 return 709 # Verify locals 710 reg_sets = self.dap_server.get_registers() 711 for reg_set in reg_sets: 712 if reg_set["name"] == "General Purpose Registers": 713 varRef = reg_set["variablesReference"] 714 regs = self.dap_server.request_variables(varRef)["body"]["variables"] 715 for reg in regs: 716 if reg["name"] == pc_name: 717 value = reg["value"] 718 self.assertTrue(value.startswith("0x")) 719 self.assertIn("a.out`main + ", value) 720 self.assertIn("at main.cpp:", value) 721 722 @no_debug_info_test 723 @skipUnlessDarwin 724 def test_darwin_dwarf_missing_obj(self): 725 """ 726 Test that if we build a binary with DWARF in .o files and we remove 727 the .o file for main.cpp, that we get a variable named "<error>" 728 whose value matches the appriopriate error. Errors when getting 729 variables are returned in the LLDB API when the user should be 730 notified of issues that can easily be solved by rebuilding or 731 changing compiler options and are designed to give better feedback 732 to the user. 733 """ 734 self.darwin_dwarf_missing_obj(None) 735 736 @no_debug_info_test 737 @skipUnlessDarwin 738 def test_darwin_dwarf_missing_obj_with_symbol_ondemand_enabled(self): 739 """ 740 Test that if we build a binary with DWARF in .o files and we remove 741 the .o file for main.cpp, that we get a variable named "<error>" 742 whose value matches the appriopriate error. Test with symbol_ondemand_enabled. 743 """ 744 initCommands = ["settings set symbols.load-on-demand true"] 745 self.darwin_dwarf_missing_obj(initCommands) 746 747 @no_debug_info_test 748 @skipIfWindows 749 def test_value_format(self): 750 """ 751 Test that toggle variables value format between decimal and hexical works. 752 """ 753 program = self.getBuildArtifact("a.out") 754 self.build_and_launch(program) 755 source = "main.cpp" 756 breakpoint1_line = line_number(source, "// breakpoint 1") 757 lines = [breakpoint1_line] 758 759 breakpoint_ids = self.set_source_breakpoints(source, lines) 760 self.assertEqual( 761 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 762 ) 763 self.continue_to_breakpoints(breakpoint_ids) 764 765 # Verify locals value format decimal 766 is_hex = False 767 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 768 self.assertEqual(var_pt_x["value"], "11") 769 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 770 self.assertEqual(var_pt_y["value"], "22") 771 772 # Verify locals value format hexical 773 is_hex = True 774 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 775 self.assertEqual(var_pt_x["value"], "0x0000000b") 776 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 777 self.assertEqual(var_pt_y["value"], "0x00000016") 778 779 # Toggle and verify locals value format decimal again 780 is_hex = False 781 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 782 self.assertEqual(var_pt_x["value"], "11") 783 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 784 self.assertEqual(var_pt_y["value"], "22") 785