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