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