test(node): give the compass lifecycle waits a CI-sized budget - #6670
Conversation
waitUntil defaults to 1000 ms, which on CI is a rendering-speed assertion rather than a liveness bound. Real CI artifacts show this test taking 11.9-12.8 s against ~2.3 s locally, with waitForIdle alone exceeding 5 s and 6 s on runs that PASS. When that slowness lands inside a waitUntil instead of a waitForIdle (which has no cap, it only warns) the test dies with ComposeTimeoutException: Condition still not satisfied after 1000 ms at NodeDetailCompassLifecycleTest.kt:140 Across four sampled CI runs that is 3 failed attempts out of 7. The condition is satisfiable; only the budget was wrong, so raise it to 30 s — a regression still fails, just later. Note 5 s would not have been enough: 6 s waits occur on passing runs. Each wait also gets a description, so a future timeout names which of the four conditions was not met instead of only reporting a duration. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe compass lifecycle test now uses labeled waits with a shared 30-second timeout. The test continues to verify compass start, stop, restart, and dismissal cleanup counts. ChangesCompass lifecycle test
Estimated code review effort: 1 (Trivial) | ~5 minutes Mergeability Score: ⚪ Minimal · up to This PR only adjusts test lifecycle wait budgets and timeout diagnostics; it does not change product behavior. No actionable merge-blocking risk remains after normal checks and review. Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Why
NodeDetailCompassLifecycleTestis the last known-red test onmainafter the CMP revert (#6664). It is not order-dependent, not CMP-version-dependent, and does not reproduce locally — it passed 24/24 here. The answer was only visible in CI artifacts.waitUntildefaults to 1000 ms. On CI that is a rendering-speed assertion, not a liveness bound:<system-out>waitUntil0–55 mswaitForIdle has not finished after 5 seconds/6 secondswaitForIdlehas no cap — it warns and keeps waiting.waitUntildoes. So the same underlying slowness is harmless in one and fatal in the other, which is exactly the coin-flip we've been seeing. Sampled across four CI runs: 3 failed attempts out of 7.The condition is satisfiable. Only the budget was wrong.
Correction to an earlier revision of this description: I first wrote that failing attempts take ~35–50 s, derived by dividing suite totals by attempt count. Per-attempt data refutes that. Failing attempts are 17.1 / 18.2 / 30.7 s (mean ~22 s) and passing ones 18.3 / 14.6 / 12.8 / 11.9 s (mean ~14 s) — failures skew slower but overlap: in run 31657204256 the passing attempt (18.3 s) was slower than the failing one (17.1 s). So "failures are simply the slowest runs" is not supported; what matters is whether that one wait crossed 1000 ms, not the total.
Could this be masking a real race rather than fixing a timeout?
A fair challenge, and worth stating the bound explicitly. Every sampled failure is
ComposeTimeoutExceptionat line 140 — no assertion failure has ever been observed, including thestarts == 2/stops == 2assertions that a genuine lifecycle race would be expected to trip. But a race in which cleanup never runs would also surface as this timeout, so that alone does not separate the two.What bounds the risk: raising a timeout cannot hide a race that never completes — the test still fails, 30 s later instead of 1 s later. It can only absorb a race that completes late, and "completes late" is what "slow" means. So the failure mode this change could conceal is the one it is meant to tolerate.
The discriminator is this PR's own CI. If the compass test still times out at 30 s, the race hypothesis is right and this change should be rejected.
🐛 Changes
Raise the four lifecycle waits to a 30 s liveness bound. A genuine regression still fails — just later. 5 s would not have been enough: 6 s waits occur on runs that pass, which is why the earlier 1 s → 5 s attempt was directionally right but numerically short.
Each wait also gets a
conditionDescription, so a future timeout names which of the four conditions was not met rather than reporting only a duration — the missing detail that made the original failures expensive to read.Test-only; no production code touched.
Testing Performed
:feature:node:spotlessCheck✅ ·detekt✅ · 3 fresh runs of the test, 1 testcase / 0<failure>elements each, XML timestamps confirmed fresh (Develocity retries twice withfailOnPassedAfterRetry=false, so build result alone is not evidence).Local green proves only "no regression" — it passed locally before this change too. The real evidence is the CI artifact analysis above. At a ~43% base rate, one green CI run would not demonstrate a fix either; several are needed to be meaningful.
Hypotheses tested and falsified, so nobody re-runs them
UnconfinedTestDispatcherwith no scheduler advancement — swapping inStandardTestDispatcher, which queues everything, still passed 3/3. Something does drain it.🤖 Generated with Claude Code
Summary by CodeRabbit