|
18 | 18 |
|
19 | 19 | import static com.google.cloud.storage.TestUtils.assertAll; |
20 | 20 | import static com.google.common.truth.Truth.assertThat; |
| 21 | +import static org.mockito.ArgumentMatchers.any; |
| 22 | +import static org.mockito.ArgumentMatchers.anyLong; |
| 23 | +import static org.mockito.Mockito.mock; |
| 24 | +import static org.mockito.Mockito.when; |
21 | 25 |
|
22 | 26 | import com.google.api.core.ApiClock; |
23 | 27 | import com.google.api.core.NanoClock; |
|
31 | 35 | import com.google.cloud.RetryHelper; |
32 | 36 | import com.google.cloud.RetryHelper.RetryHelperException; |
33 | 37 | import com.google.cloud.storage.Backoff.Jitterer; |
| 38 | +import com.google.cloud.storage.RetryContext.BackoffComment; |
| 39 | +import com.google.cloud.storage.RetryContext.InterruptedBackoffComment; |
34 | 40 | import com.google.cloud.storage.RetryContext.OnFailure; |
35 | 41 | import com.google.cloud.storage.RetryContext.OnSuccess; |
36 | 42 | import com.google.cloud.storage.Retrying.RetryingDependencies; |
|
42 | 48 | import java.util.List; |
43 | 49 | import java.util.concurrent.CountDownLatch; |
44 | 50 | import java.util.concurrent.Executors; |
| 51 | +import java.util.concurrent.RejectedExecutionException; |
45 | 52 | import java.util.concurrent.ScheduledExecutorService; |
46 | 53 | import java.util.concurrent.TimeUnit; |
47 | 54 | import java.util.concurrent.atomic.AtomicBoolean; |
@@ -423,6 +430,24 @@ public void resetAlsoResetsBackoffState() throws Exception { |
423 | 430 | }); |
424 | 431 | } |
425 | 432 |
|
| 433 | + @Test |
| 434 | + public void rejectedExecutionException_funneledToOnFailureHandlerAsSuppressedException() { |
| 435 | + ScheduledExecutorService exec = mock(ScheduledExecutorService.class); |
| 436 | + RejectedExecutionException alreadyShutdown = new RejectedExecutionException("already shutdown"); |
| 437 | + when(exec.schedule(any(Runnable.class), anyLong(), any())).thenThrow(alreadyShutdown); |
| 438 | + Throwable t1 = new RuntimeException("{err1}", new Throwable("{err1Cause}")); |
| 439 | + RetryContext ctx = |
| 440 | + RetryContext.of(exec, maxAttempts(2), Retrying.alwaysRetry(), Jitterer.noJitter()); |
| 441 | + |
| 442 | + AtomicReference<Throwable> err1 = new AtomicReference<>(); |
| 443 | + ctx.recordError(t1, failOnSuccess(), err1::set); |
| 444 | + Throwable t = err1.get(); |
| 445 | + assertThat(t).isNotNull(); |
| 446 | + assertThat(t.getSuppressed()[0]).isInstanceOf(BackoffComment.class); |
| 447 | + assertThat(t.getSuppressed()[1]).isInstanceOf(InterruptedBackoffComment.class); |
| 448 | + assertThat(t.getSuppressed()[1].getSuppressed()[0]).isSameInstanceAs(alreadyShutdown); |
| 449 | + } |
| 450 | + |
426 | 451 | private static ApiException apiException(Code code, String message) { |
427 | 452 | return ApiExceptionFactory.createException(message, null, GrpcStatusCode.of(code), false); |
428 | 453 | } |
|
0 commit comments