1import lldb 2from lldbsuite.test.lldbtest import * 3from lldbsuite.test.decorators import * 4from lldbsuite.test.gdbclientutils import * 5from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase 6 7 8@skipIfWindows 9class TestPty(GDBRemoteTestBase): 10 server_socket_class = PtyServerSocket 11 12 def get_term_attrs(self): 13 import termios 14 return termios.tcgetattr(self._secondary_socket) 15 16 def setUp(self): 17 super().setUp() 18 # Duplicate the pty descriptors so we can inspect the pty state after 19 # they are closed 20 self._primary_socket = os.dup(self.server._socket._primary.name) 21 self._secondary_socket = os.dup(self.server._socket._secondary.name) 22 self.orig_attr = self.get_term_attrs() 23 24 def assert_raw_mode(self, current_attr): 25 import termios 26 self.assertEqual(current_attr[0] & (termios.BRKINT | 27 termios.PARMRK | 28 termios.ISTRIP | termios.INLCR | 29 termios.IGNCR | termios.ICRNL | 30 termios.IXON), 31 0) 32 self.assertEqual(current_attr[1] & termios.OPOST, 0) 33 self.assertEqual(current_attr[2] & termios.CSIZE, termios.CS8) 34 self.assertEqual(current_attr[3] & (termios.ICANON | termios.ECHO | 35 termios.ISIG | termios.IEXTEN), 36 0) 37 self.assertEqual(current_attr[6][termios.VMIN], 1) 38 self.assertEqual(current_attr[6][termios.VTIME], 0) 39 40 def get_parity_flags(self, attr): 41 import termios 42 return attr[2] & (termios.PARENB | termios.PARODD) 43 44 def get_stop_bit_flags(self, attr): 45 import termios 46 return attr[2] & termios.CSTOPB 47 48 def test_process_connect_sync(self): 49 """Test the process connect command in synchronous mode""" 50 try: 51 self.dbg.SetAsync(False) 52 self.expect("platform select remote-gdb-server", 53 substrs=['Platform: remote-gdb-server', 'Connected: no']) 54 self.expect("process connect " + self.server.get_connect_url(), 55 substrs=['Process', 'stopped']) 56 57 current_attr = self.get_term_attrs() 58 # serial:// should set raw mode 59 self.assert_raw_mode(current_attr) 60 # other parameters should be unmodified 61 self.assertEqual(current_attr[4:6], self.orig_attr[4:6]) 62 self.assertEqual(self.get_parity_flags(current_attr), 63 self.get_parity_flags(self.orig_attr)) 64 self.assertEqual(self.get_stop_bit_flags(current_attr), 65 self.get_stop_bit_flags(self.orig_attr)) 66 finally: 67 self.dbg.GetSelectedTarget().GetProcess().Kill() 68 # original mode should be restored on exit 69 self.assertEqual(self.get_term_attrs(), self.orig_attr) 70 71 def test_process_connect_async(self): 72 """Test the process connect command in asynchronous mode""" 73 try: 74 self.dbg.SetAsync(True) 75 self.expect("platform select remote-gdb-server", 76 substrs=['Platform: remote-gdb-server', 'Connected: no']) 77 self.expect("process connect " + self.server.get_connect_url(), 78 matching=False, 79 substrs=['Process', 'stopped']) 80 lldbutil.expect_state_changes(self, self.dbg.GetListener(), 81 self.process(), [lldb.eStateStopped]) 82 83 current_attr = self.get_term_attrs() 84 # serial:// should set raw mode 85 self.assert_raw_mode(current_attr) 86 # other parameters should be unmodified 87 self.assertEqual(current_attr[4:6], self.orig_attr[4:6]) 88 self.assertEqual(self.get_parity_flags(current_attr), 89 self.get_parity_flags(self.orig_attr)) 90 self.assertEqual(self.get_stop_bit_flags(current_attr), 91 self.get_stop_bit_flags(self.orig_attr)) 92 finally: 93 self.dbg.GetSelectedTarget().GetProcess().Kill() 94 lldbutil.expect_state_changes(self, self.dbg.GetListener(), 95 self.process(), [lldb.eStateExited]) 96 # original mode should be restored on exit 97 self.assertEqual(self.get_term_attrs(), self.orig_attr) 98 99 def test_connect_via_file(self): 100 """Test connecting via the legacy file:// URL""" 101 import termios 102 try: 103 self.expect("platform select remote-gdb-server", 104 substrs=['Platform: remote-gdb-server', 'Connected: no']) 105 self.expect("process connect file://" + 106 self.server.get_connect_address(), 107 substrs=['Process', 'stopped']) 108 109 # file:// sets baud rate and some raw-related flags 110 current_attr = self.get_term_attrs() 111 self.assertEqual(current_attr[3] & (termios.ICANON | termios.ECHO | 112 termios.ECHOE | termios.ISIG), 113 0) 114 self.assertEqual(current_attr[4], termios.B115200) 115 self.assertEqual(current_attr[5], termios.B115200) 116 self.assertEqual(current_attr[6][termios.VMIN], 1) 117 self.assertEqual(current_attr[6][termios.VTIME], 0) 118 finally: 119 self.dbg.GetSelectedTarget().GetProcess().Kill() 120 121 def test_process_connect_params(self): 122 """Test serial:// URL with parameters""" 123 import termios 124 try: 125 self.expect("platform select remote-gdb-server", 126 substrs=['Platform: remote-gdb-server', 'Connected: no']) 127 self.expect("process connect " + self.server.get_connect_url() + 128 "?baud=115200&stop-bits=2", 129 substrs=['Process', 'stopped']) 130 131 current_attr = self.get_term_attrs() 132 self.assert_raw_mode(current_attr) 133 self.assertEqual(current_attr[4:6], 2 * [termios.B115200]) 134 self.assertEqual(self.get_parity_flags(current_attr), 135 self.get_parity_flags(self.orig_attr)) 136 self.assertEqual(self.get_stop_bit_flags(current_attr), 137 termios.CSTOPB) 138 finally: 139 self.dbg.GetSelectedTarget().GetProcess().Kill() 140 # original mode should be restored on exit 141 self.assertEqual(self.get_term_attrs(), self.orig_attr) 142