Home | History | Annotate | Download | only in mockitoutil
      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)
     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
     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
     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
     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
     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
    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
    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)
    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
    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
    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
    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
    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
    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
    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
    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
    257     public void return_current_classloader() throws Exception {
    258         assertThat(currentClassLoader()).isEqualTo(this.getClass().getClassLoader());
    259     }
    260 
    261     @Test
    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
    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