• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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