|
69 | 69 | import io.grpc.Channel; |
70 | 70 | import io.grpc.ChannelCredentials; |
71 | 71 | import io.grpc.ChannelLogger; |
| 72 | +import io.grpc.ChildChannelConfigurer; |
72 | 73 | import io.grpc.ClientCall; |
73 | 74 | import io.grpc.ClientInterceptor; |
74 | 75 | import io.grpc.ClientInterceptors; |
|
101 | 102 | import io.grpc.LoadBalancerRegistry; |
102 | 103 | import io.grpc.LongCounterMetricInstrument; |
103 | 104 | import io.grpc.ManagedChannel; |
| 105 | +import io.grpc.ManagedChannelBuilder; |
104 | 106 | import io.grpc.Metadata; |
105 | 107 | import io.grpc.MethodDescriptor; |
106 | 108 | import io.grpc.MethodDescriptor.MethodType; |
107 | 109 | import io.grpc.MetricInstrumentRegistry; |
| 110 | +import io.grpc.MetricRecorder; |
108 | 111 | import io.grpc.MetricSink; |
109 | 112 | import io.grpc.NameResolver; |
110 | 113 | import io.grpc.NameResolver.ConfigOrError; |
@@ -302,9 +305,12 @@ public String getPolicyName() { |
302 | 305 | private boolean panicExpected; |
303 | 306 | @Captor |
304 | 307 | private ArgumentCaptor<ResolvedAddresses> resolvedAddressCaptor; |
305 | | - |
306 | 308 | private ArgumentCaptor<ClientStreamListener> streamListenerCaptor = |
307 | 309 | ArgumentCaptor.forClass(ClientStreamListener.class); |
| 310 | + @Mock |
| 311 | + private ChildChannelConfigurer mockChildChannelConfigurer; |
| 312 | + @Mock |
| 313 | + private MetricRecorder mockMetricRecorder; |
308 | 314 |
|
309 | 315 | private void createChannel(ClientInterceptor... interceptors) { |
310 | 316 | createChannel(false, interceptors); |
@@ -5139,4 +5145,116 @@ private static ManagedChannelServiceConfig createManagedChannelServiceConfig( |
5139 | 5145 | return ManagedChannelServiceConfig |
5140 | 5146 | .fromServiceConfig(rawServiceConfig, true, 3, 4, policySelection); |
5141 | 5147 | } |
| 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 | + } |
5142 | 5260 | } |
0 commit comments