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 def test_scopes_variables_setVariable_evaluate(self): 398 self.do_test_scopes_variables_setVariable_evaluate( 399 enableAutoVariableSummaries=False 400 ) 401 402 @skipIfWindows 403 def test_scopes_variables_setVariable_evaluate_with_descriptive_summaries(self): 404 self.do_test_scopes_variables_setVariable_evaluate( 405 enableAutoVariableSummaries=True 406 ) 407 408 def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: bool): 409 """ 410 Tests the evaluated expression expands successfully after "scopes" packets 411 and permanent expressions persist. 412 """ 413 program = self.getBuildArtifact("a.out") 414 self.build_and_launch( 415 program, enableAutoVariableSummaries=enableAutoVariableSummaries 416 ) 417 source = "main.cpp" 418 breakpoint1_line = line_number(source, "// breakpoint 1") 419 lines = [breakpoint1_line] 420 # Set breakpoint in the thread function so we can step the threads 421 breakpoint_ids = self.set_source_breakpoints(source, lines) 422 self.assertEqual( 423 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 424 ) 425 self.continue_to_breakpoints(breakpoint_ids) 426 427 # Verify locals 428 locals = self.dap_server.get_local_variables() 429 buffer_children = make_buffer_verify_dict(0, 32) 430 verify_locals = { 431 "argc": { 432 "equals": {"type": "int", "value": "1"}, 433 "missing": ["indexedVariables"], 434 }, 435 "argv": { 436 "equals": {"type": "const char **"}, 437 "startswith": {"value": "0x"}, 438 "hasVariablesReference": True, 439 "missing": ["indexedVariables"], 440 }, 441 "pt": { 442 "equals": {"type": "PointType"}, 443 "hasVariablesReference": True, 444 "missing": ["indexedVariables"], 445 "children": { 446 "x": { 447 "equals": {"type": "int", "value": "11"}, 448 "missing": ["indexedVariables"], 449 }, 450 "y": { 451 "equals": {"type": "int", "value": "22"}, 452 "missing": ["indexedVariables"], 453 }, 454 "buffer": { 455 "children": buffer_children, 456 "equals": {"indexedVariables": 16}, 457 }, 458 }, 459 }, 460 "x": { 461 "equals": {"type": "int"}, 462 "missing": ["indexedVariables"], 463 }, 464 } 465 self.verify_variables(verify_locals, locals) 466 467 # Evaluate expandable expression twice: once permanent (from repl) 468 # the other temporary (from other UI). 469 expandable_expression = { 470 "name": "pt", 471 "context": { 472 "repl": { 473 "equals": {"type": "PointType"}, 474 "equals": { 475 "result": """(PointType) $0 = { 476 x = 11 477 y = 22 478 buffer = { 479 [0] = 0 480 [1] = 1 481 [2] = 2 482 [3] = 3 483 [4] = 4 484 [5] = 5 485 [6] = 6 486 [7] = 7 487 [8] = 8 488 [9] = 9 489 [10] = 10 490 [11] = 11 491 [12] = 12 492 [13] = 13 493 [14] = 14 494 [15] = 15 495 } 496}""" 497 }, 498 "missing": ["indexedVariables"], 499 "hasVariablesReference": True, 500 }, 501 "hover": { 502 "equals": {"type": "PointType"}, 503 "startswith": { 504 "result": ( 505 "{x:11, y:22, buffer:{...}}" 506 if enableAutoVariableSummaries 507 else "PointType @ 0x" 508 ) 509 }, 510 "missing": ["indexedVariables"], 511 "hasVariablesReference": True, 512 }, 513 "watch": { 514 "equals": {"type": "PointType"}, 515 "startswith": { 516 "result": ( 517 "{x:11, y:22, buffer:{...}}" 518 if enableAutoVariableSummaries 519 else "PointType @ 0x" 520 ) 521 }, 522 "missing": ["indexedVariables"], 523 "hasVariablesReference": True, 524 }, 525 "variables": { 526 "equals": {"type": "PointType"}, 527 "startswith": { 528 "result": ( 529 "{x:11, y:22, buffer:{...}}" 530 if enableAutoVariableSummaries 531 else "PointType @ 0x" 532 ) 533 }, 534 "missing": ["indexedVariables"], 535 "hasVariablesReference": True, 536 }, 537 }, 538 "children": { 539 "x": {"equals": {"type": "int", "value": "11"}}, 540 "y": {"equals": {"type": "int", "value": "22"}}, 541 "buffer": {"children": buffer_children}, 542 }, 543 } 544 545 # Evaluate from known contexts. 546 expr_varref_dict = {} 547 for context, verify_dict in expandable_expression["context"].items(): 548 response = self.dap_server.request_evaluate( 549 expandable_expression["name"], 550 frameIndex=0, 551 threadId=None, 552 context=context, 553 ) 554 self.verify_values( 555 verify_dict, 556 response["body"], 557 expr_varref_dict, 558 expandable_expression["name"], 559 ) 560 561 # Evaluate locals again. 562 locals = self.dap_server.get_local_variables() 563 self.verify_variables(verify_locals, locals) 564 565 # Verify the evaluated expressions before second locals evaluation 566 # can be expanded. 567 var_ref = expr_varref_dict[expandable_expression["name"]] 568 response = self.dap_server.request_variables(var_ref) 569 self.verify_variables( 570 expandable_expression["children"], response["body"]["variables"] 571 ) 572 573 # Continue to breakpoint 3, permanent variable should still exist 574 # after resume. 575 breakpoint3_line = line_number(source, "// breakpoint 3") 576 lines = [breakpoint3_line] 577 breakpoint_ids = self.set_source_breakpoints(source, lines) 578 self.assertEqual( 579 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 580 ) 581 self.continue_to_breakpoints(breakpoint_ids) 582 583 var_ref = expr_varref_dict[expandable_expression["name"]] 584 response = self.dap_server.request_variables(var_ref) 585 self.verify_variables( 586 expandable_expression["children"], response["body"]["variables"] 587 ) 588 589 # Test that frame scopes have corresponding presentation hints. 590 frame_id = self.dap_server.get_stackFrame()["id"] 591 scopes = self.dap_server.request_scopes(frame_id)["body"]["scopes"] 592 593 scope_names = [scope["name"] for scope in scopes] 594 self.assertIn("Locals", scope_names) 595 self.assertIn("Registers", scope_names) 596 597 for scope in scopes: 598 if scope["name"] == "Locals": 599 self.assertEqual(scope.get("presentationHint"), "locals") 600 if scope["name"] == "Registers": 601 self.assertEqual(scope.get("presentationHint"), "registers") 602 603 @skipIfWindows 604 def test_scopes_and_evaluate_expansion(self): 605 self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=False) 606 607 @skipIfWindows 608 def test_scopes_and_evaluate_expansion_with_descriptive_summaries(self): 609 self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=True) 610 611 def do_test_indexedVariables(self, enableSyntheticChildDebugging: bool): 612 """ 613 Tests that arrays and lldb.SBValue objects that have synthetic child 614 providers have "indexedVariables" key/value pairs. This helps the IDE 615 not to fetch too many children all at once. 616 """ 617 program = self.getBuildArtifact("a.out") 618 self.build_and_launch( 619 program, enableSyntheticChildDebugging=enableSyntheticChildDebugging 620 ) 621 source = "main.cpp" 622 breakpoint1_line = line_number(source, "// breakpoint 4") 623 lines = [breakpoint1_line] 624 # Set breakpoint in the thread function so we can step the threads 625 breakpoint_ids = self.set_source_breakpoints(source, lines) 626 self.assertEqual( 627 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 628 ) 629 self.continue_to_breakpoints(breakpoint_ids) 630 631 # Verify locals 632 locals = self.dap_server.get_local_variables() 633 # The vector variables might have one additional entry from the fake 634 # "[raw]" child. 635 raw_child_count = 1 if enableSyntheticChildDebugging else 0 636 verify_locals = { 637 "small_array": {"equals": {"indexedVariables": 5}}, 638 "large_array": {"equals": {"indexedVariables": 200}}, 639 "small_vector": {"equals": {"indexedVariables": 5 + raw_child_count}}, 640 "large_vector": {"equals": {"indexedVariables": 200 + raw_child_count}}, 641 "pt": {"missing": ["indexedVariables"]}, 642 } 643 self.verify_variables(verify_locals, locals) 644 645 # We also verify that we produce a "[raw]" fake child with the real 646 # SBValue for the synthetic type. 647 verify_children = { 648 "[0]": {"equals": {"type": "int", "value": "0"}}, 649 "[1]": {"equals": {"type": "int", "value": "0"}}, 650 "[2]": {"equals": {"type": "int", "value": "0"}}, 651 "[3]": {"equals": {"type": "int", "value": "0"}}, 652 "[4]": {"equals": {"type": "int", "value": "0"}}, 653 } 654 if enableSyntheticChildDebugging: 655 verify_children["[raw]"] = ({"contains": {"type": ["vector"]}},) 656 657 children = self.dap_server.request_variables(locals[2]["variablesReference"])[ 658 "body" 659 ]["variables"] 660 self.verify_variables(verify_children, children) 661 662 @skipIfWindows 663 def test_indexedVariables(self): 664 self.do_test_indexedVariables(enableSyntheticChildDebugging=False) 665 666 @skipIfWindows 667 def test_indexedVariables_with_raw_child_for_synthetics(self): 668 self.do_test_indexedVariables(enableSyntheticChildDebugging=True) 669 670 @skipIfWindows 671 def test_registers(self): 672 """ 673 Test that registers whose byte size is the size of a pointer on 674 the current system get formatted as lldb::eFormatAddressInfo. This 675 will show the pointer value followed by a description of the address 676 itself. To test this we attempt to find the PC value in the general 677 purpose registers, and since we will be stopped in main.cpp, verify 678 that the value for the PC starts with a pointer and is followed by 679 a description that contains main.cpp. 680 """ 681 program = self.getBuildArtifact("a.out") 682 self.build_and_launch(program) 683 source = "main.cpp" 684 breakpoint1_line = line_number(source, "// breakpoint 1") 685 lines = [breakpoint1_line] 686 # Set breakpoint in the thread function so we can step the threads 687 breakpoint_ids = self.set_source_breakpoints(source, lines) 688 self.assertEqual( 689 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 690 ) 691 self.continue_to_breakpoints(breakpoint_ids) 692 693 pc_name = None 694 arch = self.getArchitecture() 695 if arch == "x86_64": 696 pc_name = "rip" 697 elif arch == "x86": 698 pc_name = "rip" 699 elif arch.startswith("arm"): 700 pc_name = "pc" 701 702 if pc_name is None: 703 return 704 # Verify locals 705 reg_sets = self.dap_server.get_registers() 706 for reg_set in reg_sets: 707 if reg_set["name"] == "General Purpose Registers": 708 varRef = reg_set["variablesReference"] 709 regs = self.dap_server.request_variables(varRef)["body"]["variables"] 710 for reg in regs: 711 if reg["name"] == pc_name: 712 value = reg["value"] 713 self.assertTrue(value.startswith("0x")) 714 self.assertIn("a.out`main + ", value) 715 self.assertIn("at main.cpp:", value) 716 717 @no_debug_info_test 718 @skipUnlessDarwin 719 def test_darwin_dwarf_missing_obj(self): 720 """ 721 Test that if we build a binary with DWARF in .o files and we remove 722 the .o file for main.cpp, that we get a variable named "<error>" 723 whose value matches the appriopriate error. Errors when getting 724 variables are returned in the LLDB API when the user should be 725 notified of issues that can easily be solved by rebuilding or 726 changing compiler options and are designed to give better feedback 727 to the user. 728 """ 729 self.darwin_dwarf_missing_obj(None) 730 731 @no_debug_info_test 732 @skipUnlessDarwin 733 def test_darwin_dwarf_missing_obj_with_symbol_ondemand_enabled(self): 734 """ 735 Test that if we build a binary with DWARF in .o files and we remove 736 the .o file for main.cpp, that we get a variable named "<error>" 737 whose value matches the appriopriate error. Test with symbol_ondemand_enabled. 738 """ 739 initCommands = ["settings set symbols.load-on-demand true"] 740 self.darwin_dwarf_missing_obj(initCommands) 741 742 @no_debug_info_test 743 @skipIfWindows 744 def test_value_format(self): 745 """ 746 Test that toggle variables value format between decimal and hexical works. 747 """ 748 program = self.getBuildArtifact("a.out") 749 self.build_and_launch(program) 750 source = "main.cpp" 751 breakpoint1_line = line_number(source, "// breakpoint 1") 752 lines = [breakpoint1_line] 753 754 breakpoint_ids = self.set_source_breakpoints(source, lines) 755 self.assertEqual( 756 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 757 ) 758 self.continue_to_breakpoints(breakpoint_ids) 759 760 # Verify locals value format decimal 761 is_hex = False 762 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 763 self.assertEqual(var_pt_x["value"], "11") 764 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 765 self.assertEqual(var_pt_y["value"], "22") 766 767 # Verify locals value format hexical 768 is_hex = True 769 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 770 self.assertEqual(var_pt_x["value"], "0x0000000b") 771 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 772 self.assertEqual(var_pt_y["value"], "0x00000016") 773 774 # Toggle and verify locals value format decimal again 775 is_hex = False 776 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 777 self.assertEqual(var_pt_x["value"], "11") 778 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 779 self.assertEqual(var_pt_y["value"], "22") 780