https://github.com/eronnen updated https://github.com/llvm/llvm-project/pull/140470
>From 5c1d1854c3f93e081405e27fa0f14a3c02ef7cc7 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Sun, 18 May 2025 20:56:47 +0200 Subject: [PATCH 1/6] [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 a028381a0a4f9..60ff2f55bc908 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 -@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 -@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 f44ea3f84638f96e9f5169085aa0dbc8cdee53dd Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Sun, 18 May 2025 21:11:25 +0200 Subject: [PATCH 2/6] 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 a87cf3e69c2fa7b04dcdda0ae5b162331f495e45 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Wed, 21 May 2025 07:52:49 +0200 Subject: [PATCH 3/6] 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 60ff2f55bc908..ff69b7e7336cc 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 929279728360204c138ae026478f8b09dbfb308f Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Wed, 21 May 2025 07:58:45 +0200 Subject: [PATCH 4/6] 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 4607cf1e7cece4b63e0ced99688c3556e9a2b571 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Wed, 21 May 2025 08:14:54 +0200 Subject: [PATCH 5/6] 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 ff69b7e7336cc..df979957aae5b 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 64a42f60fec2af7ab23effd1fe8374317e42ba16 Mon Sep 17 00:00:00 2001 From: Ely Ronnen <elyron...@gmail.com> Date: Wed, 21 May 2025 22:21:32 +0200 Subject: [PATCH 6/6] 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 df979957aae5b..ff0dabd342fd3 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( _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits