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):
    SHARED_BUILD_TESTCASE = False

    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)
