| """ |
| Test lldb-dap setBreakpoints request |
| """ |
| |
| from dap_server import Source |
| from lldbsuite.test.decorators import * |
| from lldbsuite.test.lldbtest import * |
| from lldbsuite.test import lldbutil |
| import lldbdap_testcase |
| import os |
| |
| |
| class TestDAP_breakpointEvents(lldbdap_testcase.DAPTestCaseBase): |
| @skipUnlessDarwin |
| def test_breakpoint_events(self): |
| """ |
| This test sets a breakpoint in a shared library and runs and stops |
| at the entry point of a program. When we stop at the entry point, |
| the shared library won't be loaded yet. At this point the |
| breakpoint should set itself, but not be verified because no |
| locations are resolved. We will then continue and expect to get a |
| breakpoint event that informs us that the breakpoint in the shared |
| library is "changed" and the correct line number should be |
| supplied. We also set a breakpoint using a LLDB command using the |
| "preRunCommands" when launching our program. Any breakpoints set via |
| the command interpreter should not be have breakpoint events sent |
| back to VS Code as the UI isn't able to add new breakpoints to |
| their UI. Code has been added that tags breakpoints set from VS Code |
| DAP packets so we know the IDE knows about them. If VS Code is ever |
| able to register breakpoints that aren't initially set in the GUI, |
| then we will need to revise this. |
| """ |
| main_source_basename = "main.cpp" |
| main_source_path = os.path.join(os.getcwd(), main_source_basename) |
| foo_source_basename = "foo.cpp" |
| foo_source_path = os.path.join(os.getcwd(), foo_source_basename) |
| main_bp_line = line_number("main.cpp", "main breakpoint 1") |
| foo_bp1_line = line_number("foo.cpp", "foo breakpoint 1") |
| foo_bp2_line = line_number("foo.cpp", "foo breakpoint 2") |
| |
| # Visual Studio Code Debug Adapters have no way to specify the file |
| # without launching or attaching to a process, so we must start a |
| # process in order to be able to set breakpoints. |
| program = self.getBuildArtifact("a.out") |
| |
| # Set a breakpoint after creating the target by running a command line |
| # command. It will eventually resolve and cause a breakpoint changed |
| # event to be sent to lldb-dap. We want to make sure we don't send a |
| # breakpoint any breakpoints that were set from the command line. |
| # Breakpoints that are set via the VS code DAP packets will be |
| # registered and marked with a special keyword to ensure we deliver |
| # breakpoint events for these breakpoints but not for ones that are not |
| # set via the command interpreter. |
| bp_command = "breakpoint set --file foo.cpp --line %u" % (foo_bp2_line) |
| self.build_and_launch(program, preRunCommands=[bp_command]) |
| main_bp_id = 0 |
| foo_bp_id = 0 |
| # Set breakpoints and verify that they got set correctly |
| dap_breakpoint_ids = [] |
| response = self.dap_server.request_setBreakpoints( |
| Source.build(path=main_source_path), [main_bp_line] |
| ) |
| self.assertTrue(response["success"]) |
| breakpoints = response["body"]["breakpoints"] |
| for breakpoint in breakpoints: |
| main_bp_id = breakpoint["id"] |
| dap_breakpoint_ids.append("%i" % (main_bp_id)) |
| self.assertTrue( |
| breakpoint["verified"], "expect main breakpoint to be verified" |
| ) |
| |
| response = self.dap_server.request_setBreakpoints( |
| Source.build(path=foo_source_path), [foo_bp1_line] |
| ) |
| self.assertTrue(response["success"]) |
| breakpoints = response["body"]["breakpoints"] |
| for breakpoint in breakpoints: |
| foo_bp_id = breakpoint["id"] |
| dap_breakpoint_ids.append("%i" % (foo_bp_id)) |
| self.assertFalse( |
| breakpoint["verified"], "expect foo breakpoint to not be verified" |
| ) |
| |
| # Flush the breakpoint events. |
| self.dap_server.wait_for_breakpoint_events() |
| |
| # Continue to the breakpoint |
| self.continue_to_breakpoints(dap_breakpoint_ids) |
| |
| verified_breakpoint_ids = [] |
| unverified_breakpoint_ids = [] |
| for breakpoint_event in self.dap_server.wait_for_breakpoint_events(): |
| breakpoint = breakpoint_event["body"]["breakpoint"] |
| id = breakpoint["id"] |
| if breakpoint["verified"]: |
| verified_breakpoint_ids.append(id) |
| else: |
| unverified_breakpoint_ids.append(id) |
| |
| self.assertIn(main_bp_id, unverified_breakpoint_ids) |
| self.assertIn(foo_bp_id, unverified_breakpoint_ids) |
| |
| self.assertIn(main_bp_id, verified_breakpoint_ids) |
| self.assertIn(foo_bp_id, verified_breakpoint_ids) |