1 /* 2 * Copyright 2020 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 com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.fail; 21 22 import com.google.common.collect.ImmutableSet; 23 import java.net.InetSocketAddress; 24 import java.net.SocketAddress; 25 import java.net.URI; 26 import java.util.Collection; 27 import java.util.Collections; 28 import org.junit.Test; 29 import org.junit.runner.RunWith; 30 import org.junit.runners.JUnit4; 31 32 /** Unit tests for {@link ManagedChannelRegistry}. */ 33 @RunWith(JUnit4.class) 34 public class ManagedChannelRegistryTest { 35 private String target = "testing123"; 36 private ChannelCredentials creds = new ChannelCredentials() { 37 @Override 38 public ChannelCredentials withoutBearerTokens() { 39 throw new UnsupportedOperationException(); 40 } 41 }; 42 43 @Test register_unavailableProviderThrows()44 public void register_unavailableProviderThrows() { 45 ManagedChannelRegistry reg = new ManagedChannelRegistry(); 46 try { 47 reg.register(new BaseProvider(false, 5)); 48 fail("Should throw"); 49 } catch (IllegalArgumentException e) { 50 assertThat(e).hasMessageThat().contains("isAvailable() returned false"); 51 } 52 assertThat(reg.providers()).isEmpty(); 53 } 54 55 @Test deregister()56 public void deregister() { 57 ManagedChannelRegistry reg = new ManagedChannelRegistry(); 58 ManagedChannelProvider p1 = new BaseProvider(true, 5); 59 ManagedChannelProvider p2 = new BaseProvider(true, 5); 60 ManagedChannelProvider p3 = new BaseProvider(true, 5); 61 reg.register(p1); 62 reg.register(p2); 63 reg.register(p3); 64 assertThat(reg.providers()).containsExactly(p1, p2, p3).inOrder(); 65 reg.deregister(p2); 66 assertThat(reg.providers()).containsExactly(p1, p3).inOrder(); 67 } 68 69 @Test provider_sorted()70 public void provider_sorted() { 71 ManagedChannelRegistry reg = new ManagedChannelRegistry(); 72 ManagedChannelProvider p1 = new BaseProvider(true, 5); 73 ManagedChannelProvider p2 = new BaseProvider(true, 3); 74 ManagedChannelProvider p3 = new BaseProvider(true, 8); 75 ManagedChannelProvider p4 = new BaseProvider(true, 3); 76 ManagedChannelProvider p5 = new BaseProvider(true, 8); 77 reg.register(p1); 78 reg.register(p2); 79 reg.register(p3); 80 reg.register(p4); 81 reg.register(p5); 82 assertThat(reg.providers()).containsExactly(p3, p5, p1, p2, p4).inOrder(); 83 } 84 85 @Test getProvider_noProvider()86 public void getProvider_noProvider() { 87 assertThat(new ManagedChannelRegistry().provider()).isNull(); 88 } 89 90 @Test newChannelBuilder_providerReturnsError()91 public void newChannelBuilder_providerReturnsError() { 92 final String errorString = "brisking"; 93 class ErrorProvider extends BaseProvider { 94 ErrorProvider() { 95 super(true, 5); 96 } 97 98 @Override 99 public NewChannelBuilderResult newChannelBuilder( 100 String passedTarget, ChannelCredentials passedCreds) { 101 assertThat(passedTarget).isSameInstanceAs(target); 102 assertThat(passedCreds).isSameInstanceAs(creds); 103 return NewChannelBuilderResult.error(errorString); 104 } 105 } 106 107 ManagedChannelRegistry registry = new ManagedChannelRegistry(); 108 registry.register(new ErrorProvider()); 109 try { 110 registry.newChannelBuilder(target, creds); 111 fail("expected exception"); 112 } catch (ManagedChannelRegistry.ProviderNotFoundException ex) { 113 assertThat(ex).hasMessageThat().contains(errorString); 114 assertThat(ex).hasMessageThat().contains(ErrorProvider.class.getName()); 115 } 116 } 117 118 @Test newChannelBuilder_providerReturnsNonNull()119 public void newChannelBuilder_providerReturnsNonNull() { 120 ManagedChannelRegistry registry = new ManagedChannelRegistry(); 121 registry.register(new BaseProvider(true, 5) { 122 @Override 123 public NewChannelBuilderResult newChannelBuilder( 124 String passedTarget, ChannelCredentials passedCreds) { 125 return NewChannelBuilderResult.error("dodging"); 126 } 127 }); 128 class MockChannelBuilder extends ForwardingChannelBuilder<MockChannelBuilder> { 129 @Override public ManagedChannelBuilder<?> delegate() { 130 throw new UnsupportedOperationException(); 131 } 132 } 133 134 final ManagedChannelBuilder<?> mcb = new MockChannelBuilder(); 135 registry.register(new BaseProvider(true, 4) { 136 @Override 137 public NewChannelBuilderResult newChannelBuilder( 138 String passedTarget, ChannelCredentials passedCreds) { 139 return NewChannelBuilderResult.channelBuilder(mcb); 140 } 141 }); 142 registry.register(new BaseProvider(true, 3) { 143 @Override 144 public NewChannelBuilderResult newChannelBuilder( 145 String passedTarget, ChannelCredentials passedCreds) { 146 fail("Should not be called"); 147 throw new AssertionError(); 148 } 149 }); 150 assertThat(registry.newChannelBuilder(target, creds)).isSameInstanceAs(mcb); 151 } 152 153 @Test newChannelBuilder_noProvider()154 public void newChannelBuilder_noProvider() { 155 ManagedChannelRegistry registry = new ManagedChannelRegistry(); 156 try { 157 registry.newChannelBuilder(target, creds); 158 fail("expected exception"); 159 } catch (ManagedChannelRegistry.ProviderNotFoundException ex) { 160 assertThat(ex).hasMessageThat().contains("No functional channel service provider found"); 161 assertThat(ex).hasMessageThat().contains("grpc-netty"); 162 } 163 } 164 165 @Test newChannelBuilder_usesScheme()166 public void newChannelBuilder_usesScheme() { 167 NameResolverRegistry nameResolverRegistry = new NameResolverRegistry(); 168 class SocketAddress1 extends SocketAddress { 169 } 170 171 class SocketAddress2 extends SocketAddress { 172 } 173 174 nameResolverRegistry.register(new BaseNameResolverProvider(true, 5, "sc1") { 175 @Override 176 protected Collection<Class<? extends SocketAddress>> getProducedSocketAddressTypes() { 177 return Collections.singleton(SocketAddress1.class); 178 } 179 }); 180 nameResolverRegistry.register(new BaseNameResolverProvider(true, 6, "sc2") { 181 @Override 182 protected Collection<Class<? extends SocketAddress>> getProducedSocketAddressTypes() { 183 fail("Should not be called"); 184 throw new AssertionError(); 185 } 186 }); 187 188 ManagedChannelRegistry registry = new ManagedChannelRegistry(); 189 registry.register(new BaseProvider(true, 5) { 190 @Override 191 protected Collection<Class<? extends SocketAddress>> getSupportedSocketAddressTypes() { 192 return Collections.singleton(SocketAddress2.class); 193 } 194 195 @Override 196 public NewChannelBuilderResult newChannelBuilder( 197 String passedTarget, ChannelCredentials passedCreds) { 198 fail("Should not be called"); 199 throw new AssertionError(); 200 } 201 }); 202 class MockChannelBuilder extends ForwardingChannelBuilder<MockChannelBuilder> { 203 @Override public ManagedChannelBuilder<?> delegate() { 204 throw new UnsupportedOperationException(); 205 } 206 } 207 208 final ManagedChannelBuilder<?> mcb = new MockChannelBuilder(); 209 registry.register(new BaseProvider(true, 4) { 210 @Override 211 protected Collection<Class<? extends SocketAddress>> getSupportedSocketAddressTypes() { 212 return Collections.singleton(SocketAddress1.class); 213 } 214 215 @Override 216 public NewChannelBuilderResult newChannelBuilder( 217 String passedTarget, ChannelCredentials passedCreds) { 218 return NewChannelBuilderResult.channelBuilder(mcb); 219 } 220 }); 221 assertThat( 222 registry.newChannelBuilder(nameResolverRegistry, "sc1:" + target, creds)).isSameInstanceAs( 223 mcb); 224 } 225 226 @Test newChannelBuilder_unsupportedSocketAddressTypes()227 public void newChannelBuilder_unsupportedSocketAddressTypes() { 228 NameResolverRegistry nameResolverRegistry = new NameResolverRegistry(); 229 class SocketAddress1 extends SocketAddress { 230 } 231 232 class SocketAddress2 extends SocketAddress { 233 } 234 235 nameResolverRegistry.register(new BaseNameResolverProvider(true, 5, "sc1") { 236 @Override 237 protected Collection<Class<? extends SocketAddress>> getProducedSocketAddressTypes() { 238 return ImmutableSet.of(SocketAddress1.class, SocketAddress2.class); 239 } 240 }); 241 242 ManagedChannelRegistry registry = new ManagedChannelRegistry(); 243 registry.register(new BaseProvider(true, 5) { 244 @Override 245 protected Collection<Class<? extends SocketAddress>> getSupportedSocketAddressTypes() { 246 return Collections.singleton(SocketAddress2.class); 247 } 248 249 @Override 250 public NewChannelBuilderResult newChannelBuilder( 251 String passedTarget, ChannelCredentials passedCreds) { 252 fail("Should not be called"); 253 throw new AssertionError(); 254 } 255 }); 256 257 registry.register(new BaseProvider(true, 4) { 258 @Override 259 protected Collection<Class<? extends SocketAddress>> getSupportedSocketAddressTypes() { 260 return Collections.singleton(SocketAddress1.class); 261 } 262 263 @Override 264 public NewChannelBuilderResult newChannelBuilder( 265 String passedTarget, ChannelCredentials passedCreds) { 266 fail("Should not be called"); 267 throw new AssertionError(); 268 } 269 }); 270 try { 271 registry.newChannelBuilder(nameResolverRegistry, "sc1:" + target, creds); 272 fail("expected exception"); 273 } catch (ManagedChannelRegistry.ProviderNotFoundException ex) { 274 assertThat(ex).hasMessageThat().contains("does not support 1 or more of"); 275 assertThat(ex).hasMessageThat().contains("SocketAddress1"); 276 assertThat(ex).hasMessageThat().contains("SocketAddress2"); 277 } 278 } 279 280 @Test newChannelBuilder_emptySet_asDefault()281 public void newChannelBuilder_emptySet_asDefault() { 282 NameResolverRegistry nameResolverRegistry = new NameResolverRegistry(); 283 284 ManagedChannelRegistry registry = new ManagedChannelRegistry(); 285 class MockChannelBuilder extends ForwardingChannelBuilder<MockChannelBuilder> { 286 @Override public ManagedChannelBuilder<?> delegate() { 287 throw new UnsupportedOperationException(); 288 } 289 } 290 291 final ManagedChannelBuilder<?> mcb = new MockChannelBuilder(); 292 registry.register(new BaseProvider(true, 4) { 293 @Override 294 protected Collection<Class<? extends SocketAddress>> getSupportedSocketAddressTypes() { 295 return Collections.emptySet(); 296 } 297 298 @Override 299 public NewChannelBuilderResult newChannelBuilder( 300 String passedTarget, ChannelCredentials passedCreds) { 301 return NewChannelBuilderResult.channelBuilder(mcb); 302 } 303 }); 304 assertThat( 305 registry.newChannelBuilder(nameResolverRegistry, "sc1:" + target, creds)).isSameInstanceAs( 306 mcb); 307 } 308 309 @Test newChannelBuilder_noSchemeUsesDefaultScheme()310 public void newChannelBuilder_noSchemeUsesDefaultScheme() { 311 NameResolverRegistry nameResolverRegistry = new NameResolverRegistry(); 312 class SocketAddress1 extends SocketAddress { 313 } 314 315 nameResolverRegistry.register(new BaseNameResolverProvider(true, 5, "sc1") { 316 @Override 317 protected Collection<Class<? extends SocketAddress>> getProducedSocketAddressTypes() { 318 return Collections.singleton(SocketAddress1.class); 319 } 320 }); 321 322 ManagedChannelRegistry registry = new ManagedChannelRegistry(); 323 class MockChannelBuilder extends ForwardingChannelBuilder<MockChannelBuilder> { 324 @Override public ManagedChannelBuilder<?> delegate() { 325 throw new UnsupportedOperationException(); 326 } 327 } 328 329 final ManagedChannelBuilder<?> mcb = new MockChannelBuilder(); 330 registry.register(new BaseProvider(true, 4) { 331 @Override 332 protected Collection<Class<? extends SocketAddress>> getSupportedSocketAddressTypes() { 333 return Collections.singleton(SocketAddress1.class); 334 } 335 336 @Override 337 public NewChannelBuilderResult newChannelBuilder( 338 String passedTarget, ChannelCredentials passedCreds) { 339 return NewChannelBuilderResult.channelBuilder(mcb); 340 } 341 }); 342 assertThat(registry.newChannelBuilder(nameResolverRegistry, target, creds)).isSameInstanceAs( 343 mcb); 344 } 345 346 @Test newChannelBuilder_badUri()347 public void newChannelBuilder_badUri() { 348 NameResolverRegistry nameResolverRegistry = new NameResolverRegistry(); 349 class SocketAddress1 extends SocketAddress { 350 } 351 352 ManagedChannelRegistry registry = new ManagedChannelRegistry(); 353 354 class MockChannelBuilder extends ForwardingChannelBuilder<MockChannelBuilder> { 355 @Override public ManagedChannelBuilder<?> delegate() { 356 throw new UnsupportedOperationException(); 357 } 358 } 359 360 final ManagedChannelBuilder<?> mcb = new MockChannelBuilder(); 361 registry.register(new BaseProvider(true, 4) { 362 @Override 363 protected Collection<Class<? extends SocketAddress>> getSupportedSocketAddressTypes() { 364 return Collections.singleton(SocketAddress1.class); 365 } 366 367 @Override 368 public NewChannelBuilderResult newChannelBuilder( 369 String passedTarget, ChannelCredentials passedCreds) { 370 return NewChannelBuilderResult.channelBuilder(mcb); 371 } 372 }); 373 assertThat( 374 registry.newChannelBuilder(nameResolverRegistry, ":testing123", creds)).isSameInstanceAs( 375 mcb); 376 } 377 378 private static class BaseNameResolverProvider extends NameResolverProvider { 379 private final boolean isAvailable; 380 private final int priority; 381 private final String defaultScheme; 382 BaseNameResolverProvider(boolean isAvailable, int priority, String defaultScheme)383 public BaseNameResolverProvider(boolean isAvailable, int priority, String defaultScheme) { 384 this.isAvailable = isAvailable; 385 this.priority = priority; 386 this.defaultScheme = defaultScheme; 387 } 388 389 @Override newNameResolver(URI targetUri, NameResolver.Args args)390 public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) { 391 return null; 392 } 393 394 @Override getDefaultScheme()395 public String getDefaultScheme() { 396 return defaultScheme; 397 } 398 399 @Override isAvailable()400 protected boolean isAvailable() { 401 return isAvailable; 402 } 403 404 @Override priority()405 protected int priority() { 406 return priority; 407 } 408 } 409 410 private static class BaseProvider extends ManagedChannelProvider { 411 private final boolean isAvailable; 412 private final int priority; 413 BaseProvider(boolean isAvailable, int priority)414 public BaseProvider(boolean isAvailable, int priority) { 415 this.isAvailable = isAvailable; 416 this.priority = priority; 417 } 418 419 @Override isAvailable()420 protected boolean isAvailable() { 421 return isAvailable; 422 } 423 424 @Override priority()425 protected int priority() { 426 return priority; 427 } 428 429 @Override builderForAddress(String name, int port)430 protected ManagedChannelBuilder<?> builderForAddress(String name, int port) { 431 throw new UnsupportedOperationException(); 432 } 433 434 @Override builderForTarget(String target)435 protected ManagedChannelBuilder<?> builderForTarget(String target) { 436 throw new UnsupportedOperationException(); 437 } 438 439 @Override getSupportedSocketAddressTypes()440 protected Collection<Class<? extends SocketAddress>> getSupportedSocketAddressTypes() { 441 return Collections.singleton(InetSocketAddress.class); 442 } 443 } 444 } 445