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