# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import asyncio
import unittest

from fuchsia_controller_py import Context, FcTransportStatus, Socket

from fidl import AlreadyReadingAll, AsyncChannel, AsyncSocket


class SocketTests(unittest.IsolatedAsyncioTestCase):
    """Socket tests."""

    async def test_socket_write_then_read(self) -> None:
        """Tests a simple write followed by an immediate read."""
        ctx = Context()
        (sock_out, sock_in) = ctx.socket_create()
        bytes_in = bytearray([1, 2, 3])
        sock_out.write(bytes_in)
        async_sock_in = AsyncSocket(sock_in)
        bytes_out = await async_sock_in.read()
        self.assertEqual(bytes_out, bytes_in)

    def test_socket_write_fails_when_closed(self) -> None:
        """Verifies FC_ERR_SOCKET_WRITE is surfaced when opposing socket is closed."""
        ctx = Context()
        (sock_out, sock_in) = ctx.socket_create()
        del sock_in
        with self.assertRaises(FcTransportStatus):
            try:
                sock_out.write(bytearray([1, 2, 3]))
            except FcTransportStatus as e:
                self.assertEqual(
                    e.code(), FcTransportStatus.FC_ERR_SOCKET_WRITE
                )
                raise e

    async def test_socket_passing(self) -> None:
        """Verifies a socket remains connected when passed through a channel."""
        ctx = Context()
        (chan_out, chan_in) = ctx.channel_create()
        (sock_out, sock_in) = ctx.socket_create()
        # This is using 'take' rather than 'as_int' as using 'as_int' would cause a double-close
        # error on a channel that has already been closed.
        chan_out.write((bytearray(), [(0, sock_out.take(), 0, 0, 0)]))
        async_chan_in = AsyncChannel(chan_in)
        _, hdls = await async_chan_in.read()
        self.assertEqual(len(hdls), 1)
        bytes_in = bytearray([1, 2, 3])
        new_sock_out = Socket(hdls[0])
        new_sock_out.write(bytes_in)
        async_sock_in = AsyncSocket(sock_in)
        bytes_out = await async_sock_in.read()
        self.assertEqual(bytes_out, bytes_in)

    async def test_async_socket(self) -> None:
        """Verifies an async socket is able to wait for the other end to complete writing."""
        ctx = Context()
        (sock_out, sock_in) = ctx.socket_create()
        async_sock_in = AsyncSocket(sock_in)
        bytes_in = bytearray([1, 2, 3])

        async def slow_write() -> None:
            await asyncio.sleep(1)
            sock_out.write(bytes_in)

        loop = asyncio.get_running_loop()
        write_task = loop.create_task(slow_write())
        read_task = loop.create_task(async_sock_in.read())
        done, _ = await asyncio.wait([write_task, read_task])
        self.assertEqual(len(done), 2)
        read_bytes = None
        for item in done:
            if item.result() is not None:
                read_bytes = item.result()
        self.assertEqual(read_bytes, bytes_in)

    async def test_async_socket_write_fails_when_closed(self) -> None:
        """Verifies an async socket write fails in the expected way when the other end is closed."""
        ctx = Context()
        (sock_out, sock_in) = ctx.socket_create()
        del sock_in
        with self.assertRaises(FcTransportStatus):
            async_sock_out = AsyncSocket(sock_out)
            try:
                async_sock_out.write(bytearray([1, 2, 3]))
            except FcTransportStatus as e:
                self.assertEqual(
                    e.code(), FcTransportStatus.FC_ERR_SOCKET_WRITE
                )
                raise e

    async def test_async_socket_read_fails_when_closed(self) -> None:
        """Verifies an async socket read fails in the expected way when the other end is closed."""
        ctx = Context()
        (sock_out, sock_in) = ctx.socket_create()
        del sock_out
        with self.assertRaises(FcTransportStatus):
            async_sock_in = AsyncSocket(sock_in)
            try:
                await async_sock_in.read()
            except FcTransportStatus as e:
                self.assertEqual(e.code(), FcTransportStatus.FC_ERR_FDOMAIN)
                raise e

    async def test_async_socket_read_all_twice_fails(self) -> None:
        """Verifies running `read_all()` twice fails."""
        ctx = Context()
        (sock_out, sock_in) = ctx.socket_create()
        with self.assertRaises(AlreadyReadingAll):
            async_sock_in = AsyncSocket(sock_in)
            task = asyncio.get_running_loop().create_task(
                async_sock_in.read_all()
            )
            await asyncio.gather(async_sock_in.read_all(), task)

    async def test_async_socket_read_all_then_read_fails(self) -> None:
        """Verifies running `read_all()` then `read()` fails."""
        ctx = Context()
        (sock_out, sock_in) = ctx.socket_create()
        with self.assertRaises(AlreadyReadingAll):
            async_sock_in = AsyncSocket(sock_in)
            task = asyncio.get_running_loop().create_task(
                async_sock_in.read_all()
            )
            await asyncio.gather(async_sock_in.read(), task)
