test(mcp): cancel leaked stateful auth-context cleanup task
Some checks failed
Unit Tests: Caching (Redis) / caching-redis (push) Has been cancelled
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled

initialize_session_managers() spawns a real asyncio.create_task running
_cleanup_expired_stateful_session_auth_contexts(). The
test_concurrent_initialize_session_managers test was saving and
restoring the session-manager context-manager globals but did not save,
cancel, or restore _stateful_auth_context_cleanup_task.

Because pyproject.toml sets asyncio_default_fixture_loop_scope=session,
the event loop is shared across tests in the same session, so the
leaked task kept running against module-level dicts for the rest of the
test run. Save and cancel the task in the finally block so the test
fully cleans up after itself.

Co-authored-by: Mateo Wang <mateo-berri@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-05-06 01:02:28 +00:00
parent 6cd7bb401e
commit e5c458d51a
No known key found for this signature in database

View file

@ -1,4 +1,5 @@
import asyncio
import contextlib
import contextvars
from datetime import datetime, timedelta
from unittest.mock import AsyncMock, MagicMock, patch
@ -1003,12 +1004,14 @@ async def test_concurrent_initialize_session_managers():
original_session_cm = mcp_server._session_manager_cm
original_session_stateful_cm = mcp_server._session_manager_stateful_cm
original_sse_session_cm = mcp_server._sse_session_manager_cm
original_cleanup_task = mcp_server._stateful_auth_context_cleanup_task
try:
mcp_server._SESSION_MANAGERS_INITIALIZED = False
mcp_server._session_manager_cm = None
mcp_server._session_manager_stateful_cm = None
mcp_server._sse_session_manager_cm = None
mcp_server._stateful_auth_context_cleanup_task = None
# Mock the session managers to avoid actual MCP initialization
with (
@ -1066,11 +1069,21 @@ async def test_concurrent_initialize_session_managers():
assert mcp_server._SESSION_MANAGERS_INITIALIZED is True
finally:
# Cancel the background cleanup task that initialize_session_managers()
# spawned. Otherwise it keeps running against module-level dicts for the
# rest of the test session (asyncio_default_fixture_loop_scope=session).
leaked_task = mcp_server._stateful_auth_context_cleanup_task
if leaked_task is not None and leaked_task is not original_cleanup_task:
leaked_task.cancel()
with contextlib.suppress(asyncio.CancelledError, Exception):
await leaked_task
# Restore original state
mcp_server._SESSION_MANAGERS_INITIALIZED = original_initialized
mcp_server._session_manager_cm = original_session_cm
mcp_server._session_manager_stateful_cm = original_session_stateful_cm
mcp_server._sse_session_manager_cm = original_sse_session_cm
mcp_server._stateful_auth_context_cleanup_task = original_cleanup_task
@pytest.mark.asyncio