Skip to content

Commit 2554a04

Browse files
committed
add test cases
1 parent 476e5a8 commit 2554a04

File tree

7 files changed

+232
-4
lines changed

7 files changed

+232
-4
lines changed

api/src/main/java/io/grpc/ChildChannelConfigurer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,4 @@ public interface ChildChannelConfigurer extends Consumer<ManagedChannelBuilder<?
6767
*/
6868
@Override
6969
void accept(ManagedChannelBuilder<?> builder);
70-
}
70+
}

api/src/main/java/io/grpc/ChildChannelConfigurers.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,4 @@ public static ChildChannelConfigurer conditional(boolean condition,
9696
checkNotNull(delegate, "delegate");
9797
return condition ? delegate : NO_OP;
9898
}
99-
}
99+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2025 The gRPC Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.grpc;
18+
19+
import static org.mockito.Mockito.mock;
20+
import static org.mockito.Mockito.verify;
21+
import static org.mockito.Mockito.verifyNoInteractions;
22+
23+
import org.junit.Test;
24+
import org.junit.runner.RunWith;
25+
import org.junit.runners.JUnit4;
26+
27+
@RunWith(JUnit4.class)
28+
public class ChildChannelConfigurersTest {
29+
30+
@Test
31+
public void noOp_doesNothing() {
32+
ManagedChannelBuilder<?> builder = mock(ManagedChannelBuilder.class);
33+
ChildChannelConfigurers.noOp().accept(builder);
34+
verifyNoInteractions(builder);
35+
}
36+
37+
@Test
38+
public void compose_runsInOrder() {
39+
ManagedChannelBuilder<?> builder = mock(ManagedChannelBuilder.class);
40+
ChildChannelConfigurer configurer1 = b -> b.userAgent("agent1");
41+
ChildChannelConfigurer configurer2 = b -> b.maxInboundMessageSize(123);
42+
43+
ChildChannelConfigurers.compose(configurer1, configurer2).accept(builder);
44+
45+
verify(builder).userAgent("agent1");
46+
verify(builder).maxInboundMessageSize(123);
47+
}
48+
49+
@Test
50+
public void compose_ignoresNulls() {
51+
ManagedChannelBuilder<?> builder = mock(ManagedChannelBuilder.class);
52+
ChildChannelConfigurer configurer = b -> b.userAgent("agent1");
53+
54+
ChildChannelConfigurers.compose(null, configurer, null).accept(builder);
55+
56+
verify(builder).userAgent("agent1");
57+
}
58+
}

api/src/test/java/io/grpc/NameResolverTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ public void args() {
105105
}
106106

