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