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": "{x:11, y:22, buffer:{...}}" 258 if enableAutoVariableSummaries 259 else "PointType @ 0x" 260 }, 261 "hasVariablesReference": True, 262 }, 263 "pt.buffer": { 264 "equals": {"type": "int[16]"}, 265 "startswith": { 266 "result": "{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...}" 267 if enableAutoVariableSummaries 268 else "int[16] @ 0x" 269 }, 270 "hasVariablesReference": True, 271 }, 272 "argv": { 273 "equals": {"type": "const char **"}, 274 "startswith": {"result": "0x"}, 275 "hasVariablesReference": True, 276 }, 277 "argv[0]": { 278 "equals": {"type": "const char *"}, 279 "startswith": {"result": "0x"}, 280 "hasVariablesReference": True, 281 }, 282 "2+3": { 283 "equals": {"result": "5", "type": "int"}, 284 "hasVariablesReference": False, 285 }, 286 } 287 for expression in expressions: 288 response = self.dap_server.request_evaluate(expression) 289 self.verify_values(expressions[expression], response["body"]) 290 291 # Test setting variables 292 self.set_local("argc", 123) 293 argc = self.get_local_as_int("argc") 294 self.assertEqual(argc, 123, "verify argc was set to 123 (123 != %i)" % (argc)) 295 296 self.set_local("argv", 0x1234) 297 argv = self.get_local_as_int("argv") 298 self.assertEqual( 299 argv, 0x1234, "verify argv was set to 0x1234 (0x1234 != %#x)" % (argv) 300 ) 301 302 # Set a variable value whose name is synthetic, like a variable index 303 # and verify the value by reading it 304 self.dap_server.request_setVariable(varRef, "[0]", 100) 305 response = self.dap_server.request_variables(varRef, start=0, count=1) 306 self.verify_variables( 307 make_buffer_verify_dict(0, 1, 100), response["body"]["variables"] 308 ) 309 310 # Set a variable value whose name is a real child value, like "pt.x" 311 # and verify the value by reading it 312 varRef = varref_dict["pt"] 313 self.dap_server.request_setVariable(varRef, "x", 111) 314 response = self.dap_server.request_variables(varRef, start=0, count=1) 315 value = response["body"]["variables"][0]["value"] 316 self.assertEqual( 317 value, "111", "verify pt.x got set to 111 (111 != %s)" % (value) 318 ) 319 320 # We check shadowed variables and that a new get_local_variables request 321 # gets the right data 322 breakpoint2_line = line_number(source, "// breakpoint 2") 323 lines = [breakpoint2_line] 324 breakpoint_ids = self.set_source_breakpoints(source, lines) 325 self.assertEqual( 326 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 327 ) 328 self.continue_to_breakpoints(breakpoint_ids) 329 330 verify_locals["argc"]["equals"]["value"] = "123" 331 verify_locals["pt"]["children"]["x"]["equals"]["value"] = "111" 332 verify_locals["x @ main.cpp:17"] = {"equals": {"type": "int", "value": "89"}} 333 verify_locals["x @ main.cpp:19"] = {"equals": {"type": "int", "value": "42"}} 334 verify_locals["x @ main.cpp:21"] = {"equals": {"type": "int", "value": "72"}} 335 336 self.verify_variables(verify_locals, self.dap_server.get_local_variables()) 337 338 # Now we verify that we correctly change the name of a variable with and without differentiator suffix 339 self.assertFalse(self.dap_server.request_setVariable(1, "x2", 9)["success"]) 340 self.assertFalse( 341 self.dap_server.request_setVariable(1, "x @ main.cpp:0", 9)["success"] 342 ) 343 344 self.assertTrue( 345 self.dap_server.request_setVariable(1, "x @ main.cpp:17", 17)["success"] 346 ) 347 self.assertTrue( 348 self.dap_server.request_setVariable(1, "x @ main.cpp:19", 19)["success"] 349 ) 350 self.assertTrue( 351 self.dap_server.request_setVariable(1, "x @ main.cpp:21", 21)["success"] 352 ) 353 354 # The following should have no effect 355 self.assertFalse( 356 self.dap_server.request_setVariable(1, "x @ main.cpp:21", "invalid")[ 357 "success" 358 ] 359 ) 360 361 verify_locals["x @ main.cpp:17"]["equals"]["value"] = "17" 362 verify_locals["x @ main.cpp:19"]["equals"]["value"] = "19" 363 verify_locals["x @ main.cpp:21"]["equals"]["value"] = "21" 364 365 self.verify_variables(verify_locals, self.dap_server.get_local_variables()) 366 367 # The plain x variable shold refer to the innermost x 368 self.assertTrue(self.dap_server.request_setVariable(1, "x", 22)["success"]) 369 verify_locals["x @ main.cpp:21"]["equals"]["value"] = "22" 370 371 self.verify_variables(verify_locals, self.dap_server.get_local_variables()) 372 373 # In breakpoint 3, there should be no shadowed variables 374 breakpoint3_line = line_number(source, "// breakpoint 3") 375 lines = [breakpoint3_line] 376 breakpoint_ids = self.set_source_breakpoints(source, lines) 377 self.assertEqual( 378 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 379 ) 380 self.continue_to_breakpoints(breakpoint_ids) 381 382 locals = self.dap_server.get_local_variables() 383 names = [var["name"] for var in locals] 384 # The first shadowed x shouldn't have a suffix anymore 385 verify_locals["x"] = {"equals": {"type": "int", "value": "17"}} 386 self.assertNotIn("x @ main.cpp:17", names) 387 self.assertNotIn("x @ main.cpp:19", names) 388 self.assertNotIn("x @ main.cpp:21", names) 389 390 self.verify_variables(verify_locals, locals) 391 392 @skipIfWindows 393 @skipIfRemote 394 def test_scopes_variables_setVariable_evaluate(self): 395 self.do_test_scopes_variables_setVariable_evaluate( 396 enableAutoVariableSummaries=False 397 ) 398 399 @skipIfWindows 400 @skipIfRemote 401 def test_scopes_variables_setVariable_evaluate_with_descriptive_summaries(self): 402 self.do_test_scopes_variables_setVariable_evaluate( 403 enableAutoVariableSummaries=True 404 ) 405 406 def do_test_scopes_and_evaluate_expansion(self, enableAutoVariableSummaries: bool): 407 """ 408 Tests the evaluated expression expands successfully after "scopes" packets 409 and permanent expressions persist. 410 """ 411 program = self.getBuildArtifact("a.out") 412 self.build_and_launch( 413 program, enableAutoVariableSummaries=enableAutoVariableSummaries 414 ) 415 source = "main.cpp" 416 breakpoint1_line = line_number(source, "// breakpoint 1") 417 lines = [breakpoint1_line] 418 # Set breakpoint in the thread function so we can step the threads 419 breakpoint_ids = self.set_source_breakpoints(source, lines) 420 self.assertEqual( 421 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 422 ) 423 self.continue_to_breakpoints(breakpoint_ids) 424 425 # Verify locals 426 locals = self.dap_server.get_local_variables() 427 buffer_children = make_buffer_verify_dict(0, 32) 428 verify_locals = { 429 "argc": { 430 "equals": {"type": "int", "value": "1"}, 431 "missing": ["indexedVariables"], 432 }, 433 "argv": { 434 "equals": {"type": "const char **"}, 435 "startswith": {"value": "0x"}, 436 "hasVariablesReference": True, 437 "missing": ["indexedVariables"], 438 }, 439 "pt": { 440 "equals": {"type": "PointType"}, 441 "hasVariablesReference": True, 442 "missing": ["indexedVariables"], 443 "children": { 444 "x": { 445 "equals": {"type": "int", "value": "11"}, 446 "missing": ["indexedVariables"], 447 }, 448 "y": { 449 "equals": {"type": "int", "value": "22"}, 450 "missing": ["indexedVariables"], 451 }, 452 "buffer": { 453 "children": buffer_children, 454 "equals": {"indexedVariables": 16}, 455 }, 456 }, 457 }, 458 "x": { 459 "equals": {"type": "int"}, 460 "missing": ["indexedVariables"], 461 }, 462 } 463 self.verify_variables(verify_locals, locals) 464 465 # Evaluate expandable expression twice: once permanent (from repl) 466 # the other temporary (from other UI). 467 expandable_expression = { 468 "name": "pt", 469 "context": { 470 "repl": { 471 "equals": {"type": "PointType"}, 472 "equals": { 473 "result": """(PointType) $0 = { 474 x = 11 475 y = 22 476 buffer = { 477 [0] = 0 478 [1] = 1 479 [2] = 2 480 [3] = 3 481 [4] = 4 482 [5] = 5 483 [6] = 6 484 [7] = 7 485 [8] = 8 486 [9] = 9 487 [10] = 10 488 [11] = 11 489 [12] = 12 490 [13] = 13 491 [14] = 14 492 [15] = 15 493 } 494}""" 495 }, 496 "missing": ["indexedVariables"], 497 "hasVariablesReference": True, 498 }, 499 "hover": { 500 "equals": {"type": "PointType"}, 501 "equals": { 502 "result": """(PointType) pt = { 503 x = 11 504 y = 22 505 buffer = { 506 [0] = 0 507 [1] = 1 508 [2] = 2 509 [3] = 3 510 [4] = 4 511 [5] = 5 512 [6] = 6 513 [7] = 7 514 [8] = 8 515 [9] = 9 516 [10] = 10 517 [11] = 11 518 [12] = 12 519 [13] = 13 520 [14] = 14 521 [15] = 15 522 } 523}""" 524 }, 525 "missing": ["indexedVariables"], 526 "hasVariablesReference": True, 527 }, 528 "watch": { 529 "equals": {"type": "PointType"}, 530 "startswith": { 531 "result": "{x:11, y:22, buffer:{...}}" 532 if enableAutoVariableSummaries 533 else "PointType @ 0x" 534 }, 535 "missing": ["indexedVariables"], 536 "hasVariablesReference": True, 537 }, 538 "variables": { 539 "equals": {"type": "PointType"}, 540 "startswith": { 541 "result": "{x:11, y:22, buffer:{...}}" 542 if enableAutoVariableSummaries 543 else "PointType @ 0x" 544 }, 545 "missing": ["indexedVariables"], 546 "hasVariablesReference": True, 547 }, 548 }, 549 "children": { 550 "x": {"equals": {"type": "int", "value": "11"}}, 551 "y": {"equals": {"type": "int", "value": "22"}}, 552 "buffer": {"children": buffer_children}, 553 }, 554 } 555 556 # Evaluate from known contexts. 557 expr_varref_dict = {} 558 for context, verify_dict in expandable_expression["context"].items(): 559 response = self.dap_server.request_evaluate( 560 expandable_expression["name"], 561 frameIndex=0, 562 threadId=None, 563 context=context, 564 ) 565 self.verify_values( 566 verify_dict, 567 response["body"], 568 expr_varref_dict, 569 expandable_expression["name"], 570 ) 571 572 # Evaluate locals again. 573 locals = self.dap_server.get_local_variables() 574 self.verify_variables(verify_locals, locals) 575 576 # Verify the evaluated expressions before second locals evaluation 577 # can be expanded. 578 var_ref = expr_varref_dict[expandable_expression["name"]] 579 response = self.dap_server.request_variables(var_ref) 580 self.verify_variables( 581 expandable_expression["children"], response["body"]["variables"] 582 ) 583 584 # Continue to breakpoint 3, permanent variable should still exist 585 # after resume. 586 breakpoint3_line = line_number(source, "// breakpoint 3") 587 lines = [breakpoint3_line] 588 breakpoint_ids = self.set_source_breakpoints(source, lines) 589 self.assertEqual( 590 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 591 ) 592 self.continue_to_breakpoints(breakpoint_ids) 593 594 var_ref = expr_varref_dict[expandable_expression["name"]] 595 response = self.dap_server.request_variables(var_ref) 596 self.verify_variables( 597 expandable_expression["children"], response["body"]["variables"] 598 ) 599 600 # Test that frame scopes have corresponding presentation hints. 601 frame_id = self.dap_server.get_stackFrame()["id"] 602 scopes = self.dap_server.request_scopes(frame_id)["body"]["scopes"] 603 604 scope_names = [scope["name"] for scope in scopes] 605 self.assertIn("Locals", scope_names) 606 self.assertIn("Registers", scope_names) 607 608 for scope in scopes: 609 if scope["name"] == "Locals": 610 self.assertEqual(scope.get("presentationHint"), "locals") 611 if scope["name"] == "Registers": 612 self.assertEqual(scope.get("presentationHint"), "registers") 613 614 @skipIfWindows 615 @skipIfRemote 616 def test_scopes_and_evaluate_expansion(self): 617 self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=False) 618 619 @skipIfWindows 620 @skipIfRemote 621 def test_scopes_and_evaluate_expansion_with_descriptive_summaries(self): 622 self.do_test_scopes_and_evaluate_expansion(enableAutoVariableSummaries=True) 623 624 def do_test_indexedVariables(self, enableSyntheticChildDebugging: bool): 625 """ 626 Tests that arrays and lldb.SBValue objects that have synthetic child 627 providers have "indexedVariables" key/value pairs. This helps the IDE 628 not to fetch too many children all at once. 629 """ 630 program = self.getBuildArtifact("a.out") 631 self.build_and_launch( 632 program, enableSyntheticChildDebugging=enableSyntheticChildDebugging 633 ) 634 source = "main.cpp" 635 breakpoint1_line = line_number(source, "// breakpoint 4") 636 lines = [breakpoint1_line] 637 # Set breakpoint in the thread function so we can step the threads 638 breakpoint_ids = self.set_source_breakpoints(source, lines) 639 self.assertEqual( 640 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 641 ) 642 self.continue_to_breakpoints(breakpoint_ids) 643 644 # Verify locals 645 locals = self.dap_server.get_local_variables() 646 # The vector variables might have one additional entry from the fake 647 # "[raw]" child. 648 raw_child_count = 1 if enableSyntheticChildDebugging else 0 649 verify_locals = { 650 "small_array": {"equals": {"indexedVariables": 5}}, 651 "large_array": {"equals": {"indexedVariables": 200}}, 652 "small_vector": {"equals": {"indexedVariables": 5 + raw_child_count}}, 653 "large_vector": {"equals": {"indexedVariables": 200 + raw_child_count}}, 654 "pt": {"missing": ["indexedVariables"]}, 655 } 656 self.verify_variables(verify_locals, locals) 657 658 # We also verify that we produce a "[raw]" fake child with the real 659 # SBValue for the synthetic type. 660 verify_children = { 661 "[0]": {"equals": {"type": "int", "value": "0"}}, 662 "[1]": {"equals": {"type": "int", "value": "0"}}, 663 "[2]": {"equals": {"type": "int", "value": "0"}}, 664 "[3]": {"equals": {"type": "int", "value": "0"}}, 665 "[4]": {"equals": {"type": "int", "value": "0"}}, 666 } 667 if enableSyntheticChildDebugging: 668 verify_children["[raw]"] = ({"contains": {"type": ["vector"]}},) 669 670 children = self.dap_server.request_variables(locals[2]["variablesReference"])[ 671 "body" 672 ]["variables"] 673 self.verify_variables(verify_children, children) 674 675 @skipIfWindows 676 @skipIfRemote 677 def test_indexedVariables(self): 678 self.do_test_indexedVariables(enableSyntheticChildDebugging=False) 679 680 @skipIfWindows 681 @skipIfRemote 682 def test_indexedVariables_with_raw_child_for_synthetics(self): 683 self.do_test_indexedVariables(enableSyntheticChildDebugging=True) 684 685 @skipIfWindows 686 @skipIfRemote 687 def test_registers(self): 688 """ 689 Test that registers whose byte size is the size of a pointer on 690 the current system get formatted as lldb::eFormatAddressInfo. This 691 will show the pointer value followed by a description of the address 692 itself. To test this we attempt to find the PC value in the general 693 purpose registers, and since we will be stopped in main.cpp, verify 694 that the value for the PC starts with a pointer and is followed by 695 a description that contains main.cpp. 696 """ 697 program = self.getBuildArtifact("a.out") 698 self.build_and_launch(program) 699 source = "main.cpp" 700 breakpoint1_line = line_number(source, "// breakpoint 1") 701 lines = [breakpoint1_line] 702 # Set breakpoint in the thread function so we can step the threads 703 breakpoint_ids = self.set_source_breakpoints(source, lines) 704 self.assertEqual( 705 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 706 ) 707 self.continue_to_breakpoints(breakpoint_ids) 708 709 pc_name = None 710 arch = self.getArchitecture() 711 if arch == "x86_64": 712 pc_name = "rip" 713 elif arch == "x86": 714 pc_name = "rip" 715 elif arch.startswith("arm"): 716 pc_name = "pc" 717 718 if pc_name is None: 719 return 720 # Verify locals 721 reg_sets = self.dap_server.get_registers() 722 for reg_set in reg_sets: 723 if reg_set["name"] == "General Purpose Registers": 724 varRef = reg_set["variablesReference"] 725 regs = self.dap_server.request_variables(varRef)["body"]["variables"] 726 for reg in regs: 727 if reg["name"] == pc_name: 728 value = reg["value"] 729 self.assertTrue(value.startswith("0x")) 730 self.assertIn("a.out`main + ", value) 731 self.assertIn("at main.cpp:", value) 732 733 @no_debug_info_test 734 @skipUnlessDarwin 735 def test_darwin_dwarf_missing_obj(self): 736 """ 737 Test that if we build a binary with DWARF in .o files and we remove 738 the .o file for main.cpp, that we get a variable named "<error>" 739 whose value matches the appriopriate error. Errors when getting 740 variables are returned in the LLDB API when the user should be 741 notified of issues that can easily be solved by rebuilding or 742 changing compiler options and are designed to give better feedback 743 to the user. 744 """ 745 self.darwin_dwarf_missing_obj(None) 746 747 @no_debug_info_test 748 @skipUnlessDarwin 749 def test_darwin_dwarf_missing_obj_with_symbol_ondemand_enabled(self): 750 """ 751 Test that if we build a binary with DWARF in .o files and we remove 752 the .o file for main.cpp, that we get a variable named "<error>" 753 whose value matches the appriopriate error. Test with symbol_ondemand_enabled. 754 """ 755 initCommands = ["settings set symbols.load-on-demand true"] 756 self.darwin_dwarf_missing_obj(initCommands) 757 758 @no_debug_info_test 759 @skipIfWindows 760 @skipIfRemote 761 def test_value_format(self): 762 """ 763 Test that toggle variables value format between decimal and hexical works. 764 """ 765 program = self.getBuildArtifact("a.out") 766 self.build_and_launch(program) 767 source = "main.cpp" 768 breakpoint1_line = line_number(source, "// breakpoint 1") 769 lines = [breakpoint1_line] 770 771 breakpoint_ids = self.set_source_breakpoints(source, lines) 772 self.assertEqual( 773 len(breakpoint_ids), len(lines), "expect correct number of breakpoints" 774 ) 775 self.continue_to_breakpoints(breakpoint_ids) 776 777 # Verify locals value format decimal 778 is_hex = False 779 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 780 self.assertEquals(var_pt_x["value"], "11") 781 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 782 self.assertEquals(var_pt_y["value"], "22") 783 784 # Verify locals value format hexical 785 is_hex = True 786 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 787 self.assertEquals(var_pt_x["value"], "0x0000000b") 788 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 789 self.assertEquals(var_pt_y["value"], "0x00000016") 790 791 # Toggle and verify locals value format decimal again 792 is_hex = False 793 var_pt_x = self.dap_server.get_local_variable_child("pt", "x", is_hex=is_hex) 794 self.assertEquals(var_pt_x["value"], "11") 795 var_pt_y = self.dap_server.get_local_variable_child("pt", "y", is_hex=is_hex) 796 self.assertEquals(var_pt_y["value"], "22") 797