blob: 19032c8642fc13d2786a43f56c7a961dc208b5ef [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package art;
import java.util.*;
import java.util.function.*;
import java.lang.reflect.*;
import java.nio.ByteBuffer;
import dalvik.system.InMemoryDexClassLoader;
public class Test1946 {
// Base64 encoded dex file containing the following classes. Note the class E cannot be loaded.
// public class A {}
// public class B {}
// public class C {}
// public class D {}
// public class E extends ClassNotThere {}
private static final byte[] TEST_CLASSES = Base64.getDecoder().decode(
"ZGV4CjAzNQDzTO8rVDlKlz80vQF4NLYV5MjMMjHlOtRoAwAAcAAAAHhWNBIAAAAAAAAAAOACAAAO" +
"AAAAcAAAAAgAAACoAAAAAQAAAMgAAAAAAAAAAAAAAAcAAADUAAAABQAAAAwBAAC8AQAArAEAACQC" +
"AAAsAgAANAIAADwCAABEAgAATAIAAFQCAABZAgAAXgIAAGMCAAB0AgAAeQIAAH4CAACSAgAABgAA" +
"AAcAAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAANAAAABwAAAAAAAAAAAAAAAAAAAAEAAAAAAAAA" +
"AgAAAAAAAAADAAAAAAAAAAQAAAAAAAAABQAAAAAAAAAGAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAB" +
"AAAAAAAAAK4CAAAAAAAAAQAAAAAAAAAGAAAAAAAAAAIAAAAAAAAAuAIAAAAAAAACAAAAAAAAAAYA" +
"AAAAAAAAAwAAAAAAAADCAgAAAAAAAAQAAAAAAAAABgAAAAAAAAAEAAAAAAAAAMwCAAAAAAAABQAA" +
"AAAAAAADAAAAAAAAAAUAAAAAAAAA1gIAAAAAAAABAAEAAQAAAJUCAAAEAAAAcBAGAAAADgABAAEA" +
"AQAAAJoCAAAEAAAAcBAGAAAADgABAAEAAQAAAJ8CAAAEAAAAcBAGAAAADgABAAEAAQAAAKQCAAAE" +
"AAAAcBAGAAAADgABAAEAAQAAAKkCAAAEAAAAcBADAAAADgAGPGluaXQ+AAZBLmphdmEABkIuamF2" +
"YQAGQy5qYXZhAAZELmphdmEABkUuamF2YQADTEE7AANMQjsAA0xDOwAPTENsYXNzTm90VGhlcmU7" +
"AANMRDsAA0xFOwASTGphdmEvbGFuZy9PYmplY3Q7AAFWAAEABw4AAQAHDgABAAcOAAEABw4AAQAH" +
"DgAAAAEAAICABKwDAAABAAGAgATEAwAAAQACgIAE3AMAAAEABICABPQDAAABAAWAgASMBAsAAAAA" +
"AAAAAQAAAAAAAAABAAAADgAAAHAAAAACAAAACAAAAKgAAAADAAAAAQAAAMgAAAAFAAAABwAAANQA" +
"AAAGAAAABQAAAAwBAAABIAAABQAAAKwBAAACIAAADgAAACQCAAADIAAABQAAAJUCAAAAIAAABQAA" +
"AK4CAAAAEAAAAQAAAOACAAA=");
public class TMP1 {}
public class TMP2 {}
public class TMP3 extends ArrayList {}
private static void check(boolean b, Supplier<String> msg) {
if (!b) {
throw new Error("Test failed! " + msg.get());
}
}
private static <T> void checkEq(T[] full, T[] sub, final String msg) {
List<T> f = Arrays.asList(full);
check(full.length == sub.length, () -> "not equal length");
Supplier<String> msgGen =
() -> Arrays.toString(full) + " is not same as " + Arrays.toString(sub) + ": " + msg;
check(new HashSet<T>(Arrays.asList(full)).containsAll(Arrays.asList(sub)), msgGen);
}
private static <T> void checkSubset(T[] full, T[] sub, final String msg) {
Supplier<String> msgGen =
() -> Arrays.toString(full) + " does not contain all of " + Arrays.toString(sub) + ": " + msg;
check(new HashSet<T>(Arrays.asList(full)).containsAll(Arrays.asList(sub)), msgGen);
}
public static void run() throws Exception {
initializeTest();
// Check a few random classes in BCP.
checkSubset(getClassloaderDescriptors(null),
new String[] { "Ljava/lang/String;", "Ljava/util/TreeSet;" },
"Missing entries for null classloader.");
// Make sure that null is the same as BootClassLoader
checkEq(getClassloaderDescriptors(null),
getClassloaderDescriptors(Object.class.getClassLoader()), "Object not in bcp!");
// Check the current class loader gets expected classes.
checkSubset(getClassloaderDescriptors(Test1946.class.getClassLoader()),
new String[] {
"Lart/Test1946;",
"Lart/Test1946$TMP1;",
"Lart/Test1946$TMP2;",
"Lart/Test1946$TMP3;"
},
"Missing entries for current class classloader.");
// Check that the result is exactly what we expect and includes classes that fail verification.
checkEq(getClassloaderDescriptors(makeClassLoaderFrom(TEST_CLASSES,
ClassLoader.getSystemClassLoader())),
new String[] { "LA;", "LB;", "LC;", "LD;", "LE;" },
"Unexpected classes in custom classloader");
checkEq(getClassloaderDescriptors(makeClassLoaderFrom(TEST_CLASSES,
Object.class.getClassLoader())),
new String[] { "LA;", "LB;", "LC;", "LD;", "LE;" },
"Unexpected classes in custom classloader");
checkEq(getClassloaderDescriptors(makeClassLoaderFrom(TEST_CLASSES,
Test1946.class.getClassLoader())),
new String[] { "LA;", "LB;", "LC;", "LD;", "LE;" },
"Unexpected classes in custom classloader");
// Check we only get 1 copy of each descriptor.
checkEq(getClassloaderDescriptors(makeClassLoaderFrom(Arrays.asList(TEST_CLASSES, TEST_CLASSES),
Test1946.class.getClassLoader())),
new String[] { "LA;", "LB;", "LC;", "LD;", "LE;" },
"Unexpected classes in custom classloader");
System.out.println("Passed!");
}
private static ClassLoader makeClassLoaderFrom(byte[] data, ClassLoader parent) throws Exception {
return new InMemoryDexClassLoader(ByteBuffer.wrap(data), parent);
}
private static ClassLoader makeClassLoaderFrom(List<byte[]> data, ClassLoader parent)
throws Exception {
ArrayList<ByteBuffer> bufs = new ArrayList<>();
for (byte[] d : data) {
bufs.add(ByteBuffer.wrap(d));
}
return new InMemoryDexClassLoader(bufs.toArray(new ByteBuffer[0]), parent);
}
private static native void initializeTest();
private static native String[] getClassloaderDescriptors(ClassLoader loader);
}