Follow-up to #6260 / #6268, raised in that PR's review.
#6260 fixed the engine suite: 44 elapsed-time assertions now measure through StallAwareStopwatch, which discounts the JVM-wide stall (stop-the-world pauses and CPU starvation) observed inside the measured window, so a bound can stay tight without being tripped by a pause late in a shared-JVM run.
The same flake mode applies to every other module that runs a suite in one JVM, and those were deliberately left out of the scope of that PR. grep over server/src/test/java and network/src/test/java turns up:
server/.../Issue5470BatchStreamStallIT.java
server/.../HTTPAuthSessionIT.java (2 sites)
server/.../Issue5470BatchErrorDeliveryIT.java
server/.../PostBatchHandlerIT.java
server/.../Issue5418ShutdownHookDeadlockTest.java
network/.../RemoteHttpComponentTest.java
The server module is a worse environment for this than the engine one, not a better one: its tests bind real ports, start real servers and talk HTTP, so they already sit closer to their bounds, and Issue5470BatchStreamStallIT is a known-red lane.
What to do
StallAwareStopwatch and JvmStallMonitor live in the engine test-jar, which server and network already consume for TestHelper, so nothing needs moving - the work is per-assertion classification, the same pass #6268 did:
- Bounding a named timeout - a tripwire between a bounded operation and an unbounded one.
assertGaveUpWithin; generous is free, because a wider bound cannot turn a passing run red.
- A complexity claim - the bound IS the assertion and has no other practical expression.
assertStayedUnder; loosening it deletes the test.
- A lower bound, or a short wait expected to time out - leave alone. A stall only makes those more true.
@Timeout also wants a look while in there: it is plain wall clock, JUnit gives no way to discount it, so it has to be sized as a hang detector rather than as a latency bound.
The rule is written up in CLAUDE.md under the testing guidance.
Worth checking while doing it
The engine pass found its 44 sites with a grep for assertThat(elapsed…), which missed four more that assert on the expression inline or name the local something else - one of them being a test named in the original issue as a motivating failure. Sweep on System.currentTimeMillis() - / System.nanoTime() - instead, and expect to filter out printlns and @Tag("benchmark") classes by hand.
Follow-up to #6260 / #6268, raised in that PR's review.
#6260 fixed the engine suite: 44 elapsed-time assertions now measure through
StallAwareStopwatch, which discounts the JVM-wide stall (stop-the-world pauses and CPU starvation) observed inside the measured window, so a bound can stay tight without being tripped by a pause late in a shared-JVM run.The same flake mode applies to every other module that runs a suite in one JVM, and those were deliberately left out of the scope of that PR.
grepoverserver/src/test/javaandnetwork/src/test/javaturns up:The server module is a worse environment for this than the engine one, not a better one: its tests bind real ports, start real servers and talk HTTP, so they already sit closer to their bounds, and
Issue5470BatchStreamStallITis a known-red lane.What to do
StallAwareStopwatchandJvmStallMonitorlive in theenginetest-jar, whichserverandnetworkalready consume forTestHelper, so nothing needs moving - the work is per-assertion classification, the same pass #6268 did:assertGaveUpWithin; generous is free, because a wider bound cannot turn a passing run red.assertStayedUnder; loosening it deletes the test.@Timeoutalso wants a look while in there: it is plain wall clock, JUnit gives no way to discount it, so it has to be sized as a hang detector rather than as a latency bound.The rule is written up in
CLAUDE.mdunder the testing guidance.Worth checking while doing it
The engine pass found its 44 sites with a
grepforassertThat(elapsed…), which missed four more that assert on the expression inline or name the local something else - one of them being a test named in the original issue as a motivating failure. Sweep onSystem.currentTimeMillis() -/System.nanoTime() -instead, and expect to filter out printlns and@Tag("benchmark")classes by hand.