Skip to content

Commit 55d1fb9

Browse files
authored
test: add RetryInfo test to test server disabled sending retry info (#2048)
Add more retry info test to test the scenario where server stopped sending retry info and client handles retry correctly. Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/java-bigtable/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) - [ ] Rollback plan is reviewed and LGTMed Fixes #<issue_number_goes_here> ☕️ If you write sample code, please follow the [samples format]( https://togithub.com/GoogleCloudPlatform/java-docs-samples/blob/main/SAMPLE_FORMAT.md).
1 parent 94d1ea0 commit 55d1fb9

File tree

1 file changed

+247
-9
lines changed
  • google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub

1 file changed

+247
-9
lines changed

google-cloud-bigtable/src/test/java/com/google/cloud/bigtable/data/v2/stub/RetryInfoTest.java

Lines changed: 247 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.google.cloud.bigtable.data.v2.stub;
1717

1818
import static com.google.common.truth.Truth.assertThat;
19+
import static org.junit.Assert.assertThrows;
1920

2021
import com.google.api.gax.core.NoCredentialsProvider;
2122
import com.google.api.gax.grpc.GrpcStatusCode;
@@ -132,6 +133,20 @@ public void testReadRowDisableRetryInfo() throws IOException {
132133
}
133134
}
134135

136+
@Test
137+
public void testReadRowServerNotReturningRetryInfo() {
138+
verifyNoRetryInfo(() -> client.readRow("table", "row"), true);
139+
}
140+
141+
@Test
142+
public void testReadRowServerNotReturningRetryInfoClientDisabledHandling() throws IOException {
143+
settings.stubSettings().setEnableRetryInfo(false);
144+
145+
try (BigtableDataClient newClient = BigtableDataClient.create(settings.build())) {
146+
verifyNoRetryInfo(() -> newClient.readRow("table", "row"), true);
147+
}
148+
}
149+
135150
@Test
136151
public void testReadRows() {
137152
verifyRetryInfoIsUsed(() -> client.readRows(Query.create("table")).iterator().hasNext(), true);
@@ -152,6 +167,20 @@ public void testReadRowsDisableRetryInfo() throws IOException {
152167
}
153168
}
154169