107107
private NameResolver.Args createArgs() {
108+
ManagedChannel parent = mock(ManagedChannel.class);
108109
return NameResolver.Args.newBuilder()
109110
.setDefaultPort(defaultPort)
110111
.setProxyDetector(proxyDetector)
@@ -116,9 +117,35 @@ private NameResolver.Args createArgs() {
116117
.setOverrideAuthority(overrideAuthority)
117118
.setMetricRecorder(metricRecorder)
118119
.setArg(FOO_ARG_KEY, customArgValue)
120+
.setParentChannel(parent)
119121
.build();
120122
}
121123

124+
@Test
125+
public void args_parentChannel() {
126+
ManagedChannel parent = mock(ManagedChannel.class);
127+
128+
// Create a real SynchronizationContext instead of mocking it
129+
SynchronizationContext realSyncContext = new SynchronizationContext(
130+
new Thread.UncaughtExceptionHandler() {
131+
@Override
132+
public void uncaughtException(Thread t, Throwable e) {
133+
throw new AssertionError(e);
134+
}
135+
});
136+
137+
NameResolver.Args args = NameResolver.Args.newBuilder()
138+
.setDefaultPort(8080)
139+
.setProxyDetector(mock(ProxyDetector.class))
140+
.setSynchronizationContext(realSyncContext)
141+
.setServiceConfigParser(mock(NameResolver.ServiceConfigParser.class))
142+
.setChannelLogger(mock(ChannelLogger.class))
143+
.setParentChannel(parent)
144+
.build();
145+
146+
assertThat(args.getParentChannel()).isSameInstanceAs(parent);
147+
}
148+
122149
@Test
123150
@SuppressWarnings("deprecation")
124151
public void startOnOldListener_wrapperListener2UsedToStart() {

core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import io.grpc.Channel;
7070
import io.grpc.ChannelCredentials;
7171
import io.grpc.ChannelLogger;
72+
import io.grpc.ChildChannelConfigurer;
7273
import io.grpc.ClientCall;
7374
import io.grpc.ClientInterceptor;
7475
import io.grpc.ClientInterceptors;
@@ -101,10 +102,12 @@
101102
import io.grpc.LoadBalancerRegistry;
102103
import io.grpc.LongCounterMetricInstrument;
103104
import io.grpc.ManagedChannel;
105+
import io.grpc.ManagedChannelBuilder;
104106
import io.grpc.Metadata;
105107
import io.grpc.MethodDescriptor;
106108
import io.grpc.MethodDescriptor.MethodType;
107109
import io.grpc.MetricInstrumentRegistry;
110+
import io.grpc.MetricRecorder;
108111
import io.grpc.MetricSink;
109112
import io.grpc.NameResolver;
110113
import io.grpc.NameResolver.ConfigOrError;
@@ -302,9 +305,12 @@ public String getPolicyName() {
302305
private boolean panicExpected;
303306
@Captor
304307
private ArgumentCaptor<ResolvedAddresses> resolvedAddressCaptor;
305-
306308
private ArgumentCaptor<ClientStreamListener> streamListenerCaptor =
307309
ArgumentCaptor.forClass(ClientStreamListener.class);
310+
@Mock
311+
private ChildChannelConfigurer mockChildChannelConfigurer;
312+
@Mock
313+
private MetricRecorder mockMetricRecorder;
308314

309315
private void createChannel(ClientInterceptor... interceptors) {
310316
createChannel(false, interceptors);
@@ -5139,4 +5145,116 @@ private static ManagedChannelServiceConfig createManagedChannelServiceConfig(
51395145
return ManagedChannelServiceConfig
51405146
.fromServiceConfig(rawServiceConfig, true, 3, 4, policySelection);
51415147
}
5148+
5149+
@Test
5150+
public void getChildChannelConfigurer_returnsConfiguredValue() {
5151+
ManagedChannelImplBuilder builder = new ManagedChannelImplBuilder(TARGET,
5152+
new ClientTransportFactoryBuilder() {
5153+
@Override
5154+
public ClientTransportFactory buildClientTransportFactory() {
5155+
return mockTransportFactory;
5156+
}
5157+
},
5158+
new FixedPortProvider(DEFAULT_PORT));
5159+
5160+
when(mockTransportFactory.getSupportedSocketAddressTypes())
5161+
.thenReturn(Collections.singleton(InetSocketAddress.class));
5162+
5163+
ManagedChannel channel = builder
5164+
.nameResolverFactory(new FakeNameResolverFactory(
5165+
Collections.singletonList(URI.create(TARGET)),
5166+
Collections.emptyList(),
5167+
true,
5168+
null))
5169+
.childChannelConfigurer(mockChildChannelConfigurer)
5170+
.build();
5171+
5172+
assertThat(channel.getChildChannelConfigurer()).isSameInstanceAs(mockChildChannelConfigurer);
5173+
channel.shutdownNow();
5174+
}
5175+
5176+
@Test
5177+
public void configureChannel_propagatesConfigurerToNewBuilder_endToEnd() {
5178+
when(mockTransportFactory.getSupportedSocketAddressTypes())
5179+
.thenReturn(Collections.singleton(InetSocketAddress.class));
5180+
5181+
// 1. Setup Interceptor
5182+
final AtomicInteger interceptorCalls = new AtomicInteger(0);
5183+
final ClientInterceptor trackingInterceptor = new ClientInterceptor() {
5184+
@Override
5185+
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
5186+
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
5187+
interceptorCalls.incrementAndGet();
5188+
return next.newCall(method, callOptions);
5189+
}
5190+
};
5191+
5192+
// 2. Setup Configurer
5193+
ChildChannelConfigurer configurer = new ChildChannelConfigurer() {
5194+
@Override
5195+
public void accept(ManagedChannelBuilder<?> builder) {
5196+
builder.intercept(trackingInterceptor);
5197+
}
5198+
};
5199+
5200+
// 3. Create Parent Channel
5201+
ManagedChannelImplBuilder parentBuilder = new ManagedChannelImplBuilder("fake://parent-target",
5202+
new ClientTransportFactoryBuilder() {
5203+
@Override
5204+
public ClientTransportFactory buildClientTransportFactory() {
5205+
return mockTransportFactory;
5206+
}
5207+
},
5208+
new FixedPortProvider(DEFAULT_PORT));
5209+
5210+
ManagedChannel parentChannel = parentBuilder
5211+
// MATCH THE CONSTRUCTOR SIGNATURE: (List<URI>, List<EAG>, boolean, Status)
5212+
.nameResolverFactory(new FakeNameResolverFactory(
5213+
Collections.singletonList(URI.create("fake://parent-target")),
5214+
Collections.emptyList(),
5215+
true,
5216+
null))
5217+
.childChannelConfigurer(configurer)
5218+
.build();
5219+
5220+
// 4. Create Child Channel Builder
5221+
ManagedChannelImplBuilder childBuilder = new ManagedChannelImplBuilder("fake://child-target",
5222+
new ClientTransportFactoryBuilder() {
5223+
@Override
5224+
public ClientTransportFactory buildClientTransportFactory() {
5225+
return mockTransportFactory;
5226+
}
5227+
},
5228+
new FixedPortProvider(DEFAULT_PORT));
5229+
5230+
childBuilder.configureChannel(parentChannel);
5231+
5232+
// Ensure child also has a resolver factory
5233+
childBuilder.nameResolverFactory(new FakeNameResolverFactory(
5234+
Collections.singletonList(URI.create("fake://child-target")),
5235+
Collections.emptyList(),
5236+
true,
5237+
null));
5238+
5239+
ManagedChannel childChannel = childBuilder.build();
5240+
5241+
// 5. Verification
5242+
ClientCall<String, Integer> call = childChannel.newCall(
5243+
MethodDescriptor.<String, Integer>newBuilder()
5244+
.setType(MethodDescriptor.MethodType.UNARY)
5245+
.setFullMethodName("service/method")
5246+
.setRequestMarshaller(new StringMarshaller())
5247+
.setResponseMarshaller(new IntegerMarshaller())
5248+
.build(),
5249+
CallOptions.DEFAULT);
5250+
5251+
call.start(new ClientCall.Listener<Integer>() {
5252+
}, new Metadata());
5253+
5254+
assertThat(interceptorCalls.get())
5255+
.isEqualTo(1);
5256+
5257+
childChannel.shutdownNow();
5258+
parentChannel.shutdownNow();
5259+
}
51425260
}

core/src/test/java/io/grpc/internal/MetricRecorderImplTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.grpc.internal;
1818

19+
import static com.google.common.truth.Truth.assertThat;
1920
import static org.junit.Assert.assertThrows;
2021
import static org.mockito.ArgumentMatchers.any;
2122
import static org.mockito.ArgumentMatchers.anyList;
@@ -326,4 +327,25 @@ public void recordLongGaugeMismatchedOptionalLabelValues() {
326327
callbackCaptor.getValue().run();
327328
registration.close();
328329
}
330+
331+
@Test
332+
public void noOp_returnsSingleton() {
333+
assertThat(MetricRecorder.noOp()).isSameInstanceAs(MetricRecorder.noOp());
334+
}
335+
336+
@Test
337+
public void noOp_methodsDoNotThrow() {
338+
MetricRecorder recorder = MetricRecorder.noOp();
339+
340+
recorder.addDoubleCounter(null, 1.0,
341+
null, null);
342+
recorder.addLongCounter(null, 1,
343+
null, null);
344+
recorder.addLongUpDownCounter(null, 1,
345+
null, null);
346+
recorder.recordDoubleHistogram(null, 1.0,
347+
null, null);
348+
recorder.recordLongHistogram(null, 1,
349+
null, null);
350+
}
329351
}

xds/src/main/java/io/grpc/xds/SharedXdsClientPoolProvider.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ final class SharedXdsClientPoolProvider implements XdsClientPoolFactory {
5858
@Nullable
5959
private final Bootstrapper bootstrapper;
6060
private final Object lock = new Object();
61-
// The first one wins, anything with the same target string uses the client created for the first one
61+
/*
62+
The first one wins.
63+
Anything with the same target string uses the client created for the first one.
64+
*/
6265
private final Map<String, ObjectPool<XdsClient>> targetToXdsClientMap = new ConcurrentHashMap<>();
6366

6467
SharedXdsClientPoolProvider() {

0 commit comments

Comments
 (0)