import lldb from lldbsuite.test.lldbtest import * from lldbsuite.test.decorators import * from lldbsuite.test.gdbclientutils import * from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase @skipIf(hostoslist=["windows"]) class TestPty(GDBRemoteTestBase): server_socket_class = PtyServerSocket def get_term_attrs(self): import termios return termios.tcgetattr(self._secondary_socket) def setUp(self): super().setUp() # Duplicate the pty descriptors so we can inspect the pty state after # they are closed self._primary_socket = os.dup(self.server._socket._primary.name) self._secondary_socket = os.dup(self.server._socket._secondary.name) self.orig_attr = self.get_term_attrs() def assert_raw_mode(self, current_attr): import termios self.assertEqual( current_attr[0] & ( termios.BRKINT | termios.PARMRK | termios.ISTRIP | termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IXON ), 0, ) self.assertEqual(current_attr[1] & termios.OPOST, 0) self.assertEqual(current_attr[2] & termios.CSIZE, termios.CS8) self.assertEqual( current_attr[3] & (termios.ICANON | termios.ECHO | termios.ISIG | termios.IEXTEN), 0, ) self.assertEqual(current_attr[6][termios.VMIN], 1) self.assertEqual(current_attr[6][termios.VTIME], 0) def get_parity_flags(self, attr): import termios return attr[2] & (termios.PARENB | termios.PARODD) def get_stop_bit_flags(self, attr): import termios return attr[2] & termios.CSTOPB def test_process_connect_sync(self): """Test the process connect 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 " + self.server.get_connect_url(), substrs=["Process", "stopped"], ) current_attr = self.get_term_attrs() # serial:// should set raw mode self.assert_raw_mode(current_attr) # other parameters should be unmodified self.assertEqual(current_attr[4:6], self.orig_attr[4:6]) self.assertEqual( self.get_parity_flags(current_attr), self.get_parity_flags(self.orig_attr), ) self.assertEqual( self.get_stop_bit_flags(current_attr), self.get_stop_bit_flags(self.orig_attr), ) finally: self.dbg.GetSelectedTarget().GetProcess().Kill() # original mode should be restored on exit self.assertEqual(self.get_term_attrs(), self.orig_attr) def test_process_connect_async(self): """Test the process connect command in asynchronous mode""" try: self.dbg.SetAsync(True) self.expect( "platform select remote-gdb-server", substrs=["Platform: remote-gdb-server", "Connected: no"], ) self.expect( "process connect " + self.server.get_connect_url(), matching=False, substrs=["Process", "stopped"], ) lldbutil.expect_state_changes( self, self.dbg.GetListener(), self.process(), [lldb.eStateStopped] ) current_attr = self.get_term_attrs() # serial:// should set raw mode self.assert_raw_mode(current_attr) # other parameters should be unmodified self.assertEqual(current_attr[4:6], self.orig_attr[4:6]) self.assertEqual( self.get_parity_flags(current_attr), self.get_parity_flags(self.orig_attr), ) self.assertEqual( self.get_stop_bit_flags(current_attr), self.get_stop_bit_flags(self.orig_attr), ) finally: self.dbg.GetSelectedTarget().GetProcess().Kill() lldbutil.expect_state_changes( self, self.dbg.GetListener(), self.process(), [lldb.eStateExited] ) # original mode should be restored on exit self.assertEqual(self.get_term_attrs(), self.orig_attr) def test_connect_via_file(self): """Test connecting via the legacy file:// URL""" import termios try: 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"], ) # file:// sets baud rate and some raw-related flags current_attr = self.get_term_attrs() self.assertEqual( current_attr[3] & (termios.ICANON | termios.ECHO | termios.ECHOE | termios.ISIG), 0, ) self.assertEqual(current_attr[4], termios.B115200) self.assertEqual(current_attr[5], termios.B115200) self.assertEqual(current_attr[6][termios.VMIN], 1) self.assertEqual(current_attr[6][termios.VTIME], 0) finally: self.dbg.GetSelectedTarget().GetProcess().Kill() def test_process_connect_params(self): """Test serial:// URL with parameters""" import termios try: self.expect( "platform select remote-gdb-server", substrs=["Platform: remote-gdb-server", "Connected: no"], ) self.expect( "process connect " + self.server.get_connect_url() + "?baud=115200&stop-bits=2", substrs=["Process", "stopped"], ) current_attr = self.get_term_attrs() self.assert_raw_mode(current_attr) self.assertEqual(current_attr[4:6], 2 * [termios.B115200]) self.assertEqual( self.get_parity_flags(current_attr), self.get_parity_flags(self.orig_attr), ) self.assertEqual(self.get_stop_bit_flags(current_attr), termios.CSTOPB) finally: self.dbg.GetSelectedTarget().GetProcess().Kill() # original mode should be restored on exit self.assertEqual(self.get_term_attrs(), self.orig_attr)