Skip to content

[PR #10898/a4be2cb backport][3.12] Cleanup tests to ensure connector cleanup and resource management #10900

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 58 additions & 48 deletions tests/test_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,80 +307,90 @@ async def test_close(loop) -> None:

async def test_get(loop: asyncio.AbstractEventLoop, key: ConnectionKey) -> None:
conn = aiohttp.BaseConnector()
assert await conn._get(key, []) is None
try:
assert await conn._get(key, []) is None

proto = create_mocked_conn(loop)
conn._conns[key] = deque([(proto, loop.time())])
connection = await conn._get(key, [])
assert connection is not None
assert connection.protocol == proto
connection.close()
await conn.close()
proto = create_mocked_conn(loop)
conn._conns[key] = deque([(proto, loop.time())])
connection = await conn._get(key, [])
assert connection is not None
assert connection.protocol == proto
connection.close()
finally:
await conn.close()


async def test_get_unconnected_proto(loop) -> None:
conn = aiohttp.BaseConnector()
key = ConnectionKey("localhost", 80, False, False, None, None, None)
assert await conn._get(key, []) is None

proto = create_mocked_conn(loop)
conn._conns[key] = deque([(proto, loop.time())])
connection = await conn._get(key, [])
assert connection is not None
assert connection.protocol == proto
connection.close()
try:
assert await conn._get(key, []) is None

assert await conn._get(key, []) is None
conn._conns[key] = deque([(proto, loop.time())])
proto.is_connected = lambda *args: False
assert await conn._get(key, []) is None
await conn.close()
proto = create_mocked_conn(loop)
conn._conns[key] = deque([(proto, loop.time())])
connection = await conn._get(key, [])
assert connection is not None
assert connection.protocol == proto
connection.close()

assert await conn._get(key, []) is None
conn._conns[key] = deque([(proto, loop.time())])
proto.is_connected = lambda *args: False
assert await conn._get(key, []) is None
finally:
await conn.close()


async def test_get_unconnected_proto_ssl(loop) -> None:
conn = aiohttp.BaseConnector()
key = ConnectionKey("localhost", 80, True, False, None, None, None)
assert await conn._get(key, []) is None

proto = create_mocked_conn(loop)
conn._conns[key] = deque([(proto, loop.time())])
connection = await conn._get(key, [])
assert connection is not None
assert connection.protocol == proto
connection.close()
try:
assert await conn._get(key, []) is None

assert await conn._get(key, []) is None
conn._conns[key] = deque([(proto, loop.time())])
proto.is_connected = lambda *args: False
assert await conn._get(key, []) is None
await conn.close()
proto = create_mocked_conn(loop)
conn._conns[key] = deque([(proto, loop.time())])
connection = await conn._get(key, [])
assert connection is not None
assert connection.protocol == proto
connection.close()

assert await conn._get(key, []) is None
conn._conns[key] = deque([(proto, loop.time())])
proto.is_connected = lambda *args: False
assert await conn._get(key, []) is None
finally:
await conn.close()


async def test_get_expired(loop: asyncio.AbstractEventLoop) -> None:
conn = aiohttp.BaseConnector()
key = ConnectionKey("localhost", 80, False, False, None, None, None)
assert await conn._get(key, []) is None
try:
assert await conn._get(key, []) is None

proto = mock.Mock()
conn._conns[key] = deque([(proto, loop.time() - 1000)])
assert await conn._get(key, []) is None
assert not conn._conns
await conn.close()
proto = create_mocked_conn(loop)
conn._conns[key] = deque([(proto, loop.time() - 1000)])
assert await conn._get(key, []) is None
assert not conn._conns
finally:
await conn.close()


@pytest.mark.usefixtures("enable_cleanup_closed")
async def test_get_expired_ssl(loop: asyncio.AbstractEventLoop) -> None:
conn = aiohttp.BaseConnector(enable_cleanup_closed=True)
key = ConnectionKey("localhost", 80, True, False, None, None, None)
assert await conn._get(key, []) is None
try:
assert await conn._get(key, []) is None

proto = mock.Mock()
transport = proto.transport
conn._conns[key] = deque([(proto, loop.time() - 1000)])
assert await conn._get(key, []) is None
assert not conn._conns
assert conn._cleanup_closed_transports == [transport]
await conn.close()
proto = create_mocked_conn(loop)
transport = proto.transport
conn._conns[key] = deque([(proto, loop.time() - 1000)])
assert await conn._get(key, []) is None
assert not conn._conns
assert conn._cleanup_closed_transports == [transport]
finally:
await conn.close()


async def test_release_acquired(loop, key) -> None:
Expand Down
18 changes: 11 additions & 7 deletions tests/test_proxy_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,18 @@ async def test_uvloop_secure_https_proxy(
"""Ensure HTTPS sites are accessible through a secure proxy without warning when using uvloop."""
conn = aiohttp.TCPConnector()
sess = aiohttp.ClientSession(connector=conn)
url = URL("https://example.com")

async with sess.get(url, proxy=secure_proxy_url, ssl=client_ssl_ctx) as response:
assert response.status == 200
try:
url = URL("https://example.com")

await sess.close()
await conn.close()
await asyncio.sleep(0.1)
async with sess.get(
url, proxy=secure_proxy_url, ssl=client_ssl_ctx
) as response:
assert response.status == 200
finally:
await sess.close()
await conn.close()
await asyncio.sleep(0)
await asyncio.sleep(0.1)


@pytest.fixture
Expand Down
Loading