Maintain the setup cache, and fix two id-related defects - #43
Open
davidanthoff wants to merge 4 commits into
Open
Maintain the setup cache, and fix two id-related defects#43davidanthoff wants to merge 4 commits into
davidanthoff wants to merge 4 commits into
Conversation
Four changes that share a branch because they all touch run bookkeeping. `loaded_setups` was written and never maintained. It is now invalidated when a run ships different code for a setup, or drops it entirely, via `_setup_testrun_on_process!` — which runs for every run on a pooled process, so one hook covers the Revise case too: revised source reaches a pooled process as changed setup code through that same path. Deliberately conservative: a setup cached under an earlier run that this one does not mention is dropped rather than assumed intact, since losing a cost hint only costs a scheduling opportunity while keeping a wrong one produces a worse schedule and hides why. `tr.test_items` was keyed by test item id alone. Ids are scoped to their package, so the same package checked out into two folders of one workspace mints the same id from both — the entries collapsed, and the surviving item's source then ran twice while the other never ran at all. Keyed by `(id, package_uri)` now, matching `remaining_work`, with an assertion when a run is assembled so any future scheme mistake surfaces as an error rather than a silently dropped test. `TestrunResult` now carries the real test item id. The JUnit writer used to reconstruct it from `(uri, root)` and the name, which was wrong twice over: it assumed `root` was the item's package root when callers pass the run root, and the id now carries a package qualifier that cannot be recovered from a path at all. The reconstruction survives only as a fallback for result files written before the field existed. `_relative_path` did not absolutise its root, so a relative root produced a `..`-heavy path, failed the guard, and silently emitted absolute machine paths as JUnit classnames. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two checkouts of one package keep their own source, and a run whose items are not individually addressable is rejected rather than silently losing one. Also updates a construction test that asserted the old key shape. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Widening `tr.test_items` to `(id, package_uri)` left nine reads still keyed by
the id alone. Three shapes, and my first sweep only caught one of them:
* `get(tr.test_items, id, ...)` in six handlers,
* `keys(tr.test_items)` in the scheduling-cache prune and the
every-item-reported assertion, where the keys are now tuples,
* `for (id, _) in tr.test_items` in `_get_unchunked_items`, which silently
destructured the pair and produced tuples where strings were expected.
The last one also needed scoping to the env's package: with one package checked
out twice both checkouts' items share an id, and a process may only be handed
the items belonging to its own checkout.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Member
Author
|
Full suite: 189/189, rebased onto the test speedup on That closes the one open claim in the description. Worth recording how the last two fixes were found, since the first sweep looked complete and was not: Widening
My first pass grepped for |
davidanthoff
marked this pull request as ready for review
August 15, 2026 16:46
Two hazards introduced when `tr.test_items` was keyed by `(id, package_uri)`, both on the process-termination path. The crash branch indexed the dict directly. An exception thrown out of a reactor handler does not surface as a failed test item — it kills the reactor loop, so the run never completes and the caller waits until its timeout. A missing detail now degrades to the item's id in the message; the item is reported as errored either way, which is the part that matters. The user-termination branch dereferenced `terminated_env` before the guard that establishes it is not `nothing`, so a process the run no longer tracks would have thrown there instead. Both now go through `_item_for_env`, which tolerates an unknown environment and a missing item. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Four changes that share a branch because they all touch run bookkeeping. Rebased onto the test speedup on
main.loaded_setupswas written and never maintainedIt recorded what a
@testmodule/@testsnippetcost and printed, and nothing ever invalidated it. A stale cost then mis-ranked the scheduler's setup-affinity model.Now invalidated from
_setup_testrun_on_process!when a run ships different code for a setup, or drops it. That one hook covers the Revise case too: a pooled process is set up for every run, so revised source arrives as changed setup code through the same path.Deliberately conservative — a setup cached under an earlier run that this one does not mention is dropped rather than assumed intact. Losing a cost hint costs a scheduling opportunity; keeping a wrong one produces a worse schedule and hides why.
tr.test_itemswas keyed by test item id aloneIds are scoped to their package (julia-vscode/JuliaWorkspaces.jl#257), so the same package checked out into two folders of one workspace mints the same id from both. The entries collapsed, and the surviving item's source then ran twice while the other never ran at all — silently.
Keyed by
(id, package_uri)now, matchingremaining_work.execute_testrunalso asserts every item is individually addressable. That assertion should never fire — discovery already suffixes duplicate labels with#N— which is exactly why it is worth having: a future mistake in the id scheme surfaces as an error instead of a test that quietly stopped running.TestrunResultnow carries the real idThe JUnit writer reconstructed it from
(uri, root)and the name. That was wrong twice over: it assumedrootwas the item's package root when callers pass the run root — different things in a multi-package run — and the id now carries a package qualifier that cannot be recovered from a path at all. The reconstruction survives only as a fallback for result files written before the field existed._relative_pathdid not absolutise its rootA relative root produced a
..-heavy path, failed the guard, and silently emitted absolute machine paths as JUnitclassnames. TestItemApp was working around it caller-side.Tests
25/25 across
test_state.jl,test_junit.jlandtest_results.jl, including new coverage for setup invalidation, the relative root, two checkouts keeping their own source, and the guard rejecting genuinely indistinguishable items. Full-suite verification is still in progress and I will report it here.Depends on
julia-vscode/JuliaWorkspaces.jl#257 for the id format itself. Companion: julia-vscode/JuliaMCP.jl#15.
🤖 Generated with Claude Code