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 "equals": { 506 "result": """(PointType) pt = { 507 x = 11 508 y = 22 509 buffer = { 510 [0] = 0 511 [1] = 1 512 [2] = 2 513 [3] = 3 514 [4] = 4 515 [5] = 5 516 [6] = 6 517 [7] = 7 518 [8] = 8 519 [9] = 9 520 [10] = 10 521 [11] = 11 522 [12] = 12 523 [13] = 13 524 [14] = 14 525 [15] = 15 526 } 527}""" 528 }, 529 "missing": ["indexedVariables"], 530 "hasVariablesReference": True, 531 }, 532 "watch": { 533 "equals": {"type": "PointType"}, 534 "startswith": { 535 "result": ( 536 "{x:11, y:22, buffer:{...}}" 537 if enableAutoVariableSummaries 538 else "PointType @ 0x" 539 ) 540 }, 541 "missing": ["indexedVariables"], 542 "hasVariablesReference": True, 543 }, 544 "variables": { 545 "equals": {"type": "PointType"}, 546 "startswith": { 547 "result": ( 548 "{x:11, y:22, buffer:{...}}" 549 if enableAutoVariableSummaries 550 else "PointType @ 0x" 551 ) 552 }, 553 "missing": ["indexedVariables"], 554 "hasVariablesReference": True, 555 }, 556 }, 557 "children": { 558 "x": {"equals": {"type": "int", "value": "11"}}, 559 "y": {"equals": {"type": "int", "value": "22"}}, 560 "buffer": {"children": buffer_children}, 561 }, 562 } 563 564 # Evaluate from known contexts. 565 expr_varref_dict = {} 566 for context, verify_dict in expandable_expression["context"].items(): 567 response = self.dap_server.request_evaluate( 568 expandable_expression["name"], 569 frameIndex=0, 570 threadId=None, 571 context=context, 572 ) 573 self.verify_values( 574 verify_dict, 575 response["body"], 576 expr_varref_dict, 577 expandable_expression["name"], 578 ) 579 580 # Evaluate locals again. 581 locals = self.dap_server.get_local_variables() 582 self.verify_variables(verify_locals, locals) 583 584 # Verify the evaluated expressions before second locals evaluation 585 # can be expanded. 586 var_ref = expr_varref_dict[expandable_expression["name"]] 587 response = self.dap_server.request_variables(var_ref) 588 self.verify_variables( 589 expandable_expression["children"], response["body"]["variables"] 590 ) 591 592 # Continue to breakpoint 3, permanent variable should still exist 593 # after resume. 594 breakpoint3_line = line_number(source, "// breakpoint 3") 595 lines = [breakpoint3_line] 596 breakpoint_ids = self.set_source_breakpoints(source, lines) 597 self.assertEqual( 598 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 599 ) 600 self.continue_to_breakpoints(breakpoint_ids) 601 602 var_ref = expr_varref_dict[expandable_expression["name"]] 603 response = self.dap_server.request_variables(var_ref) 604 self.verify_variables( 605 expandable_expression["children"], response["body"]["variables"] 606 ) 607 608 # Test that frame scopes have corresponding presentation hints. 609 frame_id = self.dap_server.get_stackFrame()["id"] 610 scopes = self.dap_server.request_scopes(frame_id)["body"]["scopes"] 611 612 scope_names = [scope["name"] for scope in scopes] 613 self.assertIn("Locals", scope_names) 614 self.assertIn("Registers", scope_names) 615 616 for scope in scopes: 617 if scope["name"] == "Locals": 618 self.assertEqual(scope.get("presentationHint"), "locals") 619 if scope["name"] == "Registers": 620 self.assertEqual(scope.get("presentationHint"), "registers") 621 622 @skipIfWindows 623 @skipIfRemote 624 def test_scopes_and_evaluate_expansion(self): 625 self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=False) 626 627 @skipIfWindows 628 @skipIfRemote 629 def test_scopes_and_evaluate_expansion_with_descriptive_summaries(self): 630 self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=True) 631 632 def do_test_indexedVariables(self, enableSyntheticChildDebugging: bool): 633 """ 634 Tests that arrays and lldb.SBValue objects that have synthetic child 635 providers have "indexedVariables" key/value pairs. This helps the IDE 636 not to fetch too many children all at once. 637 """ 638 program = self.getBuildArtifact("a.out") 639 self.build_and_launch( 640 program, enableSyntheticChildDebugging=enableSyntheticChildDebugging 641 ) 642 source = "main.cpp" 643 breakpoint1_line = line_number(source, "// breakpoint 4") 644 lines = [breakpoint1_line] 645 # Set breakpoint in the thread function so we can step the threads 646 breakpoint_ids = self.set_source_breakpoints(source, lines) 647 self.assertEqual( 648 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 649 ) 650 self.continue_to_breakpoints(breakpoint_ids) 651 652 # Verify locals 653 locals = self.dap_server.get_local_variables() 654 # The vector variables might have one additional entry from the fake 655 # "[raw]" child. 656 raw_child_count = 1 if enableSyntheticChildDebugging else 0 657 verify_locals = { 658 "small_array": {"equals": {"indexedVariables": 5}}, 659 "large_array": {"equals": {"indexedVariables": 200}}, 660 "small_vector": {"equals": {"indexedVariables": 5 + raw_child_count}}, 661 "large_vector": {"equals": {"indexedVariables": 200 + raw_child_count}}, 662 "pt": {"missing": ["indexedVariables"]}, 663 } 664 self.verify_variables(verify_locals, locals) 665 666 # We also verify that we produce a "[raw]" fake child with the real 667 # SBValue for the synthetic type. 668 verify_children = { 669 "[0]": {"equals": {"type": "int", "value": "0"}}, 670 "[1]": {"equals": {"type": "int", "value": "0"}}, 671 "[2]": {"equals": {"type": "int", "value": "0"}}, 672 "[3]": {"equals": {"type": "int", "value": "0"}}, 673 "[4]": {"equals": {"type": "int", "value": "0"}}, 674 } 675 if enableSyntheticChildDebugging: 676 verify_children["[raw]"] = ({"contains": {"type": ["vector"]}},) 677 678 children = self.dap_server.request_variables(locals[2]["variablesReference"])[ 679 "body" 680 ]["variables"] 681 self.verify_variables(verify_children, children) 682 683 @skipIfWindows 684 @skipIfRemote 685 def test_indexedVariables(self): 686 self.do_test_indexedVariables(enableSyntheticChildDebugging=False) 687 688 @skipIfWindows 689 @skipIfRemote 690 def test_indexedVariables_with_raw_child_for_synthetics(self): 691 self.do_test_indexedVariables(enableSyntheticChildDebugging=True) 692 693 @skipIfWindows 694 @skipIfRemote 695 def test_registers(self): 696 """ 697 Test that registers whose byte size is the size of a pointer on 698 the current system get formatted as lldb::eFormatAddressInfo. This 699 will show the pointer value followed by a description of the address 700 itself. To test this we attempt to find the PC value in the general 701 purpose registers, and since we will be stopped in main.cpp, verify 702 that the value for the PC starts with a pointer and is followed by 703 a description that contains main.cpp. 704 """ 705 program = self.getBuildArtifact("a.out") 706 self.build_and_launch(program) 707 source = "main.cpp" 708 breakpoint1_line = line_number(source, "// breakpoint 1") 709 lines = [breakpoint1_line] 710 # Set breakpoint in the thread function so we can step the threads 711 breakpoint_ids = self.set_source_breakpoints(source, lines) 712 self.assertEqual( 713 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 714 ) 715 self.continue_to_breakpoints(breakpoint_ids) 716 717 pc_name = None 718 arch = self.getArchitecture() 719 if arch == "x86_64": 720 pc_name = "rip" 721 elif arch == "x86": 722 pc_name = "rip" 723 elif arch.startswith("arm"): 724 pc_name = "pc" 725 726 if pc_name is None: 727 return 728 # Verify locals 729 reg_sets = self.dap_server.get_registers() 730 for reg_set in reg_sets: 731 if reg_set["name"] == "General Purpose Registers": 732 varRef = reg_set["variablesReference"] 733 regs = self.dap_server.request_variables(varRef)["body"]["variables"] 734 for reg in regs: 735 if reg["name"] == pc_name: 736 value = reg["value"] 737 self.assertTrue(value.startswith("0x")) 738 self.assertIn("a.out`main + ", value) 739 self.assertIn("at main.cpp:", value) 740 741 @no_debug_info_test 742 @skipUnlessDarwin 743 def test_darwin_dwarf_missing_obj(self): 744 """ 745 Test that if we build a binary with DWARF in .o files and we remove 746 the .o file for main.cpp, that we get a variable named "<error>" 747 whose value matches the appriopriate error. Errors when getting 748 variables are returned in the LLDB API when the user should be 749 notified of issues that can easily be solved by rebuilding or 750 changing compiler options and are designed to give better feedback 751 to the user. 752 """ 753 self.darwin_dwarf_missing_obj(None) 754 755 @no_debug_info_test 756 @skipUnlessDarwin 757 def test_darwin_dwarf_missing_obj_with_symbol_ondemand_enabled(self): 758 """ 759 Test that if we build a binary with DWARF in .o files and we remove 760 the .o file for main.cpp, that we get a variable named "<error>" 761 whose value matches the appriopriate error. Test with symbol_ondemand_enabled. 762 """ 763 initCommands = ["settings set symbols.load-on-demand true"] 764 self.darwin_dwarf_missing_obj(initCommands) 765 766 @no_debug_info_test 767 @skipIfWindows 768 @skipIfRemote 769 def test_value_format(self): 770 """ 771 Test that toggle variables value format between decimal and hexical works. 772 """ 773 program = self.getBuildArtifact("a.out") 774 self.build_and_launch(program) 775 source = "main.cpp" 776 breakpoint1_line = line_number(source, "// breakpoint 1") 777 lines = [breakpoint1_line] 778 779 breakpoint_ids = self.set_source_breakpoints(source, lines) 780 self.assertEqual( 781 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 782 ) 783 self.continue_to_breakpoints(breakpoint_ids) 784 785 # Verify locals value format decimal 786 is_hex = False 787 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 788 self.assertEqual(var_pt_x["value"], "11") 789 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 790 self.assertEqual(var_pt_y["value"], "22") 791 792 # Verify locals value format hexical 793 is_hex = True 794 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 795 self.assertEqual(var_pt_x["value"], "0x0000000b") 796 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 797 self.assertEqual(var_pt_y["value"], "0x00000016") 798 799 # Toggle and verify locals value format decimal again 800 is_hex = False 801 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 802 self.assertEqual(var_pt_x["value"], "11") 803 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 804 self.assertEqual(var_pt_y["value"], "22") 805