rouse-context/core
monkopedia-coder a74fb962c1
test(tunnel): de-flake MultiClientConcurrencyTest (#501) (#504)
* test(tunnel): de-flake MultiClientConcurrencyTest (#501)

The relay-backed multi-client test was flaky and hang-prone in CI: it
failed with a SocketTimeoutException on one PR and wedged for ~35 min on
another, burning the "Integration tests (relay)" job on unrelated changes.

Two root causes, both test-timing (relay passthrough is fine in prod):

1. The class-level `@Timeout(180s)` runs in the default SAME_THREAD mode,
   which only checks elapsed time *after* the test method returns. A thread
   blocked in a `Socket` `read()` is never interrupted, so a wedged run
   hangs indefinitely instead of failing. Add a method-level
   `@Timeout(120s, threadMode = SEPARATE_THREAD)` so a stuck run is
   preempted and FAILS FAST (~2 min) instead of hanging the CI job.

2. The phase transitions waited on fixed `delay(...)`s ("let the stream
   register", "let handlers spin up", "let the CLOSE propagate") that race
   a wall clock and the 30s socket read timeout under load. Replace them
   with deterministic readiness signals: the device-side session collector
   now emits on per-stream open/close Channels, and the test awaits the
   actual lifecycle events (stream surfaced / handler returned) with bounded
   `withTimeout`. The test now tracks real events, so it can neither
   flake-timeout nor wedge.

Test-only change; no production tunnel/relay behavior touched. Verified
green and ~2.3s across 5 repeated runs, plus the full :core:tunnel
integration suite (50 tests) with no regression.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* De-flake relay integration suite: shared IntegrationHttpSupport helper + SEPARATE_THREAD timeouts

Extract the duplicated socket-HTTP request/response helper (the readLine()-racing-soTimeout source of the SocketTimeoutException flakes) into a shared core/testfixtures IntegrationHttpSupport, and convert ClaudeFullFlowEndToEndTest, OAuthEndToEndTest, TunnelMcpIntegrationTest, EndToEndSessionTest, and MultiClientConcurrencyTest to it. Robust read backed by a SEPARATE_THREAD hard @Timeout ceiling rather than racing per-read soTimeout. Test infra only. #501

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* De-flake: rely on generous socket read timeout, drop broad SEPARATE_THREAD

The class-level @Timeout(threadMode = SEPARATE_THREAD) added across the
end-to-end integration classes intermittently corrupted Gradle's per-test
output store ("Could not write XML test results ... EOFException / Kryo
buffer underflow"): these tests run long-lived background coroutines whose
logging races the per-method separate-thread boundaries.

Revert to the default SAME_THREAD class timeout and rely on the generous
shared socket read timeout (IntegrationHttpSupport.SOCKET_READ_TIMEOUT_MS,
60s) as the fail-fast mechanism: every blocking read is bounded, so a stuck
relay round trip raises SocketTimeoutException in ~60s instead of hanging,
while normal CI slowness never trips it. MultiClientConcurrencyTest keeps
its method-level SEPARATE_THREAD ceiling on its single test (#504), where
the output-store interaction does not arise.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Jason Monk <monkopedia@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 15:53:59 -04:00
..
bridge FOSS #463: UnifiedPush wake path (app/UX half, deferred activation) (#473) 2026-06-14 10:05:52 -04:00
mcp Extract shared ReadinessGate (#454) (#457) 2026-06-08 10:40:17 -04:00
testfixtures test(tunnel): de-flake MultiClientConcurrencyTest (#501) (#504) 2026-06-19 15:53:59 -04:00
tunnel test(tunnel): de-flake MultiClientConcurrencyTest (#501) (#504) 2026-06-19 15:53:59 -04:00