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