[Lldb-commits] [lldb] [lldb][NFC] Add test utility for sending gdbremote packets (PR #195247)

Felipe de Azevedo Piovezan via lldb-commits lldb-commits at lists.llvm.org
Fri May 1 04:42:04 PDT 2026


https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/195247

>From a4b867f7ac70c09187d25ac23ce2e543d0f1f44b Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Fri, 1 May 2026 11:00:40 +0100
Subject: [PATCH] [lldb][NFC] Add test utility for sending gdbremote packets

This removes some duplicated code, and also helps future tests. It's
also surprisingly not easy to write these, as there are a few footguns.
---
 .../Python/lldbsuite/test/lldbutil.py         | 23 ++++++++++++++
 .../multi-breakpoint/TestMultiBreakpoint.py   | 31 +++++--------------
 .../TestDebugserverMultiMemRead.py            | 22 ++++---------
 3 files changed, 36 insertions(+), 40 deletions(-)

diff --git a/lldb/packages/Python/lldbsuite/test/lldbutil.py b/lldb/packages/Python/lldbsuite/test/lldbutil.py
index 00230036a0e71..520e7e5079d19 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbutil.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbutil.py
@@ -18,6 +18,7 @@
 import lldb
 from . import lldbtest_config
 from . import configuration
+from lldbsuite.test.gdbclientutils import escape_binary
 
 # How often failed simulator process launches are retried.
 SIMULATOR_RETRY = 3
@@ -1869,3 +1870,25 @@ def launch_exe_in_apple_simulator(
                 break
 
     return exe_path, matched_strings
+
+
+# Binary escapes `packet_str`, sends it to the remote and returns the reply.
+def send_packet_get_reply(test, packet_str):
+    packet_str = escape_binary(packet_str)
+    test.runCmd(f"proc plugin packet send '{packet_str}'", check=False)
+    # The output is of the form:
+    #  packet: <packet_str>
+    #  response: <response>
+    output = test.res.GetOutput()
+    reply = output.split("\n")
+    packet = reply[0].strip()
+    response = reply[1].strip()
+
+    test.assertTrue(packet.startswith("packet: "))
+    test.assertTrue(response.startswith("response: "))
+    return response[len("response: ") :].strip()
+
+
+def get_qsupported_capabilities(test):
+    reply = send_packet_get_reply(test, "qSupported")
+    return reply.strip().split(";")
diff --git a/lldb/test/API/functionalities/multi-breakpoint/TestMultiBreakpoint.py b/lldb/test/API/functionalities/multi-breakpoint/TestMultiBreakpoint.py
index d0d187970c81d..eb9e2952d5a49 100644
--- a/lldb/test/API/functionalities/multi-breakpoint/TestMultiBreakpoint.py
+++ b/lldb/test/API/functionalities/multi-breakpoint/TestMultiBreakpoint.py
@@ -12,38 +12,21 @@
 from lldbsuite.test.gdbclientutils import *
 
 
- at skipIfWindows # No server on Windows.
+ at skipIfWindows  # No server on Windows.
 @skipIfOutOfTreeDebugserver
 # Runs on systems where we can always predict the software break size
 @skipIf(archs=no_match(["x86_64", "arm64", "aarch64"]))
 class TestMultiBreakpoint(TestBase):
-    def send_packet(self, packet_str):
-        packet_str = escape_binary(packet_str)
-        self.runCmd(f"process plugin packet send '{packet_str}'", check=False)
-        output = self.res.GetOutput()
-        reply = output.split("\n")
-        # The output is of the form:
-        #  packet: <packet_str>
-        #  response: <response>
-        packet_line = None
-        response_line = None
-        for line in reply:
-            line = line.strip()
-            if line.startswith("packet:"):
-                packet_line = line
-            elif line.startswith("response:"):
-                response_line = line
-        self.assertIsNotNone(packet_line, f'No "packet:" line in output: {output}')
-        self.assertIsNotNone(response_line, f'No "response:" line in output: {output}')
-        return response_line[len("response:") :].strip()
-
     def check_invalid_packet(self, packet_str):
-        reply = self.send_packet(packet_str)
+        reply = lldbutil.send_packet_get_reply(self, packet_str)
         if reply.startswith("E"):
             return
         else:
             self.assertMultiResponse(reply, ["error"])
 
+    def send_packet(self, packet_str):
+        return lldbutil.send_packet_get_reply(self, packet_str)
+
     def assertMultiResponse(self, reply, expected):
         """Assert a JSON-array multi-response matches the expected pattern.
 
@@ -84,8 +67,8 @@ def test_multi_breakpoint(self):
         )
 
         # Verify the server advertises jMultiBreakpoint support.
-        reply = self.send_packet("qSupported")
-        self.assertIn("jMultiBreakpoint+", reply)
+        capabilities = lldbutil.get_qsupported_capabilities(self)
+        self.assertIn("jMultiBreakpoint+", capabilities)
 
         addr_a = self.get_function_address("func_a")
         addr_b = self.get_function_address("func_b")
diff --git a/lldb/test/API/macosx/debugserver-multimemread/TestDebugserverMultiMemRead.py b/lldb/test/API/macosx/debugserver-multimemread/TestDebugserverMultiMemRead.py
index 6caa5f85c2848..ab6e952fb7dd1 100644
--- a/lldb/test/API/macosx/debugserver-multimemread/TestDebugserverMultiMemRead.py
+++ b/lldb/test/API/macosx/debugserver-multimemread/TestDebugserverMultiMemRead.py
@@ -11,23 +11,13 @@
 @skipUnlessDarwin
 @skipIfOutOfTreeDebugserver
 class TestCase(TestBase):
-    def send_process_packet(self, packet_str):
-        self.runCmd(f"proc plugin packet send {packet_str}", check=False)
-        # The output is of the form:
-        #  packet: <packet_str>
-        #  response: <response>
-        reply = self.res.GetOutput().split("\n")
-        packet = reply[0].strip()
-        response = reply[1].strip()
-
-        self.assertTrue(packet.startswith("packet: "))
-        self.assertTrue(response.startswith("response: "))
-        return response[len("response: ") :]
-
     def check_invalid_packet(self, packet_str):
-        reply = self.send_process_packet("packet_str")
+        reply = lldbutil.send_packet_get_reply(self, "packet_str")
         self.assertEqual(reply, "E03")
 
+    def send_process_packet(self, packet_str):
+        return lldbutil.send_packet_get_reply(self, packet_str)
+
     def test_packets(self):
         self.build()
         source_file = lldb.SBFileSpec("main.c")
@@ -35,8 +25,8 @@ def test_packets(self):
             self, "break here", source_file
         )
 
-        reply = self.send_process_packet("qSupported")
-        self.assertIn("MultiMemRead+", reply)
+        capabilities = lldbutil.get_qsupported_capabilities(self)
+        self.assertIn("MultiMemRead+", capabilities)
 
         mem_address_var = thread.frames[0].FindVariable("memory")
         self.assertTrue(mem_address_var)



More information about the lldb-commits mailing list