[Lldb-commits] [lldb] [lldb-dap] Synchronously wait for breakpoints resolves in tests (PR #140470)
Ely Ronnen via lldb-commits
lldb-commits at lists.llvm.org
Sat May 31 00:06:40 PDT 2025
https://github.com/eronnen updated https://github.com/llvm/llvm-project/pull/140470
>From 87cf6aee70458b0e9bbc717ee9a5cf9b91b6242a Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 20:56:47 +0200
Subject: [PATCH 1/8] [lldb-dap] Attempt to synchronously wait for breakpoints
resolve in lldb-dap tests in order to stabilize the tests
---
.../test/tools/lldb-dap/dap_server.py | 6 +++--
.../test/tools/lldb-dap/lldbdap_testcase.py | 26 +++++++++++++++++--
.../breakpoint/TestDAP_setBreakpoints.py | 1 -
.../TestDAP_setFunctionBreakpoints.py | 1 -
.../tools/lldb-dap/module/TestDAP_module.py | 4 ++-
.../TestDAP_terminatedEvent.py | 6 +++--
...TestGetTargetBreakpointsRequestHandler.cpp | 10 +++++--
7 files changed, 43 insertions(+), 11 deletions(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 4c8c51905e1d0..5b1113f4b1251 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -1216,7 +1216,7 @@ def request_locations(self, locationReference):
}
return self.send_recv(command_dict)
- def request_testGetTargetBreakpoints(self):
+ def request_testGetTargetBreakpoints(self, only_resolved=False):
"""A request packet used in the LLDB test suite to get all currently
set breakpoint infos for all breakpoints currently set in the
target.
@@ -1224,7 +1224,9 @@ def request_testGetTargetBreakpoints(self):
command_dict = {
"command": "_testGetTargetBreakpoints",
"type": "request",
- "arguments": {},
+ "arguments": {
+ "onlyResolved": only_resolved,
+ },
}
return self.send_recv(command_dict)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index 91ae55977046b..27ce8171da630 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -49,7 +49,7 @@ def build_and_create_debug_adapter_for_attach(self):
self.build_and_create_debug_adapter(dictionary={"EXE": unique_name})
return self.getBuildArtifact(unique_name)
- def set_source_breakpoints(self, source_path, lines, data=None):
+ def set_source_breakpoints(self, source_path, lines, data=None, wait_for_resolve=True):
"""Sets source breakpoints and returns an array of strings containing
the breakpoint IDs ("1", "2") for each breakpoint that was set.
Parameter data is array of data objects for breakpoints.
@@ -65,6 +65,8 @@ def set_source_breakpoints(self, source_path, lines, data=None):
breakpoint_ids = []
for breakpoint in breakpoints:
breakpoint_ids.append("%i" % (breakpoint["id"]))
+ if wait_for_resolve:
+ self.wait_for_breakpoints_to_resolve(breakpoint_ids, timeout=10)
return breakpoint_ids
def set_source_breakpoints_assembly(self, source_reference, lines, data=None):
@@ -81,7 +83,7 @@ def set_source_breakpoints_assembly(self, source_reference, lines, data=None):
breakpoint_ids.append("%i" % (breakpoint["id"]))
return breakpoint_ids
- def set_function_breakpoints(self, functions, condition=None, hitCondition=None):
+ def set_function_breakpoints(self, functions, condition=None, hitCondition=None, wait_for_resolve=True):
"""Sets breakpoints by function name given an array of function names
and returns an array of strings containing the breakpoint IDs
("1", "2") for each breakpoint that was set.
@@ -95,7 +97,27 @@ def set_function_breakpoints(self, functions, condition=None, hitCondition=None)
breakpoint_ids = []
for breakpoint in breakpoints:
breakpoint_ids.append("%i" % (breakpoint["id"]))
+ if wait_for_resolve:
+ self.wait_for_breakpoints_to_resolve(breakpoint_ids, timeout=10)
return breakpoint_ids
+
+ def wait_for_breakpoints_to_resolve(self, breakpoint_ids: list[str], timeout: Optional[float] = None):
+ unresolved_breakpoints = set(breakpoint_ids)
+
+ # Check already resolved breakpoints
+ resolved_breakpoints = self.dap_server.request_testGetTargetBreakpoints(only_resolved=True)["body"]["breakpoints"]
+ for resolved_breakpoint in resolved_breakpoints:
+ unresolved_breakpoints.discard(str(resolved_breakpoint["id"]))
+
+ while len(unresolved_breakpoints) > 0:
+ breakpoint_event = self.dap_server.wait_for_event("breakpoint", timeout=timeout)
+ if breakpoint_event is None:
+ break
+
+ if breakpoint_event["body"]["reason"] in ["changed", "new"]:
+ unresolved_breakpoints.discard(str(breakpoint_event["body"]["breakpoint"]["id"]))
+
+ self.assertEqual(len(unresolved_breakpoints), 0, f"Expected to resolve all breakpoints. Unresolved breakpoint ids: {unresolved_breakpoints}")
def waitUntil(self, condition_callback):
for _ in range(20):
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
index 22470daac2887..831edd6494c1e 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
@@ -12,7 +12,6 @@
import os
- at skip("Temporarily disable the breakpoint tests")
class TestDAP_setBreakpoints(lldbdap_testcase.DAPTestCaseBase):
def setUp(self):
lldbdap_testcase.DAPTestCaseBase.setUp(self)
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py
index baaca4d974d5d..946595f639edc 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py
@@ -10,7 +10,6 @@
import lldbdap_testcase
- at skip("Temporarily disable the breakpoint tests")
class TestDAP_setFunctionBreakpoints(lldbdap_testcase.DAPTestCaseBase):
@skipIfWindows
def test_set_and_clear(self):
diff --git a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py
index 3fc0f752ee39e..2cea2a94adbbd 100644
--- a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py
+++ b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py
@@ -16,7 +16,9 @@ def run_test(self, symbol_basename, expect_debug_info_size):
program = self.getBuildArtifact(program_basename)
self.build_and_launch(program)
functions = ["foo"]
- breakpoint_ids = self.set_function_breakpoints(functions)
+
+ # This breakpoint will be resolved only when the libfoo module is loaded
+ breakpoint_ids = self.set_function_breakpoints(functions, wait_for_resolve=False)
self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint")
self.continue_to_breakpoints(breakpoint_ids)
active_modules = self.dap_server.get_modules()
diff --git a/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py b/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py
index b0abe2a38dac4..a93a4a2fa77cb 100644
--- a/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py
+++ b/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py
@@ -35,10 +35,12 @@ def test_terminated_event(self):
self.build_and_launch(program)
# Set breakpoints
functions = ["foo"]
- breakpoint_ids = self.set_function_breakpoints(functions)
+
+ # This breakpoint will be resolved only when the libfoo module is loaded
+ breakpoint_ids = self.set_function_breakpoints(functions, wait_for_resolve=False)
self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint")
main_bp_line = line_number("main.cpp", "// main breakpoint 1")
- breakpoint_ids.append(self.set_source_breakpoints("main.cpp", [main_bp_line]))
+ breakpoint_ids.append(self.set_source_breakpoints("main.cpp", [main_bp_line], wait_for_resolve=False))
self.continue_to_breakpoints(breakpoint_ids)
self.continue_to_exit()
diff --git a/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp
index 5f4f016f6a1ef..129eb31b8356b 100644
--- a/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp
@@ -15,12 +15,18 @@ namespace lldb_dap {
void TestGetTargetBreakpointsRequestHandler::operator()(
const llvm::json::Object &request) const {
+ const auto *arguments = request.getObject("arguments");
+ bool only_resolved = GetBoolean(arguments, "onlyResolved").value_or(false);
+
llvm::json::Object response;
FillResponse(request, response);
llvm::json::Array response_breakpoints;
for (uint32_t i = 0; dap.target.GetBreakpointAtIndex(i).IsValid(); ++i) {
- auto bp = Breakpoint(dap, dap.target.GetBreakpointAtIndex(i));
- response_breakpoints.push_back(bp.ToProtocolBreakpoint());
+ const auto target_bp = dap.target.GetBreakpointAtIndex(i);
+ if (!only_resolved || target_bp.GetNumResolvedLocations() > 0) {
+ auto bp = Breakpoint(dap, target_bp);
+ response_breakpoints.push_back(bp.ToProtocolBreakpoint());
+ }
}
llvm::json::Object body;
body.try_emplace("breakpoints", std::move(response_breakpoints));
>From 729f6eb8cdbe777d5ebaa40a19e7f375b14d2b5b Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 21:11:25 +0200
Subject: [PATCH 2/8] python format
---
.../test/tools/lldb-dap/lldbdap_testcase.py | 34 ++++++++++++++-----
.../tools/lldb-dap/module/TestDAP_module.py | 6 ++--
.../TestDAP_terminatedEvent.py | 12 +++++--
3 files changed, 38 insertions(+), 14 deletions(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index 27ce8171da630..bd4e3b8e9073e 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -49,7 +49,9 @@ def build_and_create_debug_adapter_for_attach(self):
self.build_and_create_debug_adapter(dictionary={"EXE": unique_name})
return self.getBuildArtifact(unique_name)
- def set_source_breakpoints(self, source_path, lines, data=None, wait_for_resolve=True):
+ def set_source_breakpoints(
+ self, source_path, lines, data=None, wait_for_resolve=True
+ ):
"""Sets source breakpoints and returns an array of strings containing
the breakpoint IDs ("1", "2") for each breakpoint that was set.
Parameter data is array of data objects for breakpoints.
@@ -83,7 +85,9 @@ def set_source_breakpoints_assembly(self, source_reference, lines, data=None):
breakpoint_ids.append("%i" % (breakpoint["id"]))
return breakpoint_ids
- def set_function_breakpoints(self, functions, condition=None, hitCondition=None, wait_for_resolve=True):
+ def set_function_breakpoints(
+ self, functions, condition=None, hitCondition=None, wait_for_resolve=True
+ ):
"""Sets breakpoints by function name given an array of function names
and returns an array of strings containing the breakpoint IDs
("1", "2") for each breakpoint that was set.
@@ -100,24 +104,36 @@ def set_function_breakpoints(self, functions, condition=None, hitCondition=None,
if wait_for_resolve:
self.wait_for_breakpoints_to_resolve(breakpoint_ids, timeout=10)
return breakpoint_ids
-
- def wait_for_breakpoints_to_resolve(self, breakpoint_ids: list[str], timeout: Optional[float] = None):
+
+ def wait_for_breakpoints_to_resolve(
+ self, breakpoint_ids: list[str], timeout: Optional[float] = None
+ ):
unresolved_breakpoints = set(breakpoint_ids)
-
+
# Check already resolved breakpoints
- resolved_breakpoints = self.dap_server.request_testGetTargetBreakpoints(only_resolved=True)["body"]["breakpoints"]
+ resolved_breakpoints = self.dap_server.request_testGetTargetBreakpoints(
+ only_resolved=True
+ )["body"]["breakpoints"]
for resolved_breakpoint in resolved_breakpoints:
unresolved_breakpoints.discard(str(resolved_breakpoint["id"]))
while len(unresolved_breakpoints) > 0:
- breakpoint_event = self.dap_server.wait_for_event("breakpoint", timeout=timeout)
+ breakpoint_event = self.dap_server.wait_for_event(
+ "breakpoint", timeout=timeout
+ )
if breakpoint_event is None:
break
if breakpoint_event["body"]["reason"] in ["changed", "new"]:
- unresolved_breakpoints.discard(str(breakpoint_event["body"]["breakpoint"]["id"]))
+ unresolved_breakpoints.discard(
+ str(breakpoint_event["body"]["breakpoint"]["id"])
+ )
- self.assertEqual(len(unresolved_breakpoints), 0, f"Expected to resolve all breakpoints. Unresolved breakpoint ids: {unresolved_breakpoints}")
+ self.assertEqual(
+ len(unresolved_breakpoints),
+ 0,
+ f"Expected to resolve all breakpoints. Unresolved breakpoint ids: {unresolved_breakpoints}",
+ )
def waitUntil(self, condition_callback):
for _ in range(20):
diff --git a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py
index 2cea2a94adbbd..4fc221668a8ee 100644
--- a/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py
+++ b/lldb/test/API/tools/lldb-dap/module/TestDAP_module.py
@@ -16,9 +16,11 @@ def run_test(self, symbol_basename, expect_debug_info_size):
program = self.getBuildArtifact(program_basename)
self.build_and_launch(program)
functions = ["foo"]
-
+
# This breakpoint will be resolved only when the libfoo module is loaded
- breakpoint_ids = self.set_function_breakpoints(functions, wait_for_resolve=False)
+ breakpoint_ids = self.set_function_breakpoints(
+ functions, wait_for_resolve=False
+ )
self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint")
self.continue_to_breakpoints(breakpoint_ids)
active_modules = self.dap_server.get_modules()
diff --git a/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py b/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py
index a93a4a2fa77cb..7de85bd1589cd 100644
--- a/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py
+++ b/lldb/test/API/tools/lldb-dap/terminated-event/TestDAP_terminatedEvent.py
@@ -35,12 +35,18 @@ def test_terminated_event(self):
self.build_and_launch(program)
# Set breakpoints
functions = ["foo"]
-
+
# This breakpoint will be resolved only when the libfoo module is loaded
- breakpoint_ids = self.set_function_breakpoints(functions, wait_for_resolve=False)
+ breakpoint_ids = self.set_function_breakpoints(
+ functions, wait_for_resolve=False
+ )
self.assertEqual(len(breakpoint_ids), len(functions), "expect one breakpoint")
main_bp_line = line_number("main.cpp", "// main breakpoint 1")
- breakpoint_ids.append(self.set_source_breakpoints("main.cpp", [main_bp_line], wait_for_resolve=False))
+ breakpoint_ids.append(
+ self.set_source_breakpoints(
+ "main.cpp", [main_bp_line], wait_for_resolve=False
+ )
+ )
self.continue_to_breakpoints(breakpoint_ids)
self.continue_to_exit()
>From 62ec51e544f880dc5b2cb5fbdd432ebfb85375e0 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 21 May 2025 07:52:49 +0200
Subject: [PATCH 3/8] keep track of verified breakpoints in tests
---
.../test/tools/lldb-dap/dap_server.py | 39 ++++++++++++++++---
.../test/tools/lldb-dap/lldbdap_testcase.py | 26 ++-----------
...TestGetTargetBreakpointsRequestHandler.cpp | 10 +----
3 files changed, 40 insertions(+), 35 deletions(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 5b1113f4b1251..bfae6011e0a59 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -166,6 +166,7 @@ def __init__(
self.initialized = False
self.frame_scopes = {}
self.init_commands = init_commands
+ self.resolved_breakpoints = set([])
@classmethod
def encode_content(cls, s: str) -> bytes:
@@ -309,6 +310,14 @@ def _process_continued(self, all_threads_continued: bool):
if all_threads_continued:
self.thread_stop_reasons = {}
+ def _update_verified_breakpoints(self, breakpoints):
+ for breakpoint in breakpoints:
+ if "verified" in breakpoint:
+ if breakpoint["verified"]:
+ self.resolved_breakpoints.add(str(breakpoint["id"]))
+ else:
+ self.resolved_breakpoints.discard(str(breakpoint["id"]))
+
def send_packet(self, command_dict: Request, set_sequence=True):
"""Take the "command_dict" python dictionary and encode it as a JSON
string and send the contents as a packet to the VSCode debug
@@ -452,8 +461,27 @@ def wait_for_breakpoint_events(self, timeout: Optional[float] = None):
if not event:
break
breakpoint_events.append(event)
+
+ self._update_verified_breakpoints(
+ [event["body"]["breakpoint"] for event in breakpoint_events]
+ )
return breakpoint_events
+ def wait_for_breakpoints_to_be_verified(
+ self, breakpoint_ids: list[str], timeout: Optional[float] = None
+ ):
+ """Wait for all breakpoints to be verified. Return all unverified breakpoints."""
+ unresolved_breakpoints = set(breakpoint_ids)
+ unresolved_breakpoints -= self.resolved_breakpoints
+ while len(unresolved_breakpoints) > 0:
+ breakpoint_event = self.wait_for_event("breakpoint", timeout=timeout)
+ if breakpoint_event is None:
+ break
+
+ self._update_verified_breakpoints([breakpoint_event["body"]["breakpoint"]])
+ unresolved_breakpoints -= self.resolved_breakpoints
+ return unresolved_breakpoints
+
def wait_for_exited(self, timeout: Optional[float] = None):
event_dict = self.wait_for_event("exited", timeout=timeout)
if event_dict is None:
@@ -1013,7 +1041,10 @@ def request_setBreakpoints(self, source: Source, line_array, data=None):
"type": "request",
"arguments": args_dict,
}
- return self.send_recv(command_dict)
+ response = self.send_recv(command_dict)
+ breakpoints = response["body"]["breakpoints"]
+ self._update_verified_breakpoints(breakpoints)
+ return response
def request_setExceptionBreakpoints(self, filters):
args_dict = {"filters": filters}
@@ -1216,7 +1247,7 @@ def request_locations(self, locationReference):
}
return self.send_recv(command_dict)
- def request_testGetTargetBreakpoints(self, only_resolved=False):
+ def request_testGetTargetBreakpoints(self):
"""A request packet used in the LLDB test suite to get all currently
set breakpoint infos for all breakpoints currently set in the
target.
@@ -1224,9 +1255,7 @@ def request_testGetTargetBreakpoints(self, only_resolved=False):
command_dict = {
"command": "_testGetTargetBreakpoints",
"type": "request",
- "arguments": {
- "onlyResolved": only_resolved,
- },
+ "arguments": {},
}
return self.send_recv(command_dict)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index bd4e3b8e9073e..9a8353e474990 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -106,29 +106,11 @@ def set_function_breakpoints(
return breakpoint_ids
def wait_for_breakpoints_to_resolve(
- self, breakpoint_ids: list[str], timeout: Optional[float] = None
+ self, breakpoint_ids: list[str], timeout: Optional[float] = DEFAULT_TIMEOUT
):
- unresolved_breakpoints = set(breakpoint_ids)
-
- # Check already resolved breakpoints
- resolved_breakpoints = self.dap_server.request_testGetTargetBreakpoints(
- only_resolved=True
- )["body"]["breakpoints"]
- for resolved_breakpoint in resolved_breakpoints:
- unresolved_breakpoints.discard(str(resolved_breakpoint["id"]))
-
- while len(unresolved_breakpoints) > 0:
- breakpoint_event = self.dap_server.wait_for_event(
- "breakpoint", timeout=timeout
- )
- if breakpoint_event is None:
- break
-
- if breakpoint_event["body"]["reason"] in ["changed", "new"]:
- unresolved_breakpoints.discard(
- str(breakpoint_event["body"]["breakpoint"]["id"])
- )
-
+ unresolved_breakpoints = self.dap_server.wait_for_breakpoints_to_be_verified(
+ breakpoint_ids, timeout
+ )
self.assertEqual(
len(unresolved_breakpoints),
0,
diff --git a/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp
index 129eb31b8356b..5f4f016f6a1ef 100644
--- a/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/TestGetTargetBreakpointsRequestHandler.cpp
@@ -15,18 +15,12 @@ namespace lldb_dap {
void TestGetTargetBreakpointsRequestHandler::operator()(
const llvm::json::Object &request) const {
- const auto *arguments = request.getObject("arguments");
- bool only_resolved = GetBoolean(arguments, "onlyResolved").value_or(false);
-
llvm::json::Object response;
FillResponse(request, response);
llvm::json::Array response_breakpoints;
for (uint32_t i = 0; dap.target.GetBreakpointAtIndex(i).IsValid(); ++i) {
- const auto target_bp = dap.target.GetBreakpointAtIndex(i);
- if (!only_resolved || target_bp.GetNumResolvedLocations() > 0) {
- auto bp = Breakpoint(dap, target_bp);
- response_breakpoints.push_back(bp.ToProtocolBreakpoint());
- }
+ auto bp = Breakpoint(dap, dap.target.GetBreakpointAtIndex(i));
+ response_breakpoints.push_back(bp.ToProtocolBreakpoint());
}
llvm::json::Object body;
body.try_emplace("breakpoints", std::move(response_breakpoints));
>From 12094ef63fec7384005c6416113ca9e83a7e57ce Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 21 May 2025 07:58:45 +0200
Subject: [PATCH 4/8] fix default value
---
.../Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index 9a8353e474990..4bff40894d476 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -68,7 +68,7 @@ def set_source_breakpoints(
for breakpoint in breakpoints:
breakpoint_ids.append("%i" % (breakpoint["id"]))
if wait_for_resolve:
- self.wait_for_breakpoints_to_resolve(breakpoint_ids, timeout=10)
+ self.wait_for_breakpoints_to_resolve(breakpoint_ids)
return breakpoint_ids
def set_source_breakpoints_assembly(self, source_reference, lines, data=None):
@@ -102,7 +102,7 @@ def set_function_breakpoints(
for breakpoint in breakpoints:
breakpoint_ids.append("%i" % (breakpoint["id"]))
if wait_for_resolve:
- self.wait_for_breakpoints_to_resolve(breakpoint_ids, timeout=10)
+ self.wait_for_breakpoints_to_resolve(breakpoint_ids)
return breakpoint_ids
def wait_for_breakpoints_to_resolve(
>From 1fb8a9ee9dbef53e68e7e44825186b509dee877e Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 21 May 2025 08:14:54 +0200
Subject: [PATCH 5/8] wait for resolve in request_setFunctionBreakpoints
---
.../Python/lldbsuite/test/tools/lldb-dap/dap_server.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index bfae6011e0a59..51623ba049ea0 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -1070,7 +1070,10 @@ def request_setFunctionBreakpoints(self, names, condition=None, hitCondition=Non
"type": "request",
"arguments": args_dict,
}
- return self.send_recv(command_dict)
+ response = self.send_recv(command_dict)
+ breakpoints = response["body"]["breakpoints"]
+ self._update_verified_breakpoints(breakpoints)
+ return response
def request_dataBreakpointInfo(
self, variablesReference, name, frameIndex=0, threadId=None
>From f09dd695290928d9b46ff80ea491443c4f482663 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 21 May 2025 22:21:32 +0200
Subject: [PATCH 6/8] maintain a map of resolved breakpoints
---
.../test/tools/lldb-dap/dap_server.py | 34 ++++++++-----------
1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 51623ba049ea0..48dc5509f344b 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -166,7 +166,7 @@ def __init__(
self.initialized = False
self.frame_scopes = {}
self.init_commands = init_commands
- self.resolved_breakpoints = set([])
+ self.resolved_breakpoints = {}
@classmethod
def encode_content(cls, s: str) -> bytes:
@@ -297,6 +297,9 @@ def _handle_recv_packet(self, packet: Optional[ProtocolMessage]) -> bool:
# and 'progressEnd' events. Keep these around in case test
# cases want to verify them.
self.progress_events.append(packet)
+ elif event == "breakpoint":
+ # Breakpoint events are sent when a breakpoint is resolved
+ self._update_verified_breakpoints([body["breakpoint"]])
elif packet_type == "response":
if packet["command"] == "disconnect":
@@ -310,13 +313,11 @@ def _process_continued(self, all_threads_continued: bool):
if all_threads_continued:
self.thread_stop_reasons = {}
- def _update_verified_breakpoints(self, breakpoints):
+ def _update_verified_breakpoints(self, breakpoints: list[Event]):
for breakpoint in breakpoints:
- if "verified" in breakpoint:
- if breakpoint["verified"]:
- self.resolved_breakpoints.add(str(breakpoint["id"]))
- else:
- self.resolved_breakpoints.discard(str(breakpoint["id"]))
+ self.resolved_breakpoints[str(breakpoint["id"])] = breakpoint.get(
+ "verified", False
+ )
def send_packet(self, command_dict: Request, set_sequence=True):
"""Take the "command_dict" python dictionary and encode it as a JSON
@@ -462,25 +463,18 @@ def wait_for_breakpoint_events(self, timeout: Optional[float] = None):
break
breakpoint_events.append(event)
- self._update_verified_breakpoints(
- [event["body"]["breakpoint"] for event in breakpoint_events]
- )
return breakpoint_events
def wait_for_breakpoints_to_be_verified(
self, breakpoint_ids: list[str], timeout: Optional[float] = None
):
"""Wait for all breakpoints to be verified. Return all unverified breakpoints."""
- unresolved_breakpoints = set(breakpoint_ids)
- unresolved_breakpoints -= self.resolved_breakpoints
- while len(unresolved_breakpoints) > 0:
+ while any(id not in self.resolved_breakpoints for id in breakpoint_ids):
breakpoint_event = self.wait_for_event("breakpoint", timeout=timeout)
if breakpoint_event is None:
break
- self._update_verified_breakpoints([breakpoint_event["body"]["breakpoint"]])
- unresolved_breakpoints -= self.resolved_breakpoints
- return unresolved_breakpoints
+ return [id for id in breakpoint_ids if id not in self.resolved_breakpoints]
def wait_for_exited(self, timeout: Optional[float] = None):
event_dict = self.wait_for_event("exited", timeout=timeout)
@@ -1042,8 +1036,8 @@ def request_setBreakpoints(self, source: Source, line_array, data=None):
"arguments": args_dict,
}
response = self.send_recv(command_dict)
- breakpoints = response["body"]["breakpoints"]
- self._update_verified_breakpoints(breakpoints)
+ if response["success"]:
+ self._update_verified_breakpoints(response["body"]["breakpoints"])
return response
def request_setExceptionBreakpoints(self, filters):
@@ -1071,8 +1065,8 @@ def request_setFunctionBreakpoints(self, names, condition=None, hitCondition=Non
"arguments": args_dict,
}
response = self.send_recv(command_dict)
- breakpoints = response["body"]["breakpoints"]
- self._update_verified_breakpoints(breakpoints)
+ if response["success"]:
+ self._update_verified_breakpoints(response["body"]["breakpoints"])
return response
def request_dataBreakpointInfo(
>From ea3a5e7c9f848a5d2e217426f8a9915552de41f4 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 21 May 2025 22:29:23 +0200
Subject: [PATCH 7/8] fix missing id handling
---
.../Python/lldbsuite/test/tools/lldb-dap/dap_server.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 48dc5509f344b..6b41aef2bb5b8 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -315,9 +315,10 @@ def _process_continued(self, all_threads_continued: bool):
def _update_verified_breakpoints(self, breakpoints: list[Event]):
for breakpoint in breakpoints:
- self.resolved_breakpoints[str(breakpoint["id"])] = breakpoint.get(
- "verified", False
- )
+ if "id" in breakpoint:
+ self.resolved_breakpoints[str(breakpoint["id"])] = breakpoint.get(
+ "verified", False
+ )
def send_packet(self, command_dict: Request, set_sequence=True):
"""Take the "command_dict" python dictionary and encode it as a JSON
@@ -462,7 +463,6 @@ def wait_for_breakpoint_events(self, timeout: Optional[float] = None):
if not event:
break
breakpoint_events.append(event)
-
return breakpoint_events
def wait_for_breakpoints_to_be_verified(
>From e07b3e9661694704994c5bcdcfbdd2a802f4f033 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 31 May 2025 09:06:01 +0200
Subject: [PATCH 8/8] add wait_for_resolve for assembly breakpoints
---
.../lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index 4bff40894d476..e26dbf6ae514f 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -71,7 +71,9 @@ def set_source_breakpoints(
self.wait_for_breakpoints_to_resolve(breakpoint_ids)
return breakpoint_ids
- def set_source_breakpoints_assembly(self, source_reference, lines, data=None):
+ def set_source_breakpoints_assembly(
+ self, source_reference, lines, data=None, wait_for_resolve=True
+ ):
response = self.dap_server.request_setBreakpoints(
Source(source_reference=source_reference),
lines,
@@ -83,6 +85,8 @@ def set_source_breakpoints_assembly(self, source_reference, lines, data=None):
breakpoint_ids = []
for breakpoint in breakpoints:
breakpoint_ids.append("%i" % (breakpoint["id"]))
+ if wait_for_resolve:
+ self.wait_for_breakpoints_to_resolve(breakpoint_ids)
return breakpoint_ids
def set_function_breakpoints(
More information about the lldb-commits
mailing list