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; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.fail; 21 import static org.mockito.Mockito.mock; 22 23 import io.grpc.NameResolver.ServiceConfigParser; 24 import io.grpc.internal.DnsNameResolverProvider; 25 import java.lang.Thread.UncaughtExceptionHandler; 26 import java.net.URI; 27 import java.util.List; 28 import java.util.Map; 29 import org.junit.Test; 30 import org.junit.runner.RunWith; 31 import org.junit.runners.JUnit4; 32 33 /** Unit tests for {@link NameResolverRegistry}. */ 34 @RunWith(JUnit4.class) 35 public class NameResolverRegistryTest { 36 private final URI uri = URI.create("dns:///localhost"); 37 private final NameResolver.Args args = NameResolver.Args.newBuilder() 38 .setDefaultPort(8080) 39 .setProxyDetector(mock(ProxyDetector.class)) 40 .setSynchronizationContext(new SynchronizationContext(mock(UncaughtExceptionHandler.class))) 41 .setServiceConfigParser(mock(ServiceConfigParser.class)) 42 .setChannelLogger(mock(ChannelLogger.class)) 43 .build(); 44 45 @Test register_unavilableProviderThrows()46 public void register_unavilableProviderThrows() { 47 NameResolverRegistry reg = new NameResolverRegistry(); 48 try { 49 reg.register(new BaseProvider(false, 5)); 50 fail("Should throw"); 51 } catch (IllegalArgumentException e) { 52 assertThat(e).hasMessageThat().contains("isAvailable() returned false"); 53 } 54 assertThat(reg.providers()).isEmpty(); 55 } 56 57 @Test deregister()58 public void deregister() { 59 NameResolverRegistry reg = new NameResolverRegistry(); 60 NameResolverProvider p1 = new BaseProvider(true, 5); 61 NameResolverProvider p2 = new BaseProvider(true, 5); 62 NameResolverProvider p3 = new BaseProvider(true, 5); 63 String sameScheme = p1.getDefaultScheme(); 64 reg.register(p1); 65 reg.register(p2); 66 reg.register(p3); 67 assertThat(reg.providers().get(sameScheme)).isSameInstanceAs(p1); 68 reg.deregister(p2); 69 assertThat(reg.providers().get(sameScheme)).isSameInstanceAs(p1); 70 reg.deregister(p1); 71 assertThat(reg.providers().get(sameScheme)).isSameInstanceAs(p3); 72 73 } 74 75 @Test provider_sorted()76 public void provider_sorted() { 77 NameResolverRegistry reg = new NameResolverRegistry(); 78 NameResolverProvider p1 = new BaseProvider(true, 5); 79 NameResolverProvider p2 = new BaseProvider(true, 3); 80 NameResolverProvider p3 = new BaseProvider(true, 8); 81 NameResolverProvider p4 = new BaseProvider(true, 3); 82 NameResolverProvider p5 = new BaseProvider(true, 8); 83 String sameScheme = p1.getDefaultScheme(); 84 reg.register(p1); 85 reg.register(p2); 86 reg.register(p3); 87 reg.register(p4); 88 reg.register(p5); 89 assertThat(reg.providers().get(sameScheme)).isSameInstanceAs(p3); 90 } 91 92 @Test getDefaultScheme_noProvider()93 public void getDefaultScheme_noProvider() { 94 NameResolver.Factory factory = new NameResolverRegistry().asFactory(); 95 assertThat(factory.getDefaultScheme()).isEqualTo("unknown"); 96 } 97 98 @Test newNameResolver_providerReturnsNull()99 public void newNameResolver_providerReturnsNull() { 100 NameResolverRegistry registry = new NameResolverRegistry(); 101 registry.register( 102 new BaseProvider(true, 5, "noScheme") { 103 @Override 104 public NameResolver newNameResolver(URI passedUri, NameResolver.Args passedArgs) { 105 assertThat(passedUri).isSameInstanceAs(uri); 106 assertThat(passedArgs).isSameInstanceAs(args); 107 return null; 108 } 109 }); 110 assertThat(registry.asFactory().newNameResolver(uri, args)).isNull(); 111 assertThat(registry.asFactory().getDefaultScheme()).isEqualTo("noScheme"); 112 } 113 114 @Test newNameResolver_providerReturnsNonNull()115 public void newNameResolver_providerReturnsNonNull() { 116 NameResolverRegistry registry = new NameResolverRegistry(); 117 registry.register(new BaseProvider(true, 5, uri.getScheme()) { 118 @Override 119 public NameResolver newNameResolver(URI passedUri, NameResolver.Args passedArgs) { 120 return null; 121 } 122 }); 123 final NameResolver nr = new NameResolver() { 124 @Override public String getServiceAuthority() { 125 throw new UnsupportedOperationException(); 126 } 127 128 @Override public void start(Listener2 listener) { 129 throw new UnsupportedOperationException(); 130 } 131 132 @Override public void shutdown() { 133 throw new UnsupportedOperationException(); 134 } 135 }; 136 registry.register( 137 new BaseProvider(true, 4, uri.getScheme()) { 138 @Override 139 public NameResolver newNameResolver(URI passedUri, NameResolver.Args passedArgs) { 140 return nr; 141 } 142 }); 143 registry.register( 144 new BaseProvider(true, 3, uri.getScheme()) { 145 @Override 146 public NameResolver newNameResolver(URI passedUri, NameResolver.Args passedArgs) { 147 fail("Should not be called"); 148 throw new AssertionError(); 149 } 150 }); 151 assertThat(registry.asFactory().newNameResolver(uri, args)).isNull(); 152 assertThat(registry.asFactory().getDefaultScheme()).isEqualTo(uri.getScheme()); 153 } 154 155 @Test newNameResolver_multipleScheme()156 public void newNameResolver_multipleScheme() { 157 NameResolverRegistry registry = new NameResolverRegistry(); 158 registry.register(new BaseProvider(true, 5, uri.getScheme()) { 159 @Override 160 public NameResolver newNameResolver(URI passedUri, NameResolver.Args passedArgs) { 161 return null; 162 } 163 }); 164 final NameResolver nr = new NameResolver() { 165 @Override public String getServiceAuthority() { 166 throw new UnsupportedOperationException(); 167 } 168 169 @Override public void start(Listener2 listener) { 170 throw new UnsupportedOperationException(); 171 } 172 173 @Override public void shutdown() { 174 throw new UnsupportedOperationException(); 175 } 176 }; 177 registry.register( 178 new BaseProvider(true, 4, "other") { 179 @Override 180 public NameResolver newNameResolver(URI passedUri, NameResolver.Args passedArgs) { 181 return nr; 182 } 183 }); 184 185 assertThat(registry.asFactory().newNameResolver(uri, args)).isNull(); 186 assertThat(registry.asFactory().newNameResolver(URI.create("/0.0.0.0:80"), args)).isNull(); 187 assertThat(registry.asFactory().newNameResolver(URI.create("///0.0.0.0:80"), args)).isNull(); 188 assertThat(registry.asFactory().newNameResolver(URI.create("other:///0.0.0.0:80"), args)) 189 .isSameInstanceAs(nr); 190 assertThat(registry.asFactory().newNameResolver(URI.create("OTHER:///0.0.0.0:80"), args)) 191 .isSameInstanceAs(nr); 192 assertThat(registry.asFactory().getDefaultScheme()).isEqualTo("dns"); 193 } 194 195 @Test newNameResolver_noProvider()196 public void newNameResolver_noProvider() { 197 NameResolver.Factory factory = new NameResolverRegistry().asFactory(); 198 assertThat(factory.newNameResolver(uri, args)).isNull(); 199 assertThat(factory.getDefaultScheme()).isEqualTo("unknown"); 200 } 201 202 @Test baseProviders()203 public void baseProviders() { 204 Map<String, NameResolverProvider> providers = 205 NameResolverRegistry.getDefaultRegistry().providers(); 206 assertThat(providers).hasSize(1); 207 // 2 name resolvers from grpclb and core, higher priority one is returned. 208 assertThat(providers.get("dns").getClass().getName()) 209 .isEqualTo("io.grpc.grpclb.SecretGrpclbNameResolverProvider$Provider"); 210 assertThat(NameResolverRegistry.getDefaultRegistry().asFactory().getDefaultScheme()) 211 .isEqualTo("dns"); 212 } 213 214 @Test getClassesViaHardcoded_classesPresent()215 public void getClassesViaHardcoded_classesPresent() throws Exception { 216 List<Class<?>> classes = NameResolverRegistry.getHardCodedClasses(); 217 assertThat(classes).containsExactly(io.grpc.internal.DnsNameResolverProvider.class); 218 } 219 220 @Test provided()221 public void provided() { 222 for (NameResolverProvider current 223 : InternalServiceProviders.getCandidatesViaServiceLoader( 224 NameResolverProvider.class, getClass().getClassLoader())) { 225 if (current instanceof DnsNameResolverProvider) { 226 return; 227 } 228 } 229 fail("DnsNameResolverProvider not registered"); 230 } 231 232 private static class BaseProvider extends NameResolverProvider { 233 private final boolean isAvailable; 234 private final int priority; 235 private final String scheme; 236 BaseProvider(boolean isAvailable, int priority)237 public BaseProvider(boolean isAvailable, int priority) { 238 this.isAvailable = isAvailable; 239 this.priority = priority; 240 this.scheme = null; 241 } 242 BaseProvider(boolean isAvailable, int priority, String scheme)243 public BaseProvider(boolean isAvailable, int priority, String scheme) { 244 this.isAvailable = isAvailable; 245 this.priority = priority; 246 this.scheme = scheme; 247 } 248 249 @Override isAvailable()250 protected boolean isAvailable() { 251 return isAvailable; 252 } 253 254 @Override priority()255 protected int priority() { 256 return priority; 257 } 258 259 @Override newNameResolver(URI targetUri, NameResolver.Args args)260 public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) { 261 throw new UnsupportedOperationException(); 262 } 263 264 @Override getDefaultScheme()265 public String getDefaultScheme() { 266 return scheme == null ? "scheme" + getClass().getSimpleName() : scheme; 267 } 268 } 269 } 270