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