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)