Skip to content
This repository was archived by the owner on Sep 26, 2023. It is now read-only.

Commit 18a7bce

Browse files
committed
add tracing test for non-retryable callable
1 parent 3755b64 commit 18a7bce

File tree

2 files changed

+240
-0
lines changed

2 files changed

+240
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright 2021 Google LLC
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are
6+
* met:
7+
*
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above
11+
* copyright notice, this list of conditions and the following disclaimer
12+
* in the documentation and/or other materials provided with the
13+
* distribution.
14+
* * Neither the name of Google LLC nor the names of its
15+
* contributors may be used to endorse or promote products derived from
16+
* this software without specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
package com.google.api.gax.rpc;
31+
32+
import static org.mockito.ArgumentMatchers.any;
33+
import static org.mockito.ArgumentMatchers.anyString;
34+
import static org.mockito.Mockito.atLeastOnce;
35+
import static org.mockito.Mockito.verify;
36+
import static org.mockito.Mockito.when;
37+
38+
import com.google.api.core.ApiFuture;
39+
import com.google.api.core.SettableApiFuture;
40+
import com.google.api.gax.retrying.RetrySettings;
41+
import com.google.api.gax.rpc.testing.FakeCallContext;
42+
import org.junit.Before;
43+
import org.junit.Rule;
44+
import org.junit.Test;
45+
import org.mockito.Mock;
46+
import org.mockito.Spy;
47+
import org.mockito.junit.MockitoJUnit;
48+
import org.mockito.junit.MockitoRule;
49+
import org.mockito.quality.Strictness;
50+
import org.threeten.bp.Duration;
51+
52+
public class CallableTest {
53+
54+
@Rule
55+
public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
56+
57+
@Mock private UnaryCallable<String, String> innerCallable;
58+
private SettableApiFuture<String> innerResult;
59+
60+
private RetrySettings retrySettings =
61+
RetrySettings.newBuilder()
62+
.setInitialRpcTimeout(Duration.ofMillis(5L))
63+
.setMaxRpcTimeout(Duration.ofMillis(5L))
64+
.setTotalTimeout(Duration.ofMillis(10L))
65+
.build();
66+
67+
@Spy private ApiCallContext callContext = FakeCallContext.createDefault();
68+
69+
@Spy
70+
private ApiCallContext callContextWithRetrySettings =
71+
FakeCallContext.createDefault().withRetrySettings(retrySettings);
72+
73+
private ClientContext clientContext;
74+
75+
@Before
76+
public void setUp() {
77+
// Wire the mock inner callable
78+
innerResult = SettableApiFuture.create();
79+
when(innerCallable.futureCall(anyString(), any(ApiCallContext.class))).thenReturn(innerResult);
80+
81+
clientContext = ClientContext.newBuilder().setDefaultCallContext(callContext).build();
82+
}
83+
84+
@Test
85+
public void testNonRetriedCallable() throws Exception {
86+
Duration timeout = Duration.ofMillis(5L);
87+
88+
// Verify that callables configured to not retry have context interactions.
89+
UnaryCallSettings<Object, Object> callSettings =
90+
UnaryCallSettings.newUnaryCallSettingsBuilder().setSimpleTimeoutNoRetries(timeout).build();
91+
UnaryCallable<String, String> callable =
92+
Callables.retrying(innerCallable, callSettings, clientContext);
93+
innerResult.set("No, my refrigerator is not running!");
94+
95+
ApiFuture<String> future = callable.futureCall("Is your refrigerator running?", callContext);
96+
verify(callContext, atLeastOnce()).getRetrySettings();
97+
verify(callContext).getTimeout();
98+
verify(callContext).withTimeout(timeout);
99+
}
100+
101+
@Test
102+
public void testNonRetriedCallableWithRetrySettings() throws Exception {
103+
// Verify that callables configured to not retry have context interactions.
104+
UnaryCallSettings<Object, Object> callSettings =
105+
UnaryCallSettings.newUnaryCallSettingsBuilder()
106+
.setSimpleTimeoutNoRetries(Duration.ofMillis(10L))
107+
.build();
108+
UnaryCallable<String, String> callable =
109+
Callables.retrying(innerCallable, callSettings, clientContext);
110+
innerResult.set("No, my refrigerator is not running!");
111+
112+
Duration timeout = retrySettings.getInitialRpcTimeout();
113+
114+
ApiFuture<String> future =
115+
callable.futureCall("Is your refrigerator running?", callContextWithRetrySettings);
116+
117+
verify(callContextWithRetrySettings, atLeastOnce()).getRetrySettings();
118+
verify(callContextWithRetrySettings).getTimeout();
119+
verify(callContextWithRetrySettings).withTimeout(timeout);
120+
}
121+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2021 Google LLC
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are
6+
* met:
7+
*
8+
* * Redistributions of source code must retain the above copyright
9+
* notice, this list of conditions and the following disclaimer.
10+
* * Redistributions in binary form must reproduce the above
11+
* copyright notice, this list of conditions and the following disclaimer
12+
* in the documentation and/or other materials provided with the
13+
* distribution.
14+
* * Neither the name of Google LLC nor the names of its
15+
* contributors may be used to endorse or promote products derived from
16+
* this software without specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
package com.google.api.gax.tracing;
31+
32+
import static org.mockito.ArgumentMatchers.anyInt;
33+
import static org.mockito.Mockito.any;
34+
import static org.mockito.Mockito.anyString;
35+
import static org.mockito.Mockito.eq;
36+
import static org.mockito.Mockito.times;
37+
import static org.mockito.Mockito.verify;
38+
import static org.mockito.Mockito.verifyNoMoreInteractions;
39+
import static org.mockito.Mockito.when;
40+
41+
import com.google.api.core.ApiFuture;
42+
import com.google.api.core.SettableApiFuture;
43+
import com.google.api.gax.rpc.ApiCallContext;
44+
import com.google.api.gax.rpc.Callables;
45+
import com.google.api.gax.rpc.ClientContext;
46+
import com.google.api.gax.rpc.UnaryCallSettings;
47+
import com.google.api.gax.rpc.UnaryCallable;
48+
import com.google.api.gax.rpc.testing.FakeCallContext;
49+
import com.google.api.gax.tracing.ApiTracerFactory.OperationType;
50+
import org.junit.Before;
51+
import org.junit.Rule;
52+
import org.junit.Test;
53+
import org.junit.runner.RunWith;
54+
import org.junit.runners.JUnit4;
55+
import org.mockito.Mock;
56+
import org.mockito.junit.MockitoJUnit;
57+
import org.mockito.junit.MockitoRule;
58+
import org.mockito.quality.Strictness;
59+
import org.threeten.bp.Duration;
60+
61+
@RunWith(JUnit4.class)
62+
public class TracedCallableTest {
63+
private static final SpanName SPAN_NAME = SpanName.of("FakeClient", "FakeRpc");
64+
65+
@Rule
66+
public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
67+
68+
@Mock private ApiTracerFactory tracerFactory;
69+
private ApiTracer parentTracer;
70+
@Mock private ApiTracer tracer;
71+
@Mock private UnaryCallable<String, String> innerCallable;
72+
private SettableApiFuture<String> innerResult;
73+
74+
private ApiCallContext callContext;
75+
private ClientContext clientContext;
76+
77+
@Before
78+
public void setUp() {
79+
parentTracer = NoopApiTracer.getInstance();
80+
81+
// Wire the mock tracer factory
82+
when(tracerFactory.newTracer(
83+
any(ApiTracer.class), any(SpanName.class), eq(OperationType.Unary)))
84+
.thenReturn(tracer);
85+
86+
// Wire the mock inner callable
87+
innerResult = SettableApiFuture.create();
88+
when(innerCallable.futureCall(anyString(), any(ApiCallContext.class))).thenReturn(innerResult);
89+
90+
callContext = FakeCallContext.createDefault();
91+
clientContext = ClientContext.newBuilder().setDefaultCallContext(callContext).build();
92+
}
93+
94+
public UnaryCallable<String, String> setupTracedUnaryCallable(
95+
UnaryCallSettings<Object, Object> callSettings) {
96+
UnaryCallable<String, String> callable =
97+
Callables.retrying(innerCallable, callSettings, clientContext);
98+
return new TracedUnaryCallable<>(callable, tracerFactory, SPAN_NAME);
99+
}
100+
101+
@Test
102+
public void testNonRetriedCallable() throws Exception {
103+
// Verify that callables configured to not retry have the appropriate tracer interactions.
104+
UnaryCallSettings<Object, Object> callSettings =
105+
UnaryCallSettings.newUnaryCallSettingsBuilder()
106+
.setSimpleTimeoutNoRetries(Duration.ofMillis(5L))
107+
.build();
108+
UnaryCallable<String, String> callable = setupTracedUnaryCallable(callSettings);
109+
innerResult.set("No, my refrigerator is not running!");
110+
111+
ApiFuture<String> future = callable.futureCall("Is your refrigerator running?", callContext);
112+
113+
verify(tracerFactory, times(1)).newTracer(parentTracer, SPAN_NAME, OperationType.Unary);
114+
verify(tracer, times(1)).attemptStarted(anyInt());
115+
verify(tracer, times(1)).attemptSucceeded();
116+
verify(tracer, times(1)).operationSucceeded();
117+
verifyNoMoreInteractions(tracer);
118+
}
119+
}

0 commit comments

Comments
 (0)