https://github.com/eronnen created 
https://github.com/llvm/llvm-project/pull/140470

Attempt to improve tests by synchronously waiting for breakpoints to resolve. 
Not sure if it will fix all the tests but I think it should make the tests more 
stable

>From 0bb463172bdabe20e08f743107906bce424c4b4c Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyron...@gmail.com>
Date: Sun, 18 May 2025 20:56:47 +0200
Subject: [PATCH] [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                |  4 ++-
 ...TestGetTargetBreakpointsRequestHandler.cpp | 10 +++++--
 7 files changed, 42 insertions(+), 10 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 70fd0b0c419db..1b63ec77abba6 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
@@ -1187,7 +1187,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.
@@ -1195,7 +1195,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 afdc746ed0d0d..cc45811bd5f27 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
@@ -48,7 +48,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.
@@ -62,9 +62,11 @@ 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_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.
@@ -78,7 +80,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 aae1251b17c93..26df2573555df 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..1622fb2d14de2 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,7 +35,9 @@ 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]))
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));

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to