170+
@Test
171+
public void testReadRowsServerNotReturningRetryInfo() {
172+
verifyNoRetryInfo(() -> client.readRows(Query.create("table")).iterator().hasNext(), true);
173+
}
174+
175+
@Test
176+
public void testReadRowsServerNotReturningRetryInfoClientDisabledHandling() throws IOException {
177+
settings.stubSettings().setEnableRetryInfo(false);
178+
179+
try (BigtableDataClient newClient = BigtableDataClient.create(settings.build())) {
180+
verifyNoRetryInfo(() -> newClient.readRows(Query.create("table")).iterator().hasNext(), true);
181+
}
182+
}
183+
155184
@Test
156185
public void testMutateRows() {
157186
verifyRetryInfoIsUsed(
@@ -185,6 +214,30 @@ public void testMutateRowsDisableRetryInfo() throws IOException {
185214
}
186215
}
187216

217+
@Test
218+
public void testMutateRowsServerNotReturningRetryInfo() {
219+
verifyNoRetryInfo(
220+
() ->
221+
client.bulkMutateRows(
222+
BulkMutation.create("fake-table")
223+
.add(RowMutationEntry.create("row-key-1").setCell("cf", "q", "v"))),
224+
true);
225+
}
226+
227+
@Test
228+
public void testMutateRowsServerNotReturningRetryInfoClientDisabledHandling() throws IOException {
229+
settings.stubSettings().setEnableRetryInfo(false);
230+
231+
try (BigtableDataClient newClient = BigtableDataClient.create(settings.build())) {
232+
verifyNoRetryInfo(
233+
() ->
234+
newClient.bulkMutateRows(
235+
BulkMutation.create("fake-table")
236+
.add(RowMutationEntry.create("row-key-1").setCell("cf", "q", "v"))),
237+
true);
238+
}
239+
}
240+
188241
@Test
189242
public void testMutateRow() {
190243
verifyRetryInfoIsUsed(
@@ -208,6 +261,23 @@ public void testMutateRowDisableRetryInfo() throws IOException {
208261
}
209262
}
210263

264+
@Test
265+
public void testMutateRowServerNotReturningRetryInfo() {
266+
verifyNoRetryInfo(
267+
() -> client.mutateRow(RowMutation.create("table", "key").setCell("cf", "q", "v")), true);
268+
}
269+
270+
@Test
271+
public void testMutateRowServerNotReturningRetryInfoClientDisabledHandling() throws IOException {
272+
settings.stubSettings().setEnableRetryInfo(false);
273+
274+
try (BigtableDataClient newClient = BigtableDataClient.create(settings.build())) {
275+
verifyNoRetryInfo(
276+
() -> newClient.mutateRow(RowMutation.create("table", "key").setCell("cf", "q", "v")),
277+
true);
278+
}
279+
}
280+
211281
@Test
212282
public void testSampleRowKeys() {
213283
verifyRetryInfoIsUsed(() -> client.sampleRowKeys("table"), true);
@@ -227,6 +297,21 @@ public void testSampleRowKeysDisableRetryInfo() throws IOException {
227297
}
228298
}
229299

300+
@Test
301+
public void testSampleRowKeysServerNotReturningRetryInfo() {
302+
verifyNoRetryInfo(() -> client.sampleRowKeys("table"), true);
303+
}
304+
305+
@Test
306+
public void testSampleRowKeysServerNotReturningRetryInfoClientDisabledHandling()
307+
throws IOException {
308+
settings.stubSettings().setEnableRetryInfo(false);
309+
310+
try (BigtableDataClient newClient = BigtableDataClient.create(settings.build())) {
311+
verifyNoRetryInfo(() -> newClient.sampleRowKeys("table"), true);
312+
}
313+
}
314+
230315
@Test
231316
public void testCheckAndMutateRow() {
232317
verifyRetryInfoIsUsed(
@@ -256,6 +341,33 @@ public void testCheckAndMutateDisableRetryInfo() throws IOException {
256341
}
257342
}
258343

344+
@Test
345+
public void testCheckAndMutateServerNotReturningRetryInfo() {
346+
verifyNoRetryInfo(
347+
() ->
348+
client.checkAndMutateRow(
349+
ConditionalRowMutation.create("table", "key")
350+
.condition(Filters.FILTERS.value().regex("old-value"))
351+
.then(Mutation.create().setCell("cf", "q", "v"))),
352+
false);
353+
}
354+
355+
@Test
356+
public void testCheckAndMutateServerNotReturningRetryInfoClientDisabledHandling()
357+
throws IOException {
358+
settings.stubSettings().setEnableRetryInfo(false);
359+
360+
try (BigtableDataClient newClient = BigtableDataClient.create(settings.build())) {
361+
verifyNoRetryInfo(
362+
() ->
363+
newClient.checkAndMutateRow(
364+
ConditionalRowMutation.create("table", "key")
365+
.condition(Filters.FILTERS.value().regex("old-value"))
366+
.then(Mutation.create().setCell("cf", "q", "v"))),
367+
false);
368+
}
369+
}
370+
259371
@Test
260372
public void testReadModifyWrite() {
261373
verifyRetryInfoIsUsed(
@@ -280,6 +392,28 @@ public void testReadModifyWriteDisableRetryInfo() throws IOException {
280392
}
281393
}
282394

395+
@Test
396+
public void testReadModifyWriteServerNotReturningRetryInfo() {
397+
verifyNoRetryInfo(
398+
() ->
399+
client.readModifyWriteRow(
400+
ReadModifyWriteRow.create("table", "row").append("cf", "q", "v")),
401+
false);
402+
}
403+
404+
@Test
405+
public void testReadModifyWriteNotReturningRetryInfoClientDisabledHandling() throws IOException {
406+
settings.stubSettings().setEnableRetryInfo(false);
407+
408+
try (BigtableDataClient newClient = BigtableDataClient.create(settings.build())) {
409+
verifyNoRetryInfo(
410+
() ->
411+
newClient.readModifyWriteRow(
412+
ReadModifyWriteRow.create("table", "row").append("cf", "q", "v")),
413+
false);
414+
}
415+
}
416+
283417
@Test
284418
public void testReadChangeStream() {
285419
verifyRetryInfoIsUsed(
@@ -308,6 +442,28 @@ public void testReadChangeStreamDisableRetryInfo() throws IOException {
308442
}
309443
}
310444

445+
@Test
446+
public void testReadChangeStreamServerNotReturningRetryInfo() {
447+
verifyNoRetryInfo(
448+
() -> client.readChangeStream(ReadChangeStreamQuery.create("table")).iterator().hasNext(),
449+
true);
450+
}
451+
452+
@Test
453+
public void testReadChangeStreamNotReturningRetryInfoClientDisabledHandling() throws IOException {
454+
settings.stubSettings().setEnableRetryInfo(false);
455+
456+
try (BigtableDataClient newClient = BigtableDataClient.create(settings.build())) {
457+
verifyNoRetryInfo(
458+
() ->
459+
newClient
460+
.readChangeStream(ReadChangeStreamQuery.create("table"))
461+
.iterator()
462+
.hasNext(),
463+
true);
464+
}
465+
}
466+
311467
@Test
312468
public void testGenerateInitialChangeStreamPartition() {
313469
verifyRetryInfoIsUsed(
@@ -330,6 +486,25 @@ public void testGenerateInitialChangeStreamPartitionDisableRetryInfo() throws IO
330486
}
331487
}
332488

489+
@Test
490+
public void testGenerateInitialChangeStreamServerNotReturningRetryInfo() {
491+
verifyNoRetryInfo(
492+
() -> client.generateInitialChangeStreamPartitions("table").iterator().hasNext(), true);
493+
}
494+
495+
@Test
496+
public void testGenerateInitialChangeStreamServerNotReturningRetryInfoClientDisabledHandling()
497+
throws IOException {
498+
settings.stubSettings().setEnableRetryInfo(false);
499+
500+
try (BigtableDataClient newClient = BigtableDataClient.create(settings.build())) {
501+
verifyNoRetryInfo(
502+
() -> newClient.generateInitialChangeStreamPartitions("table").iterator().hasNext(),
503+
true);
504+
}
505+
}
506+
507+
// Test the case where server returns retry info and client enables handling of retry info
333508
private void verifyRetryInfoIsUsed(Runnable runnable, boolean retryableError) {
334509
if (retryableError) {
335510
enqueueRetryableExceptionWithDelay(delay);
@@ -344,6 +519,7 @@ private void verifyRetryInfoIsUsed(Runnable runnable, boolean retryableError) {
344519
assertThat(stopwatch.elapsed()).isAtLeast(Duration.ofSeconds(delay.getSeconds()));
345520
}
346521

522+
// Test the case where server returns retry info but client disabled handling of retry info
347523
private void verifyRetryInfoCanBeDisabled(Runnable runnable) {
348524
enqueueRetryableExceptionWithDelay(delay);
349525
Stopwatch stopwatch = Stopwatch.createStarted();
@@ -354,17 +530,58 @@ private void verifyRetryInfoCanBeDisabled(Runnable runnable) {
354530
assertThat(stopwatch.elapsed()).isLessThan(Duration.ofSeconds(delay.getSeconds()));
355531

356532
attemptCounter.set(0);
357-
ApiException exception = enqueueNonRetryableExceptionWithDelay(delay);
358-
try {
533+
ApiException expectedApiException = enqueueNonRetryableExceptionWithDelay(delay);
534+
ApiException actualException =
535+
assertThrows("non retryable operations should fail", ApiException.class, runnable::run);
536+
if (actualException instanceof MutateRowsException) {
537+
assertThat(
538+
((MutateRowsException) actualException)
539+
.getFailedMutations()
540+
.get(0)
541+
.getError()
542+
.getStatusCode())
543+
.isEqualTo(expectedApiException.getStatusCode());
544+
} else {
545+
assertThat(actualException.getStatusCode()).isEqualTo(expectedApiException.getStatusCode());
546+
}
547+
assertThat(attemptCounter.get()).isEqualTo(1);
548+
}
549+
550+
// Test the case where server does not return retry info
551+
private void verifyNoRetryInfo(Runnable runnable, boolean operationRetryable) {
552+
enqueueRetryableExceptionNoRetryInfo();
553+
554+
if (!operationRetryable) {
555+
assertThrows("non retryable operation should fail", ApiException.class, runnable::run);
556+
assertThat(attemptCounter.get()).isEqualTo(1);
557+
} else {
558+
Stopwatch stopwatch = Stopwatch.createStarted();
359559
runnable.run();
360-
} catch (ApiException e) {
361-
if (e instanceof MutateRowsException) {
362-
assertThat(((MutateRowsException) e).getFailedMutations().get(0).getError().getStatusCode())
363-
.isEqualTo(exception.getStatusCode());
364-
} else {
365-
assertThat(e.getStatusCode()).isEqualTo(exception.getStatusCode());
366-
}
560+
stopwatch.stop();
561+
562+
assertThat(attemptCounter.get()).isEqualTo(2);
563+
assertThat(stopwatch.elapsed()).isLessThan(Duration.ofSeconds(delay.getSeconds()));
367564
}
565+
566+
attemptCounter.set(0);
567+
568+
ApiException expectedApiException = enqueueNonRetryableExceptionNoRetryInfo();
569+
570+
ApiException actualApiException =
571+
assertThrows("non retryable error should fail", ApiException.class, runnable::run);
572+
if (actualApiException instanceof MutateRowsException) {
573+
assertThat(
574+
((MutateRowsException) actualApiException)
575+
.getFailedMutations()
576+
.get(0)
577+
.getError()
578+
.getStatusCode())
579+
.isEqualTo(expectedApiException.getStatusCode());
580+
} else {
581+
assertThat(actualApiException.getStatusCode())
582+
.isEqualTo(expectedApiException.getStatusCode());
583+
}
584+
368585
assertThat(attemptCounter.get()).isEqualTo(1);
369586
}
370587

@@ -408,6 +625,27 @@ private ApiException enqueueNonRetryableExceptionWithDelay(com.google.protobuf.D
408625
return exception;
409626
}
410627

628+
private void enqueueRetryableExceptionNoRetryInfo() {
629+
ApiException exception =
630+
new UnavailableException(
631+
new StatusRuntimeException(Status.UNAVAILABLE),
632+
GrpcStatusCode.of(Status.Code.UNAVAILABLE),
633+
true);
634+
service.expectations.add(exception);
635+
}
636+
637+
private ApiException enqueueNonRetryableExceptionNoRetryInfo() {
638+
ApiException exception =
639+
new InternalException(
640+
new StatusRuntimeException(Status.INTERNAL),
641+
GrpcStatusCode.of(Status.Code.INTERNAL),
642+
false);
643+
644+
service.expectations.add(exception);
645+
646+
return exception;
647+
}
648+
411649
private class FakeBigtableService extends BigtableGrpc.BigtableImplBase {
412650
Queue<Exception> expectations = Queues.newArrayDeque();
413651

0 commit comments

Comments
 (0)