import asyncio
from contextlib import suppress
from unittest import mock

import pytest

from aiohttp.base_protocol import BaseProtocol


async def test_loop() -> None:
    loop = asyncio.get_event_loop()
    asyncio.set_event_loop(None)
    pr = BaseProtocol(loop)
    assert pr._loop is loop


async def test_pause_writing() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop)
    assert not pr._paused
    pr.pause_writing()
    assert pr._paused


async def test_resume_writing_no_waiters() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    pr.pause_writing()
    assert pr._paused
    pr.resume_writing()
    assert not pr._paused


async def test_connection_made() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    assert pr.transport is None
    pr.connection_made(tr)
    assert pr.transport is not None


async def test_connection_lost_not_paused() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    pr.connection_made(tr)
    assert not pr._connection_lost
    pr.connection_lost(None)
    assert pr.transport is None
    assert pr._connection_lost


async def test_connection_lost_paused_without_waiter() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    pr.connection_made(tr)
    assert not pr._connection_lost
    pr.pause_writing()
    pr.connection_lost(None)
    assert pr.transport is None
    assert pr._connection_lost


async def test_drain_lost() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    pr.connection_made(tr)
    pr.connection_lost(None)
    with pytest.raises(ConnectionResetError):
        await pr._drain_helper()


async def test_drain_not_paused() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    pr.connection_made(tr)
    assert pr._drain_waiter is None
    await pr._drain_helper()
    assert pr._drain_waiter is None


async def test_resume_drain_waited() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    pr.connection_made(tr)
    pr.pause_writing()

    t = loop.create_task(pr._drain_helper())
    await asyncio.sleep(0)

    assert pr._drain_waiter is not None
    pr.resume_writing()
    assert (await t) is None
    assert pr._drain_waiter is None


async def test_lost_drain_waited_ok() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    pr.connection_made(tr)
    pr.pause_writing()

    t = loop.create_task(pr._drain_helper())
    await asyncio.sleep(0)

    assert pr._drain_waiter is not None
    pr.connection_lost(None)
    assert (await t) is None
    assert pr._drain_waiter is None


async def test_lost_drain_waited_exception() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    pr.connection_made(tr)
    pr.pause_writing()

    t = loop.create_task(pr._drain_helper())
    await asyncio.sleep(0)

    assert pr._drain_waiter is not None
    exc = RuntimeError()
    pr.connection_lost(exc)
    with pytest.raises(RuntimeError) as cm:
        await t
    assert cm.value is exc
    assert pr._drain_waiter is None


async def test_lost_drain_cancelled() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    pr.connection_made(tr)
    pr.pause_writing()

    fut = loop.create_future()

    async def wait():
        fut.set_result(None)
        await pr._drain_helper()

    t = loop.create_task(wait())
    await fut
    t.cancel()

    assert pr._drain_waiter is not None
    pr.connection_lost(None)
    with suppress(asyncio.CancelledError):
        await t
    assert pr._drain_waiter is None


async def test_resume_drain_cancelled() -> None:
    loop = asyncio.get_event_loop()
    pr = BaseProtocol(loop=loop)
    tr = mock.Mock()
    pr.connection_made(tr)
    pr.pause_writing()

    fut = loop.create_future()

    async def wait():
        fut.set_result(None)
        await pr._drain_helper()

    t = loop.create_task(wait())
    await fut
    t.cancel()

    assert pr._drain_waiter is not None
    pr.resume_writing()
    with suppress(asyncio.CancelledError):
        await t
    assert pr._drain_waiter is None

[((11, 11, 11, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((12, 4, 12, 32), 'asyncio.set_event_loop', 'asyncio.set_event_loop', ({(12, 27, 12, 31): 'None'}, {}), '(None)', False, 'import asyncio\n'), ((13, 9, 13, 27), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', ({(13, 22, 13, 26): 'loop'}, {}), '(loop)', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((18, 11, 18, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((19, 9, 19, 27), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', ({(19, 22, 19, 26): 'loop'}, {}), '(loop)', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((26, 11, 26, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((27, 9, 27, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((35, 11, 35, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((36, 9, 36, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((37, 9, 37, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((44, 11, 44, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((45, 9, 45, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((46, 9, 46, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((55, 11, 55, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((56, 9, 56, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((57, 9, 57, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((67, 11, 67, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((68, 9, 68, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((69, 9, 69, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((77, 11, 77, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((78, 9, 78, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((79, 9, 79, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((87, 11, 87, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((88, 9, 88, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((89, 9, 89, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((103, 11, 103, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((104, 9, 104, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((105, 9, 105, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((119, 11, 119, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((120, 9, 120, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((121, 9, 121, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((138, 11, 138, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((139, 9, 139, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((140, 9, 140, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((162, 11, 162, 35), 'asyncio.get_event_loop', 'asyncio.get_event_loop', ({}, {}), '()', False, 'import asyncio\n'), ((163, 9, 163, 32), 'aiohttp.base_protocol.BaseProtocol', 'BaseProtocol', (), '', False, 'from aiohttp.base_protocol import BaseProtocol\n'), ((164, 9, 164, 20), 'unittest.mock.Mock', 'mock.Mock', ({}, {}), '()', False, 'from unittest import mock\n'), ((72, 9, 72, 44), 'pytest.raises', 'pytest.raises', ({(72, 23, 72, 43): 'ConnectionResetError'}, {}), '(ConnectionResetError)', False, 'import pytest\n'), ((94, 10, 94, 26), 'asyncio.sleep', 'asyncio.sleep', ({(94, 24, 94, 25): '(0)'}, {}), '(0)', False, 'import asyncio\n'), ((110, 10, 110, 26), 'asyncio.sleep', 'asyncio.sleep', ({(110, 24, 110, 25): '(0)'}, {}), '(0)', False, 'import asyncio\n'), ((126, 10, 126, 26), 'asyncio.sleep', 'asyncio.sleep', ({(126, 24, 126, 25): '(0)'}, {}), '(0)', False, 'import asyncio\n'), ((131, 9, 131, 36), 'pytest.raises', 'pytest.raises', ({(131, 23, 131, 35): 'RuntimeError'}, {}), '(RuntimeError)', False, 'import pytest\n'), ((156, 9, 156, 41), 'contextlib.suppress', 'suppress', ({(156, 18, 156, 40): 'asyncio.CancelledError'}, {}), '(asyncio.CancelledError)', False, 'from contextlib import suppress\n'), ((180, 9, 180, 41), 'contextlib.suppress', 'suppress', ({(180, 18, 180, 40): 'asyncio.CancelledError'}, {}), '(asyncio.CancelledError)', False, 'from contextlib import suppress\n')]