From e5c458d51a804425e854ce34d8c7bbff01968854 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 6 May 2026 01:02:28 +0000 Subject: [PATCH] test(mcp): cancel leaked stateful auth-context cleanup task 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 --- .../_experimental/mcp_server/test_mcp_server.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py index 26ace369905..fb400d8cc39 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_server.py @@ -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