Home | History | Annotate | Download | only in art
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package art;
     18 
     19 import java.util.*;
     20 import java.lang.reflect.*;
     21 import java.nio.ByteBuffer;
     22 import dalvik.system.InMemoryDexClassLoader;
     23 
     24 public class Test1946 {
     25   // Base64 encoded dex file containing the following classes. Note the class E cannot be loaded.
     26   // public class A {}
     27   // public class B {}
     28   // public class C {}
     29   // public class D {}
     30   // public class E extends ClassNotThere {}
     31   private static final byte[] TEST_CLASSES = Base64.getDecoder().decode(
     32       "ZGV4CjAzNQDzTO8rVDlKlz80vQF4NLYV5MjMMjHlOtRoAwAAcAAAAHhWNBIAAAAAAAAAAOACAAAO" +
     33       "AAAAcAAAAAgAAACoAAAAAQAAAMgAAAAAAAAAAAAAAAcAAADUAAAABQAAAAwBAAC8AQAArAEAACQC" +
     34       "AAAsAgAANAIAADwCAABEAgAATAIAAFQCAABZAgAAXgIAAGMCAAB0AgAAeQIAAH4CAACSAgAABgAA" +
     35       "AAcAAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAANAAAABwAAAAAAAAAAAAAAAAAAAAEAAAAAAAAA" +
     36       "AgAAAAAAAAADAAAAAAAAAAQAAAAAAAAABQAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAB" +
     37       "AAAAAAAAAK4CAAAAAAAAAQAAAAAAAAAGAAAAAAAAAAIAAAAAAAAAuAIAAAAAAAACAAAAAAAAAAYA" +
     38       "AAAAAAAAAwAAAAAAAADCAgAAAAAAAAQAAAAAAAAABgAAAAAAAAAEAAAAAAAAAMwCAAAAAAAABQAA" +
     39       "AAAAAAADAAAAAAAAAAUAAAAAAAAA1gIAAAAAAAABAAEAAQAAAJUCAAAEAAAAcBAGAAAADgABAAEA" +
     40       "AQAAAJoCAAAEAAAAcBAGAAAADgABAAEAAQAAAJ8CAAAEAAAAcBAGAAAADgABAAEAAQAAAKQCAAAE" +
     41       "AAAAcBAGAAAADgABAAEAAQAAAKkCAAAEAAAAcBADAAAADgAGPGluaXQ+AAZBLmphdmEABkIuamF2" +
     42       "YQAGQy5qYXZhAAZELmphdmEABkUuamF2YQADTEE7AANMQjsAA0xDOwAPTENsYXNzTm90VGhlcmU7" +
     43       "AANMRDsAA0xFOwASTGphdmEvbGFuZy9PYmplY3Q7AAFWAAEABw4AAQAHDgABAAcOAAEABw4AAQAH" +
     44       "DgAAAAEAAICABKwDAAABAAGAgATEAwAAAQACgIAE3AMAAAEABICABPQDAAABAAWAgASMBAsAAAAA" +
     45       "AAAAAQAAAAAAAAABAAAADgAAAHAAAAACAAAACAAAAKgAAAADAAAAAQAAAMgAAAAFAAAABwAAANQA" +
     46       "AAAGAAAABQAAAAwBAAABIAAABQAAAKwBAAACIAAADgAAACQCAAADIAAABQAAAJUCAAAAIAAABQAA" +
     47       "AK4CAAAAEAAAAQAAAOACAAA=");
     48   public class TMP1 {}
     49   public class TMP2 {}
     50   public class TMP3 extends ArrayList {}
     51 
     52   private static void check(boolean b, String msg) {
     53     if (!b) {
     54       throw new Error("Test failed! " + msg);
     55     }
     56   }
     57 
     58   private static <T> void checkEq(T[] full, T[] sub, String msg) {
     59     List<T> f = Arrays.asList(full);
     60     check(full.length == sub.length, "not equal length");
     61     msg = Arrays.toString(full) + " is not same as " + Arrays.toString(sub) + ": " + msg;
     62     check(Arrays.asList(full).containsAll(Arrays.asList(sub)), msg);
     63   }
     64 
     65   private static <T> void checkSubset(T[] full, T[] sub, String msg) {
     66     msg = Arrays.toString(full) + " does not contain all of " + Arrays.toString(sub) + ": " + msg;
     67     check(Arrays.asList(full).containsAll(Arrays.asList(sub)), msg);
     68   }
     69 
     70   public static void run() throws Exception {
     71     initializeTest();
     72     // Check a few random classes in BCP.
     73     checkSubset(getClassloaderDescriptors(null),
     74         new String[] { "Ljava/lang/String;", "Ljava/util/TreeSet;" },
     75         "Missing entries for null classloader.");
     76     // Make sure that null is the same as BootClassLoader
     77     checkEq(getClassloaderDescriptors(null),
     78         getClassloaderDescriptors(Object.class.getClassLoader()), "Object not in bcp!");
     79     // Check the current class loader gets expected classes.
     80     checkSubset(getClassloaderDescriptors(Test1946.class.getClassLoader()),
     81         new String[] {
     82           "Lart/Test1946;",
     83           "Lart/Test1946$TMP1;",
     84           "Lart/Test1946$TMP2;",
     85           "Lart/Test1946$TMP3;"
     86         },
     87         "Missing entries for current class classloader.");
     88     // Check that the result is exactly what we expect and includes classes that fail verification.
     89     checkEq(getClassloaderDescriptors(makeClassLoaderFrom(TEST_CLASSES,
     90             ClassLoader.getSystemClassLoader())),
     91         new String[] { "LA;", "LB;", "LC;", "LD;", "LE;" },
     92         "Unexpected classes in custom classloader");
     93     checkEq(getClassloaderDescriptors(makeClassLoaderFrom(TEST_CLASSES,
     94             Object.class.getClassLoader())),
     95         new String[] { "LA;", "LB;", "LC;", "LD;", "LE;" },
     96         "Unexpected classes in custom classloader");
     97     checkEq(getClassloaderDescriptors(makeClassLoaderFrom(TEST_CLASSES,
     98             Test1946.class.getClassLoader())),
     99         new String[] { "LA;", "LB;", "LC;", "LD;", "LE;" },
    100         "Unexpected classes in custom classloader");
    101     // Check we only get 1 copy of each descriptor.
    102     checkEq(getClassloaderDescriptors(makeClassLoaderFrom(Arrays.asList(TEST_CLASSES, TEST_CLASSES),
    103             Test1946.class.getClassLoader())),
    104         new String[] { "LA;", "LB;", "LC;", "LD;", "LE;" },
    105         "Unexpected classes in custom classloader");
    106     System.out.println("Passed!");
    107   }
    108 
    109   private static ClassLoader makeClassLoaderFrom(byte[] data, ClassLoader parent) throws Exception {
    110     return new InMemoryDexClassLoader(ByteBuffer.wrap(data), parent);
    111   }
    112 
    113   private static ClassLoader makeClassLoaderFrom(List<byte[]> data, ClassLoader parent)
    114       throws Exception {
    115     ArrayList<ByteBuffer> bufs = new ArrayList<>();
    116     for (byte[] d : data) {
    117       bufs.add(ByteBuffer.wrap(d));
    118     }
    119     return new InMemoryDexClassLoader(bufs.toArray(new ByteBuffer[0]), parent);
    120   }
    121 
    122   private static native void initializeTest();
    123   private static native String[] getClassloaderDescriptors(ClassLoader loader);
    124 }
    125