From 1bf5dab8f2a58e14664bc1542fad381101b55bc4 Mon Sep 17 00:00:00 2001 From: Kamil Krzywanski Date: Sun, 19 Jul 2026 17:53:37 +0200 Subject: [PATCH] Fix flaky DuplexTest.duplexWithAuthChallenge Same race as duplexWithRedirect: the client can process the 401 and reset the stream before MockSocketHandler finishes writing the challenge body. Wait for that write (as duplexWithRedirect already does) before continuing past request headers. Fixes #9370 --- okhttp/src/jvmTest/kotlin/okhttp3/DuplexTest.kt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/okhttp/src/jvmTest/kotlin/okhttp3/DuplexTest.kt b/okhttp/src/jvmTest/kotlin/okhttp3/DuplexTest.kt index 503e477271d4..31ca1e45326d 100644 --- a/okhttp/src/jvmTest/kotlin/okhttp3/DuplexTest.kt +++ b/okhttp/src/jvmTest/kotlin/okhttp3/DuplexTest.kt @@ -496,14 +496,27 @@ class DuplexTest { fun duplexWithAuthChallenge() { enableProtocol(Protocol.HTTP_2) val credential = basic("jesse", "secret") + val duplexResponseSent = CountDownLatch(1) + val requestHeadersEndListener = + object : EventListener() { + override fun requestHeadersEnd( + call: Call, + request: Request, + ) { + // Wait for the server to send the duplex response before acting on the 401 response + // and resetting the stream. + duplexResponseSent.await() + } + } client = client .newBuilder() .authenticator(RecordingOkAuthenticator(credential, null)) + .eventListener(eventRecorder.eventListener + requestHeadersEndListener) .build() val body1 = MockSocketHandler() - .sendResponse("please authenticate!\n") + .sendResponse("please authenticate!\n", duplexResponseSent) .requestIOException() .exhaustResponse() server.enqueue(