Skip to content

Commit 4db1d2b

Browse files
committed
extend tracer tests to every test
1 parent 1edf557 commit 4db1d2b

File tree

1 file changed

+47
-10
lines changed

1 file changed

+47
-10
lines changed

gax-java/gax-httpjson/src/test/java/com/google/api/gax/httpjson/RetryingTest.java

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import com.google.common.util.concurrent.UncheckedExecutionException;
6363
import com.google.protobuf.TypeRegistry;
6464
import java.util.Set;
65+
import java.util.concurrent.atomic.AtomicBoolean;
6566
import java.util.concurrent.atomic.AtomicInteger;
6667
import org.junit.jupiter.api.AfterEach;
6768
import org.junit.jupiter.api.BeforeEach;
@@ -93,6 +94,9 @@ class RetryingTest {
9394
.setTypeRegistry(TypeRegistry.newBuilder().build())
9495
.build();
9596

97+
private AtomicInteger tracerAttemptsFailed = new AtomicInteger();
98+
private AtomicInteger tracerAttempts = new AtomicInteger();
99+
private AtomicBoolean tracerOperationFailed = new AtomicBoolean(false);
96100
private RecordingScheduler executor;
97101
private FakeApiClock fakeClock;
98102
private ClientContext clientContext;
@@ -122,6 +126,8 @@ void resetClock() {
122126
executor = RecordingScheduler.create(fakeClock);
123127
clientContext =
124128
ClientContext.newBuilder()
129+
// we use a custom tracer to confirm whether the retrials are being recorded.
130+
.setTracerFactory(getApiTracerFactory())
125131
.setExecutor(executor)
126132
.setClock(fakeClock)
127133
.setDefaultCallContext(HttpJsonCallContext.createDefault())
@@ -135,12 +141,6 @@ void teardown() {
135141

136142
@Test
137143
void retry() {
138-
// we use a custom tracer to confirm whether the retrials are being recorded.
139-
AtomicInteger tracerFailedAttempts = new AtomicInteger();
140-
AtomicInteger tracerAttempts = new AtomicInteger();
141-
ApiTracerFactory tracerFactory = getApiTracerFactory(tracerFailedAttempts, tracerAttempts);
142-
clientContext = clientContext.toBuilder().setTracerFactory(tracerFactory).build();
143-
144144
// set a retriable that will fail 3 times before returning "2"
145145
ImmutableSet<StatusCode.Code> retryable = ImmutableSet.of(Code.UNAVAILABLE);
146146
Mockito.when(callInt.futureCall((Integer) any(), (ApiCallContext) any()))
@@ -155,8 +155,9 @@ void retry() {
155155
HttpJsonCallableFactory.createUnaryCallable(
156156
callInt, callSettings, httpJsonCallSettings, clientContext);
157157
assertThat(callable.call(initialRequest)).isEqualTo(2);
158-
assertThat(tracerFailedAttempts.get()).isEqualTo(3);
158+
assertThat(tracerAttemptsFailed.get()).isEqualTo(3);
159159
assertThat(tracerAttempts.get()).isEqualTo(4);
160+
assertThat(tracerOperationFailed.get()).isEqualTo(false);
160161

161162
// Capture the argument passed to futureCall
162163
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
@@ -194,6 +195,9 @@ void retryTotalTimeoutExceeded() {
194195
HttpJsonCallableFactory.createUnaryCallable(
195196
callInt, callSettings, httpJsonCallSettings, clientContext);
196197
assertThrows(ApiException.class, () -> callable.call(initialRequest));
198+
assertThat(tracerAttempts.get()).isEqualTo(1);
199+
assertThat(tracerAttemptsFailed.get()).isEqualTo(0);
200+
assertThat(tracerOperationFailed.get()).isEqualTo(true);
197201
// Capture the argument passed to futureCall
198202
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
199203
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class));
@@ -214,6 +218,9 @@ void retryMaxAttemptsExceeded() {
214218
HttpJsonCallableFactory.createUnaryCallable(
215219
callInt, callSettings, httpJsonCallSettings, clientContext);
216220
assertThrows(ApiException.class, () -> callable.call(initialRequest));
221+
assertThat(tracerAttempts.get()).isEqualTo(2);
222+
assertThat(tracerAttemptsFailed.get()).isEqualTo(1);
223+
assertThat(tracerOperationFailed.get()).isEqualTo(true);
217224
// Capture the argument passed to futureCall
218225
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
219226
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class));
@@ -234,6 +241,9 @@ void retryWithinMaxAttempts() {
234241
HttpJsonCallableFactory.createUnaryCallable(
235242
callInt, callSettings, httpJsonCallSettings, clientContext);
236243
assertThat(callable.call(initialRequest)).isEqualTo(2);
244+
assertThat(tracerAttempts.get()).isEqualTo(3);
245+
assertThat(tracerAttemptsFailed.get()).isEqualTo(2);
246+
assertThat(tracerOperationFailed.get()).isEqualTo(false);
237247
// Capture the argument passed to futureCall
238248
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
239249
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class));
@@ -260,6 +270,9 @@ void retryOnStatusUnknown() {
260270
HttpJsonCallableFactory.createUnaryCallable(
261271
callInt, callSettings, httpJsonCallSettings, clientContext);
262272
assertThat(callable.call(initialRequest)).isEqualTo(2);
273+
assertThat(tracerAttempts.get()).isEqualTo(4);
274+
assertThat(tracerAttemptsFailed.get()).isEqualTo(3);
275+
assertThat(tracerOperationFailed.get()).isEqualTo(false);
263276
// Capture the argument passed to futureCall
264277
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
265278
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class));
@@ -277,8 +290,12 @@ void retryOnUnexpectedException() {
277290
UnaryCallable<Integer, Integer> callable =
278291
HttpJsonCallableFactory.createUnaryCallable(
279292
callInt, callSettings, httpJsonCallSettings, clientContext);
293+
// Should an unexpected RuntimeException be received as an UnknownException?
280294
UnknownException exception =
281295
assertThrows(UnknownException.class, () -> callable.call(initialRequest));
296+
assertThat(tracerAttempts.get()).isEqualTo(1);
297+
assertThat(tracerAttemptsFailed.get()).isEqualTo(0);
298+
assertThat(tracerOperationFailed.get()).isEqualTo(true);
282299
assertThat(exception).hasCauseThat().isSameInstanceAs(throwable);
283300
// Capture the argument passed to futureCall
284301
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
@@ -308,6 +325,9 @@ void retryNoRecover() {
308325
HttpJsonCallableFactory.createUnaryCallable(
309326
callInt, callSettings, httpJsonCallSettings, clientContext);
310327
ApiException exception = assertThrows(ApiException.class, () -> callable.call(initialRequest));
328+
assertThat(tracerAttempts.get()).isEqualTo(1);
329+
assertThat(tracerAttemptsFailed.get()).isEqualTo(0);
330+
assertThat(tracerOperationFailed.get()).isEqualTo(true);
311331
assertThat(exception).isSameInstanceAs(apiException);
312332
// Capture the argument passed to futureCall
313333
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
@@ -334,6 +354,12 @@ void retryKeepFailing() {
334354

335355
UncheckedExecutionException exception =
336356
assertThrows(UncheckedExecutionException.class, () -> Futures.getUnchecked(future));
357+
// the number of attempts varies. Here we just make sure that all of them except the last are
358+
// considered as failed
359+
// attempts and that the operation was considered as failed.
360+
assertThat(tracerAttemptsFailed.get()).isGreaterThan(0);
361+
assertThat(tracerAttemptsFailed.get()).isEqualTo(tracerAttempts.get() - 1);
362+
assertThat(tracerOperationFailed.get()).isEqualTo(true);
337363
assertThat(exception).hasCauseThat().isInstanceOf(ApiException.class);
338364
assertThat(exception).hasCauseThat().hasMessageThat().contains("Unavailable");
339365
// Capture the argument passed to futureCall
@@ -374,6 +400,9 @@ void testKnownStatusCode() {
374400
callInt, callSettings, httpJsonCallSettings, clientContext);
375401
ApiException exception =
376402
assertThrows(FailedPreconditionException.class, () -> callable.call(initialRequest));
403+
assertThat(tracerAttempts.get()).isEqualTo(1);
404+
assertThat(tracerAttemptsFailed.get()).isEqualTo(0);
405+
assertThat(tracerOperationFailed.get()).isEqualTo(true);
377406
assertThat(exception.getStatusCode().getTransportCode())
378407
.isEqualTo(HTTP_CODE_PRECONDITION_FAILED);
379408
assertThat(exception).hasMessageThat().contains("precondition failed");
@@ -398,6 +427,9 @@ void testUnknownStatusCode() {
398427
UnknownException exception =
399428
assertThrows(UnknownException.class, () -> callable.call(initialRequest));
400429
assertThat(exception).hasMessageThat().isEqualTo("java.lang.RuntimeException: unknown");
430+
assertThat(tracerAttempts.get()).isEqualTo(1);
431+
assertThat(tracerAttemptsFailed.get()).isEqualTo(0);
432+
assertThat(tracerOperationFailed.get()).isEqualTo(true);
401433
// Capture the argument passed to futureCall
402434
ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
403435
verify(callInt, atLeastOnce()).futureCall(argumentCaptor.capture(), any(ApiCallContext.class));
@@ -412,13 +444,12 @@ public static UnaryCallSettings<Integer, Integer> createSettings(
412444
.build();
413445
}
414446

415-
private static ApiTracerFactory getApiTracerFactory(
416-
AtomicInteger tracerFailedAttempts, AtomicInteger tracerAttempts) {
447+
private ApiTracerFactory getApiTracerFactory() {
417448
ApiTracer tracer =
418449
new BaseApiTracer() {
419450
@Override
420451
public void attemptFailed(Throwable error, Duration delay) {
421-
tracerFailedAttempts.incrementAndGet();
452+
tracerAttemptsFailed.incrementAndGet();
422453
super.attemptFailed(error, delay);
423454
}
424455

@@ -427,6 +458,12 @@ public void attemptStarted(int attemptNumber) {
427458
tracerAttempts.incrementAndGet();
428459
super.attemptStarted(attemptNumber);
429460
}
461+
462+
@Override
463+
public void operationFailed(Throwable error) {
464+
tracerOperationFailed.set(true);
465+
super.operationFailed(error);
466+
}
430467
};
431468
ApiTracerFactory tracerFactory = (parent, spanName, operationType) -> tracer;
432469
return tracerFactory;

0 commit comments

Comments
 (0)