2525import static org .mockito .Mockito .mock ;
2626
2727import io .grpc .internal .DnsNameResolverProvider ;
28+ import java .io .IOException ;
29+ import java .lang .reflect .InvocationTargetException ;
30+ import java .lang .reflect .Method ;
2831import java .net .URI ;
32+ import java .net .URL ;
2933import java .util .Collections ;
34+ import java .util .Enumeration ;
3035import java .util .List ;
36+ import java .util .NoSuchElementException ;
3137import java .util .ServiceConfigurationError ;
38+ import java .util .regex .Pattern ;
3239import org .junit .Test ;
3340import org .junit .runner .RunWith ;
3441import org .junit .runners .JUnit4 ;
@@ -120,30 +127,47 @@ public void baseProviders() {
120127 }
121128
122129 @ Test
123- public void getCandidatesViaHardCoded_usesProvidedClassLoader () {
130+ public void getCandidatesViaHardCoded_triesToLoadClasses () throws Exception {
131+ ClassLoader cl = getClass ().getClassLoader ();
124132 final RuntimeException toThrow = new RuntimeException ();
125- try {
126- NameResolverProvider .getCandidatesViaHardCoded (new ClassLoader () {
127- @ Override
128- public Class <?> loadClass (String name ) {
133+ // Prevent DnsNameResolverProvider from being known
134+ cl = new FilteringClassLoader (cl , serviceFile );
135+ cl = new ClassLoader (cl ) {
136+ @ Override
137+ public Class <?> loadClass (String name , boolean resolve ) throws ClassNotFoundException {
138+ if (name .startsWith ("io.grpc.internal." )) {
129139 throw toThrow ;
140+ } else {
141+ return super .loadClass (name , resolve );
130142 }
131- });
143+ }
144+ };
145+ cl = new StaticTestingClassLoader (cl , Pattern .compile ("io\\ .grpc\\ .[^.]*" ));
146+ try {
147+ invokeGetCandidatesViaHardCoded (cl );
132148 fail ("Expected exception" );
133149 } catch (RuntimeException ex ) {
134150 assertSame (toThrow , ex );
135151 }
136152 }
137153
138154 @ Test
139- public void getCandidatesViaHardCoded_ignoresMissingClasses () {
140- Iterable <NameResolverProvider > i =
141- NameResolverProvider .getCandidatesViaHardCoded (new ClassLoader () {
142- @ Override
143- public Class <?> loadClass (String name ) throws ClassNotFoundException {
144- throw new ClassNotFoundException ();
145- }
146- });
155+ public void getCandidatesViaHardCoded_ignoresMissingClasses () throws Exception {
156+ ClassLoader cl = getClass ().getClassLoader ();
157+ // Prevent DnsNameResolverProvider from being known
158+ cl = new FilteringClassLoader (cl , serviceFile );
159+ cl = new ClassLoader (cl ) {
160+ @ Override
161+ public Class <?> loadClass (String name , boolean resolve ) throws ClassNotFoundException {
162+ if (name .startsWith ("io.grpc.internal." )) {
163+ throw new ClassNotFoundException ();
164+ } else {
165+ return super .loadClass (name , resolve );
166+ }
167+ }
168+ };
169+ cl = new StaticTestingClassLoader (cl , Pattern .compile ("io\\ .grpc\\ .[^.]*" ));
170+ Iterable <?> i = invokeGetCandidatesViaHardCoded (cl );
147171 assertFalse ("Iterator should be empty" , i .iterator ().hasNext ());
148172 }
149173
@@ -160,6 +184,53 @@ class PrivateClass {}
160184 }
161185 }
162186
187+ private static Iterable <?> invokeGetCandidatesViaHardCoded (ClassLoader cl ) throws Exception {
188+ // An error before the invoke likely means there is a bug in the test
189+ Class <?> klass = Class .forName (NameResolverProvider .class .getName (), true , cl );
190+ Method getCandidatesViaHardCoded = klass .getMethod ("getCandidatesViaHardCoded" );
191+ try {
192+ return (Iterable <?>) getCandidatesViaHardCoded .invoke (null );
193+ } catch (InvocationTargetException ex ) {
194+ if (ex .getCause () instanceof Exception ) {
195+ throw (Exception ) ex .getCause ();
196+ }
197+ throw ex ;
198+ }
199+ }
200+
201+ private static class FilteringClassLoader extends ClassLoader {
202+ private final String resource ;
203+
204+ public FilteringClassLoader (ClassLoader parent , String resource ) {
205+ super (parent );
206+ this .resource = resource ;
207+ }
208+
209+ @ Override
210+ public URL getResource (String name ) {
211+ if (resource .equals (name )) {
212+ return null ;
213+ }
214+ return super .getResource (name );
215+ }
216+
217+ @ Override
218+ public Enumeration <URL > getResources (String name ) throws IOException {
219+ if (resource .equals (name )) {
220+ return new Enumeration <URL >() {
221+ @ Override public boolean hasMoreElements () {
222+ return false ;
223+ }
224+
225+ @ Override public URL nextElement () {
226+ throw new NoSuchElementException ();
227+ }
228+ };
229+ }
230+ return super .getResources (name );
231+ }
232+ }
233+
163234 private static class BaseProvider extends NameResolverProvider {
164235 private final boolean isAvailable ;
165236 private final int priority ;
0 commit comments