mgorny created this revision.
mgorny added reviewers: labath, teemperor, krytarowski, emaste.
mgorny requested review of this revision.

Add a minimal mock server utilizing a pty, and add a client test
connecting to that server.


https://reviews.llvm.org/D110878

Files:
  lldb/test/API/functionalities/gdb_remote_client/TestPty.py
  lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py

Index: lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
===================================================================
--- lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
+++ lldb/test/API/functionalities/gdb_remote_client/gdbclientutils.py
@@ -1,8 +1,12 @@
+import ctypes
 import errno
+import io
 import os
 import os.path
+import pty
 import threading
 import socket
+import tty
 import lldb
 import binascii
 import traceback
@@ -352,21 +356,26 @@
     def __init__(self):
         self.responder = MockGDBServerResponder()
 
-    def start(self):
+    def _bind_and_listen(self):
         family, type, proto, _, addr = socket.getaddrinfo("localhost", 0,
                 proto=socket.IPPROTO_TCP)[0]
-        self._socket = socket.socket(family, type, proto)
-
+        sock = socket.socket(family, type, proto)
 
-        self._socket.bind(addr)
-        self._socket.listen(1)
+        sock.bind(addr)
+        sock.listen(1)
+        return sock
 
+    def start(self):
+        self._socket = self._bind_and_listen()
         # Start a thread that waits for a client connection.
         self._thread = threading.Thread(target=self._run)
         self._thread.start()
 
-    def stop(self):
+    def _close(self):
         self._socket.close()
+
+    def stop(self):
+        self._close()
         self._thread.join()
         self._thread = None
 
@@ -510,6 +519,51 @@
     class InvalidPacketException(Exception):
         pass
 
+
+class PtySocket(io.FileIO):
+    """Pseudo-pocket wrapping a pty."""
+
+    def __init__(self, fd):
+        tty.setraw(fd)
+        super().__init__(fd, 'r+')
+
+    def accept(self):
+        return self, ''
+
+    def close(self):
+        # the socket is reused, so don't close it yet
+        pass
+
+    def recv(self, size):
+        return self.read(size)
+
+    def sendall(self, data):
+        return self.write(data)
+
+    def settimeout(self, timeout):
+        pass
+
+
+class MockPtyGDBServer(MockGDBServer):
+    """
+    A variation of MockGDBServer that uses a pty instead of TCP.
+    """
+
+    def _bind_and_listen(self):
+        self._master, self._slave = pty.openpty()
+        return PtySocket(self._master)
+
+    def _close(self):
+        os.close(self._slave)
+        os.close(self._master)
+
+    def get_connect_address(self):
+        libc = ctypes.CDLL(None)
+        libc.ptsname.argtypes = (ctypes.c_int,)
+        libc.ptsname.restype = ctypes.c_char_p
+        return libc.ptsname(self._master).decode()
+
+
 class GDBRemoteTestBase(TestBase):
     """
     Base class for GDB client tests.
Index: lldb/test/API/functionalities/gdb_remote_client/TestPty.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/gdb_remote_client/TestPty.py
@@ -0,0 +1,32 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from gdbclientutils import *
+
+
+class TestPty(TestBase):
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        super().setUp()
+        self.server = MockPtyGDBServer()
+        self.server.start()
+
+    def tearDown(self):
+        if self.process() is not None:
+            self.process().Kill()
+        self.server.stop()
+        super().tearDown()
+
+    @skipIfWindows
+    def test_process_connect_sync(self):
+        """Test the gdb-remote command in synchronous mode"""
+        try:
+            self.dbg.SetAsync(False)
+            self.expect("platform select remote-gdb-server",
+                        substrs=['Platform: remote-gdb-server', 'Connected: no'])
+            self.expect("process connect file://" +
+                        self.server.get_connect_address(),
+                        substrs=['Process', 'stopped'])
+        finally:
+            self.dbg.GetSelectedPlatform().DisconnectRemote()
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to