test(mcp): stop MCP dispatch tests from leaking real spawn watchdogs - #93
Closed
basil-k-aji-dev wants to merge 1 commit into
Closed
basil-k-aji-dev wants to merge 1 commit into
basil-k-aji-dev wants to merge 1 commit into
Conversation
`mobile_run_task` arms `_start_spawn_watchdog` after `Popen` returns. Four tests in `test_mcp_tools.py` mock `Popen` but leave the watchdog live, so each starts a real daemon thread monitoring a pid that came from a MagicMock. Those threads outlive `temp_trace_env`'s directory and its monkeypatches. Past the 60-second deadline they go on to terminate a process tree, cancel a reservation, write into the restored trace directory and dispatch failure notifications -- for tasks that never existed. The issue reports a real desktop "Artemis Task Failed" notification naming fake pid 54321; reproducing it here also produced an outbound HTTP call from the notifier (`URLError: Connection refused`) during a unit-test run. Add a module-local autouse fixture that records watchdog launches instead of starting them, and assert the exact arguments in the queue-ticket and device-serial dispatch tests, so the call is now covered rather than merely suppressed. Production watchdog behaviour stays covered by `tests/unit/mcp/test_spawn_watchdog.py`. Test-only; no production change. Closes google#43.
Author
|
Closing as a duplicate. #42 by @wellorbetter already covers issue #43 and was opened first — that one should get the review, not this. My mistake: I didn't check the open PR queue for an existing claim before sending this. Sorry for the noise. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #43.
Problem
mobile_run_taskarms_start_spawn_watchdogafterPopenreturns. Four tests intest_mcp_tools.pymockPopenbut leave the watchdog live, so each starts a real daemon thread monitoring a pid that came from aMagicMock.Those threads outlive
temp_trace_env's directory and its monkeypatches. Past the 60-second deadline they go on to terminate a process tree, cancel a reservation, write into the restored trace directory, and dispatch failure notifications — for tasks that never existed. The issue reports a real desktop "Artemis Task Failed" notification naming fake pid54321.Reproduction
I reproduced it with the guard the issue describes — a temporary
conftest.pythat interceptsthreading.Thread.startforspawn-watchdog-*names, records the attempt without starting a thread, and asserts none occurred:Same four tests, same counts as the issue.
The run also surfaced something not in the original report — the leaked watchdog reached the notifier and made an outbound HTTP request from a unit test:
so the blast radius includes network egress, not just local process and filesystem effects.
Change
A module-local autouse fixture records watchdog launches instead of starting them, and returns the recorded calls so tests can assert on them.
Rather than only suppressing the call, the queue-ticket and device-serial dispatch tests now assert its exact arguments:
so arming the watchdog goes from untested-but-harmful to actually covered.
The fixture is scoped to this module, not the suite. Production watchdog behaviour — startup, terminal tasks, deadlines, cleanup, notifications — stays covered by
tests/unit/mcp/test_spawn_watchdog.py, so no coverage is lost.Test-only; no production behaviour changes, as the issue notes none are needed.
Verification
tests/unit/mcp/test_mcp_tools.pyunder the leak guardmain: 25 passed, 4 errors)tests/unit/mcp/test_mcp_tools.pynormallyURLErrortests/unit/mcp/test_spawn_watchdog.pyuv run pytest -q(full deterministic suite)main— 0 newuv run ruff check tests/Both match the issue's "after" log (
25 passed,4 passed). The guardconftest.pywas temporary and is not part of this PR.make typecheckcould not be run in my environment — thepyrightwheel downloads a Node runtime on first use and my sandbox blocks it. The touched file is not inpyright-core.json.