Skip to content

Commit d375f3e

Browse files
committed
test: use anyio's free_tcp_port fixture instead of hand-rolled helper
The anyio pytest plugin's free_tcp_port fixture tracks allocated ports within a session so concurrent tests don't step on each other, which the hand-rolled bind-and-close approach doesn't guarantee.
1 parent d297fcf commit d375f3e

File tree

1 file changed

+4
-16
lines changed

1 file changed

+4
-16
lines changed

tests/client/test_transport_stream_cleanup.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
"""
1313

1414
import gc
15-
import socket
1615
import sys
1716
from collections.abc import Iterator
1817
from contextlib import contextmanager
@@ -26,13 +25,6 @@
2625
from mcp.client.websocket import websocket_client
2726

2827

29-
def _unused_tcp_port() -> int:
30-
"""Return a port with no listener. Binding then closing leaves the port unbound."""
31-
with socket.socket() as s:
32-
s.bind(("127.0.0.1", 0))
33-
return s.getsockname()[1]
34-
35-
3628
@contextmanager
3729
def _assert_no_memory_stream_leak() -> Iterator[None]:
3830
"""Fail if any anyio MemoryObject stream emits ResourceWarning during the block.
@@ -63,19 +55,17 @@ def hook(args: Any) -> None: # pragma: no cover
6355

6456

6557
@pytest.mark.anyio
66-
async def test_sse_client_closes_all_streams_on_connection_error() -> None:
58+
async def test_sse_client_closes_all_streams_on_connection_error(free_tcp_port: int) -> None:
6759
"""sse_client must close all 4 stream ends when the connection fails.
6860
6961
Before the fix, only read_stream_writer and write_stream were closed in
7062
the finally block. read_stream and write_stream_reader were leaked.
7163
"""
72-
port = _unused_tcp_port()
73-
7464
with _assert_no_memory_stream_leak():
7565
# sse_client enters a task group BEFORE connecting, so anyio wraps the
7666
# ConnectError from aconnect_sse in an ExceptionGroup.
7767
with pytest.raises(Exception) as exc_info: # noqa: B017
78-
async with sse_client(f"http://127.0.0.1:{port}/sse"):
68+
async with sse_client(f"http://127.0.0.1:{free_tcp_port}/sse"):
7969
pytest.fail("should not reach here") # pragma: no cover
8070

8171
assert exc_info.group_contains(httpx.ConnectError)
@@ -98,15 +88,13 @@ async def test_streamable_http_client_closes_all_streams_on_exit() -> None:
9888

9989

10090
@pytest.mark.anyio
101-
async def test_websocket_client_closes_all_streams_on_connection_error() -> None:
91+
async def test_websocket_client_closes_all_streams_on_connection_error(free_tcp_port: int) -> None:
10292
"""websocket_client must close all 4 stream ends when ws_connect fails.
10393
10494
Before the fix, there was no try/finally at all — if ws_connect raised,
10595
all 4 streams were leaked.
10696
"""
107-
port = _unused_tcp_port()
108-
10997
with _assert_no_memory_stream_leak():
11098
with pytest.raises(OSError):
111-
async with websocket_client(f"ws://127.0.0.1:{port}/ws"):
99+
async with websocket_client(f"ws://127.0.0.1:{free_tcp_port}/ws"):
112100
pytest.fail("should not reach here") # pragma: no cover

0 commit comments

Comments
 (0)