@@ -28,12 +28,18 @@ import kotlin.test.Test
2828import kotlin.test.assertEquals
2929import kotlin.test.assertTrue
3030
31+ // Failsafe deadline for awaiting an operation that is expected to complete promptly. It exists only
32+ // to stop a genuinely-stuck test from hanging forever, so it is kept generous: a healthy test
33+ // returns the instant the awaited work finishes and never approaches this bound, even on a loaded
34+ // CI host running modules in parallel.
35+ private const val FAILSAFE_TIMEOUT_SECONDS = 30L
36+
3137class NettyTest {
3238 private val executor = DefaultEventExecutor ()
3339
3440 @AfterTest
3541 fun shutdown () {
36- executor.shutdownGracefully(0 , 0 , TimeUnit .SECONDS ).await(2 , TimeUnit .SECONDS )
42+ executor.shutdownGracefully(0 , 0 , TimeUnit .SECONDS ).await(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS )
3743 }
3844
3945 @Test
@@ -43,7 +49,7 @@ class NettyTest {
4349 CompletableFuture .completedFuture(mockResponse(request, 200 ))
4450 }
4551 val future = client.executeNetty(getRequest(), executor)
46- assertTrue(future.await(2 , TimeUnit .SECONDS ))
52+ assertTrue(future.await(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS ))
4753 assertTrue(future.isSuccess)
4854 assertEquals(200 , future.now.status.code)
4955 }
@@ -56,7 +62,7 @@ class NettyTest {
5662 CompletableFuture <Response >().apply { completeExceptionally(sentinel) }
5763 }
5864 val future = client.executeNetty(getRequest(), executor)
59- assertTrue(future.await(2 , TimeUnit .SECONDS ))
65+ assertTrue(future.await(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS ))
6066 assertEquals(false , future.isSuccess)
6167 // Netty's `cause()` returns the failure passed to `setFailure(...)` — should be the
6268 // original IOException, not a CompletionException wrapper.
@@ -70,7 +76,7 @@ class NettyTest {
7076 AsyncHttpClient { request -> CompletableFuture .completedFuture(mockResponse(request, 201 )) },
7177 ).build()
7278 val future = pipeline.sendNetty(getRequest(), executor)
73- assertTrue(future.await(2 , TimeUnit .SECONDS ))
79+ assertTrue(future.await(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS ))
7480 assertEquals(201 , future.now.status.code)
7581 }
7682
@@ -86,7 +92,7 @@ class NettyTest {
8692 // Cancel via Netty's API.
8793 nettyFuture.cancel(true )
8894 // Wait deterministically for the cancel to propagate to the source future.
89- cancelLatch.get(2 , TimeUnit .SECONDS )
95+ cancelLatch.get(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS )
9096 assertTrue(sourceFuture.isCancelled, " cancelling the Netty promise should cancel the source CompletableFuture" )
9197 }
9298
@@ -117,7 +123,7 @@ class NettyTest {
117123 it.start()
118124 }
119125
120- completionLatch.get(2 , TimeUnit .SECONDS )
126+ completionLatch.get(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS )
121127 val err = completionErrorRef.get()
122128 if (err != null ) throw AssertionError (" trySuccess threw unexpectedly after cancel: $err " , err)
123129 // Promise remains cancelled.
@@ -137,7 +143,7 @@ class NettyTest {
137143 CompletableFuture .completedFuture(mockResponse(request, 200 ))
138144 }
139145 val nettyFuture = async.executeNetty(getRequest(), executor)
140- nettyFuture.get(2 , TimeUnit .SECONDS )
146+ nettyFuture.get(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS )
141147 assertEquals(" netty-transport-test" , seenTraceId.get())
142148 } finally {
143149 MDC .clear()
@@ -158,7 +164,7 @@ class NettyTest {
158164 val f = CompletableFuture <Response >()
159165 // Complete on a separate thread to ensure whenComplete fires off-caller-thread.
160166 Thread {
161- gate.get(2 , TimeUnit .SECONDS )
167+ gate.get(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS )
162168 f.complete(mockResponse(request, 200 ))
163169 }.also {
164170 it.isDaemon = true
@@ -174,7 +180,7 @@ class NettyTest {
174180 mdcLatch.complete(Unit )
175181 }
176182 gate.complete(Unit )
177- mdcLatch.get(2 , TimeUnit .SECONDS )
183+ mdcLatch.get(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS )
178184 assertEquals(" netty-whencomplete-mdc" , seenTraceId.get())
179185 } finally {
180186 MDC .clear()
@@ -193,7 +199,7 @@ class NettyTest {
193199 CompletableFuture .completedFuture(mockResponse(request, 200 ))
194200 }
195201 async.executeNetty(getRequest(), executor)
196- .get(2 , TimeUnit .SECONDS )
202+ .get(FAILSAFE_TIMEOUT_SECONDS , TimeUnit .SECONDS )
197203 assertEquals(" netty-caller-preserve" , MDC .get(" trace.id" ))
198204 } finally {
199205 MDC .clear()
0 commit comments