• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017 Mockito contributors
3  * This program is made available under the terms of the MIT License.
4  */
5 package org.mockitoutil;
6 
7 import static org.assertj.core.api.Assertions.assertThat;
8 import static org.assertj.core.api.Assertions.assertThatThrownBy;
9 import static org.junit.Assert.fail;
10 import static org.mockitoutil.ClassLoaders.currentClassLoader;
11 import static org.mockitoutil.ClassLoaders.excludingClassLoader;
12 import static org.mockitoutil.ClassLoaders.isolatedClassLoader;
13 import static org.mockitoutil.ClassLoaders.jdkClassLoader;
14 
15 import java.util.concurrent.atomic.AtomicBoolean;
16 
17 import org.assertj.core.api.Assertions;
18 import org.junit.Test;
19 import org.mockito.Mockito;
20 
21 public class ClassLoadersTest {
22 
23     public static final String CLASS_NAME_DEPENDING_ON_INTERFACE =
24             "org.mockitoutil.ClassLoadersTest$ClassUsingInterface1";
25     public static final String INTERFACE_NAME = "org.mockitoutil.ClassLoadersTest$Interface1";
26 
27     @Test
isolated_class_loader_cannot_load_classes_when_no_given_prefix()28     public void isolated_class_loader_cannot_load_classes_when_no_given_prefix() {
29         // given
30         ClassLoader cl = isolatedClassLoader().build();
31 
32         // when / then
33         assertThatThrownBy(
34                         () -> {
35                             cl.loadClass("org.mockito.Mockito");
36                         })
37                 .isInstanceOf(ClassNotFoundException.class)
38                 .hasMessage("Can only load classes with prefixes : [], but not : []");
39     }
40 
41     @Test
isolated_class_loader_cannot_load_classes_if_no_code_source_path()42     public void isolated_class_loader_cannot_load_classes_if_no_code_source_path() {
43         // given
44         ClassLoader cl =
45                 isolatedClassLoader().withPrivateCopyOf(CLASS_NAME_DEPENDING_ON_INTERFACE).build();
46 
47         // when
48         try {
49             cl.loadClass(CLASS_NAME_DEPENDING_ON_INTERFACE);
50             fail();
51         } catch (ClassNotFoundException e) {
52             // then
53             assertThat(e).hasMessageContaining(CLASS_NAME_DEPENDING_ON_INTERFACE);
54         }
55     }
56 
57     @Test
58     public void
isolated_class_loader_cannot_load_classes_if_dependent_classes_do_not_match_the_prefixes()59             isolated_class_loader_cannot_load_classes_if_dependent_classes_do_not_match_the_prefixes()
60                     throws Exception {
61         // given
62         ClassLoader cl =
63                 isolatedClassLoader()
64                         .withCurrentCodeSourceUrls()
65                         .withPrivateCopyOf(CLASS_NAME_DEPENDING_ON_INTERFACE)
66                         .build();
67 
68         // when
69         try {
70             cl.loadClass(CLASS_NAME_DEPENDING_ON_INTERFACE);
71             fail();
72         } catch (NoClassDefFoundError e) {
73             // then
74             assertThat(e).hasMessageContaining("org/mockitoutil/ClassLoadersTest$Interface1");
75         }
76     }
77 
78     @Test
79     public void
isolated_class_loader_can_load_classes_when_dependent_classes_are_matching_the_prefixes()80             isolated_class_loader_can_load_classes_when_dependent_classes_are_matching_the_prefixes()
81                     throws Exception {
82         // given
83         ClassLoader cl =
84                 isolatedClassLoader()
85                         .withCurrentCodeSourceUrls()
86                         .withPrivateCopyOf(CLASS_NAME_DEPENDING_ON_INTERFACE)
87                         .withPrivateCopyOf(INTERFACE_NAME)
88                         .build();
89 
90         // when
91         Class<?> aClass = cl.loadClass(CLASS_NAME_DEPENDING_ON_INTERFACE);
92 
93         // then
94         assertThat(aClass).isNotNull();
95         assertThat(aClass.getClassLoader()).isEqualTo(cl);
96         assertThat(aClass.getInterfaces()[0].getClassLoader()).isEqualTo(cl);
97     }
98 
99     @Test
isolated_class_loader_can_load_classes_isolated_classes_in_isolation()100     public void isolated_class_loader_can_load_classes_isolated_classes_in_isolation()
101             throws Exception {
102         // given
103         ClassLoader cl =
104                 isolatedClassLoader()
105                         .withCurrentCodeSourceUrls()
106                         .withPrivateCopyOf(ClassLoadersTest.class.getPackage().getName())
107                         .build();
108 
109         // when
110         Class<?> aClass = cl.loadClass(AClass.class.getName());
111 
112         // then
113         assertThat(aClass).isNotNull();
114         assertThat(aClass).isNotSameAs(AClass.class);
115         assertThat(aClass.getClassLoader()).isEqualTo(cl);
116     }
117 
118     @Test
isolated_class_loader_cannot_load_classes_if_prefix_excluded()119     public void isolated_class_loader_cannot_load_classes_if_prefix_excluded() {
120         // given
121         ClassLoader cl =
122                 isolatedClassLoader()
123                         .withCurrentCodeSourceUrls()
124                         .withPrivateCopyOf(ClassLoadersTest.class.getPackage().getName())
125                         .without(AClass.class.getName())
126                         .build();
127 
128         // when
129         try {
130             cl.loadClass(AClass.class.getName());
131             fail();
132         } catch (ClassNotFoundException e) {
133             // then
134             assertThat(e)
135                     .hasMessageContaining("org.mockitoutil")
136                     .hasMessageContaining(AClass.class.getName());
137         }
138     }
139 
140     @Test
isolated_class_loader_has_no_parent()141     public void isolated_class_loader_has_no_parent() {
142         ClassLoader cl =
143                 isolatedClassLoader()
144                         .withCurrentCodeSourceUrls()
145                         .withPrivateCopyOf(CLASS_NAME_DEPENDING_ON_INTERFACE)
146                         .withPrivateCopyOf(INTERFACE_NAME)
147                         .build();
148 
149         assertThat(cl.getParent()).isNull();
150     }
151 
152     @Test
excluding_class_loader_cannot_load_classes_when_no_correct_source_url_set()153     public void excluding_class_loader_cannot_load_classes_when_no_correct_source_url_set() {
154         // given
155         ClassLoader cl = excludingClassLoader().withCodeSourceUrlOf(this.getClass()).build();
156 
157         // when / then
158         assertThatThrownBy(
159                         () -> {
160                             cl.loadClass("org.mockito.Mockito");
161                         })
162                 .isInstanceOf(ClassNotFoundException.class)
163                 .hasMessage("org.mockito.Mockito");
164     }
165 
166     @Test
excluding_class_loader_can_load_classes_when_correct_source_url_set()167     public void excluding_class_loader_can_load_classes_when_correct_source_url_set()
168             throws Exception {
169         // given
170         ClassLoader cl = excludingClassLoader().withCodeSourceUrlOf(Mockito.class).build();
171 
172         // when
173         cl.loadClass("org.mockito.Mockito");
174 
175         // then class successfully loaded
176     }
177 
178     @Test
excluding_class_loader_cannot_load_class_when_excluded_prefix_match_class_to_load()179     public void excluding_class_loader_cannot_load_class_when_excluded_prefix_match_class_to_load()
180             throws Exception {
181         // given
182         ClassLoader cl =
183                 excludingClassLoader()
184                         .withCodeSourceUrlOf(Mockito.class)
185                         .without("org.mockito.BDDMockito")
186                         .build();
187 
188         cl.loadClass("org.mockito.Mockito");
189 
190         // when
191         try {
192             cl.loadClass("org.mockito.BDDMockito");
193             fail("should have raise a ClassNotFoundException");
194         } catch (ClassNotFoundException e) {
195             assertThat(e.getMessage()).contains("org.mockito.BDDMockito");
196         }
197 
198         // then class successfully loaded
199     }
200 
201     @Test
can_not_load_a_class_not_previously_registered_in_builder()202     public void can_not_load_a_class_not_previously_registered_in_builder() {
203         // given
204         ClassLoader cl =
205                 ClassLoaders.inMemoryClassLoader()
206                         .withClassDefinition(
207                                 "yop.Dude", SimpleClassGenerator.makeMarkerInterface("yop.Dude"))
208                         .build();
209 
210         // when
211         try {
212             cl.loadClass("not.Defined");
213             fail();
214         } catch (ClassNotFoundException e) {
215             // then
216             assertThat(e.getMessage()).contains("not.Defined");
217         }
218     }
219 
220     @Test
can_load_a_class_in_memory_from_bytes()221     public void can_load_a_class_in_memory_from_bytes() throws Exception {
222         // given
223         ClassLoader cl =
224                 ClassLoaders.inMemoryClassLoader()
225                         .withClassDefinition(
226                                 "yop.Dude", SimpleClassGenerator.makeMarkerInterface("yop.Dude"))
227                         .build();
228 
229         // when
230         Class<?> aClass = cl.loadClass("yop.Dude");
231 
232         // then
233         assertThat(aClass).isNotNull();
234         assertThat(aClass.getClassLoader()).isEqualTo(cl);
235         assertThat(aClass.getName()).isEqualTo("yop.Dude");
236     }
237 
238     @Test
cannot_load_a_class_file_not_in_parent()239     public void cannot_load_a_class_file_not_in_parent() throws Exception {
240         // given
241         ClassLoader cl = ClassLoaders.inMemoryClassLoader().withParent(jdkClassLoader()).build();
242 
243         cl.loadClass("java.lang.String");
244 
245         try {
246             // when
247             cl.loadClass("org.mockito.Mockito");
248             fail("should have not found Mockito class");
249         } catch (ClassNotFoundException e) {
250             // then
251             assertThat(e.getMessage()).contains("org.mockito.Mockito");
252         }
253     }
254 
255     @Test
can_list_all_classes_reachable_in_a_classloader()256     public void can_list_all_classes_reachable_in_a_classloader() throws Exception {
257         ClassLoader classLoader =
258                 ClassLoaders.inMemoryClassLoader()
259                         .withParent(jdkClassLoader())
260                         .withClassDefinition("a.A", SimpleClassGenerator.makeMarkerInterface("a.A"))
261                         .withClassDefinition(
262                                 "a.b.B", SimpleClassGenerator.makeMarkerInterface("a.b.B"))
263                         .withClassDefinition("c.C", SimpleClassGenerator.makeMarkerInterface("c.C"))
264                         //                .withCodeSourceUrlOf(ClassLoaders.class)
265                         .build();
266 
267         assertThat(ClassLoaders.in(classLoader).listOwnedClasses())
268                 .containsOnly("a.A", "a.b.B", "c.C");
269         assertThat(ClassLoaders.in(classLoader).omit("b", "c").listOwnedClasses())
270                 .containsOnly("a.A");
271     }
272 
273     @Test
return_bootstrap_classloader()274     public void return_bootstrap_classloader() {
275         assertThat(jdkClassLoader()).isNotEqualTo(Mockito.class.getClassLoader());
276         assertThat(jdkClassLoader()).isNotEqualTo(ClassLoaders.class.getClassLoader());
277         assertThat(jdkClassLoader()).isEqualTo(Number.class.getClassLoader());
278         assertThat(jdkClassLoader()).isEqualTo(null);
279     }
280 
281     @Test
return_current_classloader()282     public void return_current_classloader() {
283         assertThat(currentClassLoader()).isEqualTo(this.getClass().getClassLoader());
284     }
285 
286     @Test
can_run_in_given_classloader()287     public void can_run_in_given_classloader() throws Exception {
288         // given
289         final ClassLoader cl =
290                 isolatedClassLoader()
291                         .withCurrentCodeSourceUrls()
292                         .withCodeSourceUrlOf(Assertions.class)
293                         .withPrivateCopyOf("org.assertj.core")
294                         .withPrivateCopyOf(ClassLoadersTest.class.getPackage().getName())
295                         .without(AClass.class.getName())
296                         .build();
297 
298         final AtomicBoolean executed = new AtomicBoolean(false);
299 
300         // when
301         ClassLoaders.using(cl)
302                 .execute(
303                         new Runnable() {
304                             @Override
305                             public void run() {
306                                 assertThat(this.getClass().getClassLoader())
307                                         .describedAs("runnable is reloaded in given classloader")
308                                         .isEqualTo(cl);
309                                 assertThat(Thread.currentThread().getContextClassLoader())
310                                         .describedAs(
311                                                 "Thread context classloader is using given classloader")
312                                         .isEqualTo(cl);
313 
314                                 try {
315                                     assertThat(
316                                                     Thread.currentThread()
317                                                             .getContextClassLoader()
318                                                             .loadClass("java.lang.String"))
319                                             .describedAs("can load JDK type")
320                                             .isNotNull();
321                                     assertThat(
322                                                     Thread.currentThread()
323                                                             .getContextClassLoader()
324                                                             .loadClass(
325                                                                     "org.mockitoutil.ClassLoadersTest$ClassUsingInterface1"))
326                                             .describedAs("can load classloader types")
327                                             .isNotNull();
328                                 } catch (ClassNotFoundException cnfe) {
329                                     Assertions.fail("should not have raised a CNFE", cnfe);
330                                 }
331                                 executed.set(true);
332                             }
333                         });
334 
335         // then
336         assertThat(executed.get()).isEqualTo(true);
337     }
338 
339     @Test
cannot_load_runnable_in_given_classloader_if_some_type_cant_be_loaded()340     public void cannot_load_runnable_in_given_classloader_if_some_type_cant_be_loaded()
341             throws Exception {
342         // given
343         final ClassLoader cl =
344                 isolatedClassLoader()
345                         .withCurrentCodeSourceUrls()
346                         .withPrivateCopyOf(ClassLoadersTest.class.getPackage().getName())
347                         .without(AClass.class.getName())
348                         .build();
349 
350         // when
351         try {
352             ClassLoaders.using(cl)
353                     .execute(
354                             new Runnable() {
355                                 @Override
356                                 public void run() {
357                                     AClass cant_be_found = new AClass();
358                                 }
359                             });
360             Assertions.fail("should have raised a ClassNotFoundException");
361         } catch (IllegalStateException ise) {
362             // then
363             assertThat(ise)
364                     .hasCauseInstanceOf(NoClassDefFoundError.class)
365                     .hasMessageContaining("AClass");
366         }
367     }
368 
369     @SuppressWarnings("unused")
370     static class AClass {}
371 
372     @SuppressWarnings("unused")
373     static class ClassUsingInterface1 implements Interface1 {}
374 
375     @SuppressWarnings("unused")
376     interface Interface1 {}
377 }
378