test(mcp): cover timer shutdown scheduling guards

This commit is contained in:
2026-06-16 22:33:14 -04:00
committed by Forgejo
parent 3ffc8f6a8e
commit a103d755ce
2 changed files with 51 additions and 1 deletions
@@ -88,6 +88,35 @@ def step_shared_callback_flag(context: Context) -> None:
context.timer_race_callback_lock = threading.Lock()
@given("an McpClient with active idle and health timers")
def step_mcp_client_active_timers(context: Context) -> None:
"""Create a client whose timer schedulers would normally install timers."""
server_config = MCPServerConfig(
name="test-timer-shutdown-guard",
transport="stdio",
command="echo",
)
context.timer_race_config = McpClientConfig(
server=server_config,
lazy_start=False,
idle_timeout_seconds=60.0,
health_check_interval_seconds=60.0,
)
context.timer_race_transport = MockMCPTransport(
tools=[_mock_tool("test_tool")],
)
context.timer_race_client = McpClient(
config=context.timer_race_config,
transport=context.timer_race_transport,
)
@given("the timer race client is marked as shutting down")
def step_mark_timer_race_client_shutting_down(context: Context) -> None:
"""Simulate the shutdown window before timer scheduling is attempted."""
context.timer_race_client._shutting_down = True
# ── When ──────────────────────────────────────────────────────────
@@ -213,6 +242,13 @@ def step_wait_for_late_fires(context: Context) -> None:
original_sleep(0.3)
@when("I ask the client to schedule idle and health timers")
def step_schedule_idle_and_health_timers(context: Context) -> None:
"""Invoke both scheduler guards while shutdown is in progress."""
context.timer_race_client._schedule_idle_timer()
context.timer_race_client._schedule_health_check()
# ── Then ──────────────────────────────────────────────────────────
@@ -237,3 +273,11 @@ def step_idle_callback_not_fired_after_shutdown(context: Context) -> None:
"different synchronisation scheme to prevent the race. "
f"Errors (if any): {getattr(context, 'timer_race_errors', [])}"
)
@then("no idle or health timer should be scheduled")
def step_no_idle_or_health_timer_scheduled(context: Context) -> None:
"""Assert shutdown guards returned before installing timers."""
client = context.timer_race_client
assert client._idle_timer is None, "Idle timer was scheduled during shutdown"
assert client._health_timer is None, "Health timer was scheduled during shutdown"
@@ -75,4 +75,10 @@ Feature: TDD Issue #10516 — McpClient timer can fire after cancellation race
When I start the client
And I trigger the idle timer race by forcing a reschedule during shutdown
And I wait long enough for any late timer fires (0.3s)
Then the idle timer callback should not have fired after shutdown
Then the idle timer callback should not have fired after shutdown
Scenario: Timer schedulers skip work during shutdown
Given an McpClient with active idle and health timers
And the timer race client is marked as shutting down
When I ask the client to schedule idle and health timers
Then no idle or health timer should be scheduled