Repository navigation
Fix the races behind flaky Review-pane and language server tests - #511
Draft
jamescrosswell wants to merge 4 commits into
Draft
jamescrosswell wants to merge 4 commits into
jamescrosswell wants to merge 4 commits into
Conversation
Showing the Review tab starts its load, and when the fake git call finished before the await checked, the load carried on synchronously on the main thread and showed its result inside the tab switch, before FocusReview had moved focus. The refresh then put focus back on the Explorer, the sidebar followed it, and tests waiting on the Review pane timed out. Hosted, the load now starts off the main thread, so its results always arrive on a later iteration. The narrow-terminal sidebar drag test set the screen size once, but the Windows console reports its own size periodically, which undid it while the test waited for the sidebar to shrink. It now pins the size, as other host tests do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # tests/TuiCode.Tests/SidebarDragHostTests.cs
The client marked itself initialized only after sending `initialized`, and decided readiness and set it in two steps. A server that reported its loading done before the client had marked itself initialized, as the smoke test's fake does in reply to `initialized`, left it Loading until the quiet-load timer, which in the AOT smoke is its whole 10 s timeout. Readiness is now decided and set under one lock, and checked again once the client is initialized. Two test races go with it: the "edits before the server has started" test now holds the fake's initialize answer until it has made its edits, and the fake records a notification only once it has handled it, so a test that waits for one can rely on its effect. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stopped recorded the reason, killed the process and only then set the state. The kill completes the connection, which calls Stopped(null) from another thread, and when that landed in between it replaced the reason with null. The state is now set with the reason, under the same lock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Summary
Fixes the races behind the CI flakes that keep hitting PRs: host tests timing out (
RunAsync timed out) once they open the Review pane, the language server smoke sayingserver never became ready (Loading), andLanguageServerTestsfailing now and then. Three are app bugs and two are test bugs.Review tab (app fix). Showing the Review tab starts its load. When the fake git call finished before the
awaitchecked it, the load carried on synchronously on the main thread, andApp.Invokeshowed the result inside the tab switch, beforeFocusReviewhad moved focus. The refresh's focus settling then put focus back on the Explorer, the sidebar'sTabsfollowed it, and any test waiting on the Review pane timed out.ReviewView.Refreshnow starts the load off the main thread when hosted, so its results always arrive on a later iteration. Real git is slow enough that this practically never happened in the app, but it was a re-entrancy bug all the same.Language server readiness (app fix). The client marked itself initialized only after sending
initialized, and worked out readiness and set it in two separate steps. A server that reported its loading finished before the client had marked itself initialized, as the smoke's fake does in reply toinitialized, left itLoadinguntil the quiet-load timer. In the AOT smoke that timer is the whole 10 s timeout, henceserver never became ready (Loading); in the app, the status bar could say loading for longer than it should. Readiness is now decided and set under one lock, and checked again once the client is initialized.Language server stop reason (app fix).
Stoppedrecorded why the server stopped, killed the process, and only then set the state. The kill completes the connection, which callsStopped(null)from another thread, and when that landed in between it replaced the reason with null, soA_server_that_fails_to_initialize_stops_and_says_whysaw no failure message. The state is now set with the reason, under the same lock. Under stress that test failed 2 times in 400 runs before, and 0 in 600 after.Language server tests (test fixes).
Edits_made_before_the_server_has_started_open_it_at_their_versionassumed the fake hadn't answeredinitializebefore the test's edits. The fake can now hold that answer (HoldInitialize), and the test holds it until it has made them.FinishLoading's "end" could overtake the "begin" thatinitializedtriggers, which is what madeIt_loads_until_the_server_says_it_has_finished_then_is_readytime out. It now records a notification once it has handled it.Notes
FocusHostTestsandReviewOverviewHostTestsin 10 parallel processes, the old code timed out 6 times in about 224 runs; with the fix, 0 in 240. A temporary stack-trace hook showed the chain:FocusReview→SidebarPart.ShowTab→ReviewView.Refresh→ synchronousShow→SettleFocusAfterRedraw→ focus to the Explorer.A_server_that_finishes_loading_before_it_answers_initialize_is_ready_once_it_hasis new. It times out every time against the old client and passes with the fix. The language server tests (LanguageServerTests,LanguageServersTests,GoToDefinitionHostTests,FindUsagesHostTests) then ran 400 times in parallel with no failures; before the fake's fix,It_loads_until…failed 2 times in 300.mainby Ctrl+\ puts the current file beside the others, in a second editor group #500 in the meantime with the same change (pinning the screen size), so it's no longer in this diff.🤖 Generated with Claude Code