https://github.com/DavidSpickett created 
https://github.com/llvm/llvm-project/pull/204834

For #204788.

>From 308eae1cbce0f35ccca1b207b261333d40e4f86b Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Fri, 19 Jun 2026 13:41:43 +0000
Subject: [PATCH] [lldb][test] test case for ignoring notifications (WIP)

---
 .../Python/lldbsuite/test/gdbclientutils.py   | 15 +++--
 .../TestIgnoringNotifications.py              | 67 +++++++++++++++++++
 2 files changed, 76 insertions(+), 6 deletions(-)
 create mode 100644 
lldb/test/API/functionalities/gdb_remote_client/TestIgnoringNotifications.py

diff --git a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py 
b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
index 4c40299f3256d..b789452bac174 100644
--- a/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
+++ b/lldb/packages/Python/lldbsuite/test/gdbclientutils.py
@@ -22,15 +22,18 @@ def checksum(message):
     return check % 256
 
 
-def frame_packet(message):
+def frame_packet(message, prefix):
     """
     Create a framed packet that's ready to send over the GDB connection
     channel.
 
-    Framing includes surrounding the message between $ and #, and appending
-    a two character hex checksum.
+    Framing means:
+    * Attaching the prefix. Which is usually '$' but for notifications will be
+      '%'.
+    * Appending a '#'.
+    * Adding a two character hex checksum.
     """
-    return "$%s#%02x" % (message, checksum(message))
+    return "%s%s#%02x" % (prefix, message, checksum(message))
 
 
 def escape_binary(message):
@@ -694,9 +697,9 @@ def _parsePacket(self):
         self._receivedDataOffset = 0
         return packet
 
-    def _sendPacket(self, packet: str):
+    def _sendPacket(self, packet: str, prefix="$"):
         assert self._socket is not None
-        framed_packet = seven.bitcast_to_bytes(frame_packet(packet))
+        framed_packet = seven.bitcast_to_bytes(frame_packet(packet, prefix))
         self._socket.sendall(framed_packet)
 
     def _handlePacket(self, packet):
diff --git 
a/lldb/test/API/functionalities/gdb_remote_client/TestIgnoringNotifications.py 
b/lldb/test/API/functionalities/gdb_remote_client/TestIgnoringNotifications.py
new file mode 100644
index 0000000000000..4867d301c440a
--- /dev/null
+++ 
b/lldb/test/API/functionalities/gdb_remote_client/TestIgnoringNotifications.py
@@ -0,0 +1,67 @@
+"""
+Test that LLDB ignores notification packets (those beginning with '%')
+when waiting for a response to a '$' packet.
+
+OpenOCD is one debug server that uses notification packets to reset
+the connection timeout if a memory read takes too long. So that's what
+we test here, but it should apply to any exchange.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test.gdbclientutils import *
+from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
+
+
+class NotifyingServerResponder(MockGDBServerResponder):
+    def readMemory(self, addr, length):
+        return "01" * length
+
+
+class NotifyingServer(MockGDBServer):
+    def __init__(self, socket):
+        self._socket = socket
+        self.responder = NotifyingServerResponder()
+        self.sent_notification = False
+
+    def _sendPacket(self, packet: str, prefix="$"):
+        # In theory we could add notifies before all packets, but it always
+        # goes through the same code and just makes the test take longer.
+        if packet == "01010101":
+            # Send more than one to make sure we clear them all to find
+            # the real response.
+            super()._sendPacket("this_is_a_notification", prefix="%")
+            super()._sendPacket("this_is_a_2nd_notification", prefix="%")
+            self.sent_notification = True
+
+        super()._sendPacket(packet)
+
+
+class TestIgnoringNotifications(GDBRemoteTestBase):
+    def setUp(self):
+        TestBase.setUp(self)
+        self.server = NotifyingServer(self.server_socket_class())
+        self.server.start()
+
+    @skipIfLLVMTargetMissing("AArch64")
+    def test(self):
+        target = self.createTarget("basic_eh_frame-aarch64.yaml")
+
+        if self.TraceOn():
+            self.runCmd("log enable gdb-remote packets")
+            self.addTearDownHook(lambda: self.runCmd("log disable gdb-remote 
packets"))
+
+        process = self.connect(target)
+        lldbutil.expect_state_changes(
+            self, self.dbg.GetListener(), process, [lldb.eStateStopped]
+        )
+
+        # Disabling cache is not required but makes debugging this test easier.
+        self.runCmd("settings set target.process.disable-memory-cache true")
+
+        # Should succeed despite getting a notification before the real result.
+        self.expect("memory read --format hex 0x1234 0x1238", 
substrs=["0x01010101"])
+
+        # Check we didn't succeed because lldb got memory in some other way.
+        self.assertTrue(self.server.sent_notification)

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to