Skip to content

Commit a94df4a

Browse files
chore: deflake trailer skipping test (#2411)
Change-Id: I43324a0916e61e67ff3b7019189a9c54afae38ba 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 - [ ] All new data plane features have a completed end to end testing plan 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 9796d57 commit a94df4a

File tree

1 file changed

+46
-12
lines changed

1 file changed

+46
-12
lines changed

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

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,11 @@
1515
*/
1616
package com.google.cloud.bigtable.data.v2.stub;
1717

18-
import static org.mockito.Mockito.never;
19-
import static org.mockito.Mockito.times;
20-
import static org.mockito.Mockito.verify;
18+
import static com.google.common.truth.Truth.assertThat;
2119
import static org.mockito.Mockito.when;
2220

2321
import com.google.api.core.ApiFuture;
2422
import com.google.api.gax.core.NoCredentialsProvider;
25-
import com.google.api.gax.tracing.ApiTracer;
2623
import com.google.api.gax.tracing.ApiTracerFactory;
2724
import com.google.auto.value.AutoValue;
2825
import com.google.bigtable.v2.BigtableGrpc;
@@ -43,6 +40,7 @@
4340
import com.google.cloud.bigtable.data.v2.models.TableId;
4441
import com.google.cloud.bigtable.data.v2.models.TargetId;
4542
import com.google.cloud.bigtable.data.v2.stub.metrics.BigtableTracer;
43+
import com.google.cloud.bigtable.data.v2.stub.metrics.NoopMetricsProvider;
4644
import com.google.common.base.Preconditions;
4745
import com.google.common.base.Supplier;
4846
import com.google.common.collect.ImmutableList;
@@ -56,10 +54,13 @@
5654
import io.grpc.ServerServiceDefinition;
5755
import io.grpc.stub.ServerCalls;
5856
import io.grpc.stub.StreamObserver;
57+
import java.util.Optional;
58+
import java.util.concurrent.ConcurrentHashMap;
5959
import java.util.concurrent.ExecutionException;
6060
import java.util.concurrent.LinkedBlockingDeque;
6161
import java.util.concurrent.TimeUnit;
6262
import java.util.concurrent.TimeoutException;
63+
import java.util.concurrent.atomic.AtomicInteger;
6364
import org.junit.After;
6465
import org.junit.Assert;
6566
import org.junit.Before;
@@ -69,7 +70,6 @@
6970
import org.junit.runners.JUnit4;
7071
import org.mockito.Mock;
7172
import org.mockito.Mockito;
72-
import org.mockito.exceptions.verification.WantedButNotInvoked;
7373
import org.mockito.junit.MockitoJUnit;
7474
import org.mockito.junit.MockitoRule;
7575

@@ -85,7 +85,7 @@ public class SkipTrailersTest {
8585
private Server server;
8686

8787
@Mock private ApiTracerFactory tracerFactory;
88-
@Mock private BigtableTracer tracer;
88+
private FakeTracer tracer = new FakeTracer();
8989

9090
private BigtableDataClient client;
9191

@@ -95,12 +95,12 @@ public void setUp() throws Exception {
9595
server = FakeServiceBuilder.create(hackedService).start();
9696

9797
when(tracerFactory.newTracer(Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(tracer);
98-
when(tracer.inScope()).thenReturn(Mockito.mock(ApiTracer.Scope.class));
9998

10099
BigtableDataSettings.Builder clientBuilder =
101100
BigtableDataSettings.newBuilderForEmulator(server.getPort())
102101
.setProjectId(PROJECT_ID)
103102
.setInstanceId(INSTANCE_ID)
103+
.setMetricsProvider(NoopMetricsProvider.INSTANCE)
104104
.setCredentialsProvider(NoCredentialsProvider.create());
105105
clientBuilder.stubSettings().setEnableSkipTrailers(true).setTracerFactory(tracerFactory);
106106

@@ -159,7 +159,7 @@ private <T> void test(Supplier<ApiFuture<?>> invoker, T fakeResponse)
159159

160160
// Wait for the call to start on the server
161161
@SuppressWarnings("unchecked")
162-
ServerRpc<?, T> rpc = (ServerRpc<?, T>) hackedService.rpcs.poll(10, TimeUnit.SECONDS);
162+
ServerRpc<?, T> rpc = (ServerRpc<?, T>) hackedService.rpcs.poll(30, TimeUnit.SECONDS);
163163
Preconditions.checkNotNull(
164164
rpc, "Timed out waiting for the call to be received by the mock server");
165165

@@ -173,8 +173,21 @@ private <T> void test(Supplier<ApiFuture<?>> invoker, T fakeResponse)
173173
Assert.fail("timed out waiting for the trailer optimization future to resolve");
174174
}
175175

176-
verify(tracer, times(1)).operationFinishEarly();
177-
verify(tracer, never()).operationSucceeded();
176+
// The tracer will be notified in parallel to the future being resolved
177+
// This normal and expected, but requires the test to wait a bit
178+
for (int i = 10; i > 0; i--) {
179+
try {
180+
assertThat(tracer.getCallCount("operationFinishEarly")).isEqualTo(1);
181+
break;
182+
} catch (AssertionError e) {
183+
if (i > 1) {
184+
Thread.sleep(100);
185+
} else {
186+
throw e;
187+
}
188+
}
189+
}
190+
assertThat(tracer.getCallCount("operationSucceeded")).isEqualTo(0);
178191

179192
// clean up
180193
rpc.getResponseStream().onCompleted();
@@ -183,9 +196,9 @@ private <T> void test(Supplier<ApiFuture<?>> invoker, T fakeResponse)
183196
// Since we dont have a way to know exactly when this happens, we poll
184197
for (int i = 10; i > 0; i--) {
185198
try {
186-
verify(tracer, times(1)).operationSucceeded();
199+
assertThat(tracer.getCallCount("operationSucceeded")).isEqualTo(1);
187200
break;
188-
} catch (WantedButNotInvoked e) {
201+
} catch (AssertionError e) {
189202
if (i > 1) {
190203
Thread.sleep(100);
191204
} else {
@@ -195,6 +208,27 @@ private <T> void test(Supplier<ApiFuture<?>> invoker, T fakeResponse)
195208
}
196209
}
197210

211+
static class FakeTracer extends BigtableTracer {
212+
ConcurrentHashMap<String, AtomicInteger> callCounts = new ConcurrentHashMap<>();
213+
214+
@Override
215+
public void operationFinishEarly() {
216+
record("operationFinishEarly");
217+
}
218+
219+
@Override
220+
public void operationSucceeded() {
221+
record("operationSucceeded");
222+
}
223+
224+
private void record(String op) {
225+
callCounts.computeIfAbsent(op, (ignored) -> new AtomicInteger()).getAndIncrement();
226+
}
227+
228+
private int getCallCount(String op) {
229+
return Optional.ofNullable(callCounts.get(op)).map(AtomicInteger::get).orElse(0);
230+
}
231+
}
198232
/**
199233
* Hack the srvice definition to allow grpc server to simulate delayed trailers. This will augment
200234
* the bigtable service definition to promote unary rpcs to server streaming

0 commit comments

Comments
 (0)