1 /* 2 * Copyright 2016 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.internal; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static junit.framework.TestCase.assertFalse; 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertNotEquals; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertNull; 25 import static org.junit.Assert.assertTrue; 26 import static org.junit.Assert.fail; 27 import static org.mockito.Mockito.mock; 28 29 import com.google.common.util.concurrent.MoreExecutors; 30 import io.grpc.CallOptions; 31 import io.grpc.Channel; 32 import io.grpc.ClientCall; 33 import io.grpc.ClientInterceptor; 34 import io.grpc.CompressorRegistry; 35 import io.grpc.DecompressorRegistry; 36 import io.grpc.LoadBalancer; 37 import io.grpc.MethodDescriptor; 38 import io.grpc.NameResolver; 39 import io.grpc.internal.testing.StatsTestUtils.FakeStatsRecorder; 40 import io.grpc.internal.testing.StatsTestUtils.FakeTagContextBinarySerializer; 41 import io.grpc.internal.testing.StatsTestUtils.FakeTagger; 42 import java.net.InetSocketAddress; 43 import java.net.SocketAddress; 44 import java.net.URI; 45 import java.util.List; 46 import java.util.concurrent.Executor; 47 import java.util.concurrent.TimeUnit; 48 import org.junit.Rule; 49 import org.junit.Test; 50 import org.junit.rules.ExpectedException; 51 import org.junit.runner.RunWith; 52 import org.junit.runners.JUnit4; 53 54 /** Unit tests for {@link AbstractManagedChannelImplBuilder}. */ 55 @RunWith(JUnit4.class) 56 public class AbstractManagedChannelImplBuilderTest { 57 58 @Rule 59 public final ExpectedException thrown = ExpectedException.none(); 60 61 private static final ClientInterceptor DUMMY_USER_INTERCEPTOR = 62 new ClientInterceptor() { 63 @Override 64 public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall( 65 MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) { 66 return next.newCall(method, callOptions); 67 } 68 }; 69 70 private Builder builder = new Builder("fake"); 71 private Builder directAddressBuilder = new Builder(new SocketAddress(){}, "fake"); 72 73 @Test 74 public void executor_default() { 75 assertNotNull(builder.executorPool); 76 } 77 78 @Test 79 public void executor_normal() { 80 Executor executor = mock(Executor.class); 81 assertEquals(builder, builder.executor(executor)); 82 assertEquals(executor, builder.executorPool.getObject()); 83 } 84 85 @Test 86 public void executor_null() { 87 ObjectPool<? extends Executor> defaultValue = builder.executorPool; 88 builder.executor(mock(Executor.class)); 89 assertEquals(builder, builder.executor(null)); 90 assertEquals(defaultValue, builder.executorPool); 91 } 92 93 @Test 94 public void directExecutor() { 95 assertEquals(builder, builder.directExecutor()); 96 assertEquals(MoreExecutors.directExecutor(), builder.executorPool.getObject()); 97 } 98 99 @Test 100 public void nameResolverFactory_default() { 101 assertNotNull(builder.getNameResolverFactory()); 102 } 103 104 @Test 105 public void nameResolverFactory_normal() { 106 NameResolver.Factory nameResolverFactory = mock(NameResolver.Factory.class); 107 assertEquals(builder, builder.nameResolverFactory(nameResolverFactory)); 108 assertEquals(nameResolverFactory, builder.getNameResolverFactory()); 109 } 110 111 @Test 112 public void nameResolverFactory_null() { 113 NameResolver.Factory defaultValue = builder.getNameResolverFactory(); 114 builder.nameResolverFactory(mock(NameResolver.Factory.class)); 115 assertEquals(builder, builder.nameResolverFactory(null)); 116 assertEquals(defaultValue, builder.getNameResolverFactory()); 117 } 118 119 @Test(expected = IllegalStateException.class) 120 public void nameResolverFactory_notAllowedWithDirectAddress() { 121 directAddressBuilder.nameResolverFactory(mock(NameResolver.Factory.class)); 122 } 123 124 @Test 125 public void loadBalancerFactory_default() { 126 assertNull(builder.loadBalancerFactory); 127 } 128 129 @Test 130 public void loadBalancerFactory_normal() { 131 LoadBalancer.Factory loadBalancerFactory = mock(LoadBalancer.Factory.class); 132 assertEquals(builder, builder.loadBalancerFactory(loadBalancerFactory)); 133 assertEquals(loadBalancerFactory, builder.loadBalancerFactory); 134 } 135 136 @Test 137 public void loadBalancerFactory_null() { 138 LoadBalancer.Factory defaultValue = builder.loadBalancerFactory; 139 builder.loadBalancerFactory(mock(LoadBalancer.Factory.class)); 140 assertEquals(builder, builder.loadBalancerFactory(null)); 141 assertEquals(defaultValue, builder.loadBalancerFactory); 142 } 143 144 @Test(expected = IllegalStateException.class) 145 public void loadBalancerFactory_notAllowedWithDirectAddress() { 146 directAddressBuilder.loadBalancerFactory(mock(LoadBalancer.Factory.class)); 147 } 148 149 @Test 150 public void fullStreamDecompression_default() { 151 assertFalse(builder.fullStreamDecompression); 152 } 153 154 @Test 155 public void fullStreamDecompression_enabled() { 156 assertEquals(builder, builder.enableFullStreamDecompression()); 157 assertTrue(builder.fullStreamDecompression); 158 } 159 160 @Test 161 public void decompressorRegistry_default() { 162 assertNotNull(builder.decompressorRegistry); 163 } 164 165 @Test 166 public void decompressorRegistry_normal() { 167 DecompressorRegistry decompressorRegistry = DecompressorRegistry.emptyInstance(); 168 assertNotEquals(decompressorRegistry, builder.decompressorRegistry); 169 assertEquals(builder, builder.decompressorRegistry(decompressorRegistry)); 170 assertEquals(decompressorRegistry, builder.decompressorRegistry); 171 } 172 173 @Test 174 public void decompressorRegistry_null() { 175 DecompressorRegistry defaultValue = builder.decompressorRegistry; 176 assertEquals(builder, builder.decompressorRegistry(DecompressorRegistry.emptyInstance())); 177 assertNotEquals(defaultValue, builder.decompressorRegistry); 178 builder.decompressorRegistry(null); 179 assertEquals(defaultValue, builder.decompressorRegistry); 180 } 181 182 @Test 183 public void compressorRegistry_default() { 184 assertNotNull(builder.compressorRegistry); 185 } 186 187 @Test 188 public void compressorRegistry_normal() { 189 CompressorRegistry compressorRegistry = CompressorRegistry.newEmptyInstance(); 190 assertNotEquals(compressorRegistry, builder.compressorRegistry); 191 assertEquals(builder, builder.compressorRegistry(compressorRegistry)); 192 assertEquals(compressorRegistry, builder.compressorRegistry); 193 } 194 195 @Test 196 public void compressorRegistry_null() { 197 CompressorRegistry defaultValue = builder.compressorRegistry; 198 builder.compressorRegistry(CompressorRegistry.newEmptyInstance()); 199 assertNotEquals(defaultValue, builder.compressorRegistry); 200 assertEquals(builder, builder.compressorRegistry(null)); 201 assertEquals(defaultValue, builder.compressorRegistry); 202 } 203 204 @Test 205 public void userAgent_default() { 206 assertNull(builder.userAgent); 207 } 208 209 @Test 210 public void userAgent_normal() { 211 String userAgent = "user-agent/1"; 212 assertEquals(builder, builder.userAgent(userAgent)); 213 assertEquals(userAgent, builder.userAgent); 214 } 215 216 @Test 217 public void userAgent_null() { 218 assertEquals(builder, builder.userAgent(null)); 219 assertNull(builder.userAgent); 220 221 builder.userAgent("user-agent/1"); 222 builder.userAgent(null); 223 assertNull(builder.userAgent); 224 } 225 226 @Test 227 public void overrideAuthority_default() { 228 assertNull(builder.authorityOverride); 229 } 230 231 @Test 232 public void overrideAuthority_normal() { 233 String overrideAuthority = "best-authority"; 234 assertEquals(builder, builder.overrideAuthority(overrideAuthority)); 235 assertEquals(overrideAuthority, builder.authorityOverride); 236 } 237 238 @Test(expected = NullPointerException.class) 239 public void overrideAuthority_null() { 240 builder.overrideAuthority(null); 241 } 242 243 @Test(expected = IllegalArgumentException.class) 244 public void overrideAuthority_invalid() { 245 builder.overrideAuthority("not_allowed"); 246 } 247 248 @Test 249 public void overrideAuthority_getNameResolverFactory() { 250 Builder builder = new Builder("target"); 251 assertNull(builder.authorityOverride); 252 assertFalse(builder.getNameResolverFactory() instanceof OverrideAuthorityNameResolverFactory); 253 builder.overrideAuthority("google.com"); 254 assertTrue(builder.getNameResolverFactory() instanceof OverrideAuthorityNameResolverFactory); 255 } 256 257 @Test 258 public void makeTargetStringForDirectAddress_scopedIpv6() throws Exception { 259 InetSocketAddress address = new InetSocketAddress("0:0:0:0:0:0:0:0%0", 10005); 260 assertEquals("/0:0:0:0:0:0:0:0%0:10005", address.toString()); 261 String target = AbstractManagedChannelImplBuilder.makeTargetStringForDirectAddress(address); 262 URI uri = new URI(target); 263 assertEquals("directaddress:////0:0:0:0:0:0:0:0%250:10005", target); 264 assertEquals(target, uri.toString()); 265 } 266 267 @Test 268 public void getEffectiveInterceptors_default() { 269 builder.intercept(DUMMY_USER_INTERCEPTOR); 270 List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors(); 271 assertEquals(3, effectiveInterceptors.size()); 272 assertThat(effectiveInterceptors.get(0)) 273 .isInstanceOf(CensusTracingModule.TracingClientInterceptor.class); 274 assertThat(effectiveInterceptors.get(1)) 275 .isInstanceOf(CensusStatsModule.StatsClientInterceptor.class); 276 assertThat(effectiveInterceptors.get(2)).isSameAs(DUMMY_USER_INTERCEPTOR); 277 } 278 279 @Test 280 public void getEffectiveInterceptors_disableStats() { 281 builder.intercept(DUMMY_USER_INTERCEPTOR); 282 builder.setStatsEnabled(false); 283 List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors(); 284 assertEquals(2, effectiveInterceptors.size()); 285 assertThat(effectiveInterceptors.get(0)) 286 .isInstanceOf(CensusTracingModule.TracingClientInterceptor.class); 287 assertThat(effectiveInterceptors.get(1)).isSameAs(DUMMY_USER_INTERCEPTOR); 288 } 289 290 @Test 291 public void getEffectiveInterceptors_disableTracing() { 292 builder.intercept(DUMMY_USER_INTERCEPTOR); 293 builder.setTracingEnabled(false); 294 List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors(); 295 assertEquals(2, effectiveInterceptors.size()); 296 assertThat(effectiveInterceptors.get(0)) 297 .isInstanceOf(CensusStatsModule.StatsClientInterceptor.class); 298 assertThat(effectiveInterceptors.get(1)).isSameAs(DUMMY_USER_INTERCEPTOR); 299 } 300 301 @Test 302 public void getEffectiveInterceptors_disableBoth() { 303 builder.intercept(DUMMY_USER_INTERCEPTOR); 304 builder.setStatsEnabled(false); 305 builder.setTracingEnabled(false); 306 List<ClientInterceptor> effectiveInterceptors = builder.getEffectiveInterceptors(); 307 assertThat(effectiveInterceptors).containsExactly(DUMMY_USER_INTERCEPTOR); 308 } 309 310 @Test 311 public void idleTimeout() { 312 Builder builder = new Builder("target"); 313 314 assertEquals(AbstractManagedChannelImplBuilder.IDLE_MODE_DEFAULT_TIMEOUT_MILLIS, 315 builder.getIdleTimeoutMillis()); 316 317 builder.idleTimeout(Long.MAX_VALUE, TimeUnit.DAYS); 318 assertEquals(ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE, builder.getIdleTimeoutMillis()); 319 320 builder.idleTimeout(AbstractManagedChannelImplBuilder.IDLE_MODE_MAX_TIMEOUT_DAYS, 321 TimeUnit.DAYS); 322 assertEquals(ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE, builder.getIdleTimeoutMillis()); 323 324 try { 325 builder.idleTimeout(0, TimeUnit.SECONDS); 326 fail("Should throw"); 327 } catch (IllegalArgumentException e) { 328 // expected 329 } 330 331 builder.idleTimeout(1, TimeUnit.NANOSECONDS); 332 assertEquals(AbstractManagedChannelImplBuilder.IDLE_MODE_MIN_TIMEOUT_MILLIS, 333 builder.getIdleTimeoutMillis()); 334 335 builder.idleTimeout(30, TimeUnit.SECONDS); 336 assertEquals(TimeUnit.SECONDS.toMillis(30), builder.getIdleTimeoutMillis()); 337 } 338 339 @Test 340 public void maxRetryAttempts() { 341 Builder builder = new Builder("target"); 342 assertEquals(5, builder.maxRetryAttempts); 343 344 builder.maxRetryAttempts(3); 345 assertEquals(3, builder.maxRetryAttempts); 346 } 347 348 @Test 349 public void maxHedgedAttempts() { 350 Builder builder = new Builder("target"); 351 assertEquals(5, builder.maxHedgedAttempts); 352 353 builder.maxHedgedAttempts(3); 354 assertEquals(3, builder.maxHedgedAttempts); 355 } 356 357 @Test 358 public void retryBufferSize() { 359 Builder builder = new Builder("target"); 360 assertEquals(1L << 24, builder.retryBufferSize); 361 362 builder.retryBufferSize(3456L); 363 assertEquals(3456L, builder.retryBufferSize); 364 } 365 366 @Test 367 public void perRpcBufferLimit() { 368 Builder builder = new Builder("target"); 369 assertEquals(1L << 20, builder.perRpcBufferLimit); 370 371 builder.perRpcBufferLimit(3456L); 372 assertEquals(3456L, builder.perRpcBufferLimit); 373 } 374 375 @Test 376 public void retryBufferSizeInvalidArg() { 377 Builder builder = new Builder("target"); 378 379 thrown.expect(IllegalArgumentException.class); 380 builder.retryBufferSize(0L); 381 } 382 383 @Test 384 public void perRpcBufferLimitInvalidArg() { 385 Builder builder = new Builder("target"); 386 387 thrown.expect(IllegalArgumentException.class); 388 builder.perRpcBufferLimit(0L); 389 } 390 391 @Test 392 public void disableRetry() { 393 Builder builder = new Builder("target"); 394 395 builder.enableRetry(); 396 assertTrue(builder.retryEnabled); 397 398 builder.disableRetry(); 399 assertFalse(builder.retryEnabled); 400 401 builder.enableRetry(); 402 assertTrue(builder.retryEnabled); 403 404 builder.disableRetry(); 405 assertFalse(builder.retryEnabled); 406 } 407 408 static class Builder extends AbstractManagedChannelImplBuilder<Builder> { 409 Builder(String target) { 410 super(target); 411 overrideCensusStatsModule( 412 new CensusStatsModule( 413 new FakeTagger(), 414 new FakeTagContextBinarySerializer(), 415 new FakeStatsRecorder(), 416 GrpcUtil.STOPWATCH_SUPPLIER, 417 true)); 418 } 419 420 Builder(SocketAddress directServerAddress, String authority) { 421 super(directServerAddress, authority); 422 overrideCensusStatsModule( 423 new CensusStatsModule( 424 new FakeTagger(), 425 new FakeTagContextBinarySerializer(), 426 new FakeStatsRecorder(), 427 GrpcUtil.STOPWATCH_SUPPLIER, 428 true)); 429 } 430 431 @Override 432 protected ClientTransportFactory buildTransportFactory() { 433 throw new UnsupportedOperationException(); 434 } 435 } 436 } 437