import asyncio from unittest.mock import Mock import pytest from sanic import Sanic from sanic.exceptions import RequestTimeout, ServiceUnavailable from sanic.http import Stage from sanic.server import HttpProtocol @pytest.fixture def app(): return Sanic("test") @pytest.fixture def mock_transport(): return Mock() @pytest.fixture def protocol(app, mock_transport): loop = asyncio.new_event_loop() protocol = HttpProtocol(loop=loop, app=app) protocol.connection_made(mock_transport) protocol._setup_connection() protocol._http.init_for_request() protocol._task = Mock(spec=asyncio.Task) protocol._task.cancel = Mock() return protocol def test_setup(protocol: HttpProtocol): assert protocol._task is not None assert protocol._http is not None assert protocol._time is not None def test_check_timeouts_no_timeout(protocol: HttpProtocol): protocol.keep_alive_timeout = 1 protocol.loop.call_later = Mock() protocol.check_timeouts() protocol._task.cancel.assert_not_called() assert protocol._http.stage is Stage.IDLE assert protocol._http.exception is None protocol.loop.call_later.assert_called_with( protocol.keep_alive_timeout / 2, protocol.check_timeouts ) def test_check_timeouts_keep_alive_timeout(protocol: HttpProtocol): protocol._http.stage = Stage.IDLE protocol._time = 0 protocol.check_timeouts() protocol._task.cancel.assert_called_once() assert protocol._http.exception is None def test_check_timeouts_request_timeout(protocol: HttpProtocol): protocol._http.stage = Stage.REQUEST protocol._time = 0 protocol.check_timeouts() protocol._task.cancel.assert_called_once() assert isinstance(protocol._http.exception, RequestTimeout) def test_check_timeouts_response_timeout(protocol: HttpProtocol): protocol._http.stage = Stage.RESPONSE protocol._time = 0 protocol.check_timeouts() protocol._task.cancel.assert_called_once() assert isinstance(protocol._http.exception, ServiceUnavailable)