11e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson/* 21e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * Copyright (C) 2010 The Android Open Source Project 31e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * 41e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 51e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * you may not use this file except in compliance with the License. 61e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * You may obtain a copy of the License at 71e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * 81e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 91e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * 101e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * Unless required by applicable law or agreed to in writing, software 111e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 121e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * See the License for the specific language governing permissions and 141e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * limitations under the License. 151e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson */ 161e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 171e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonpackage libcore.java.lang.reflect; 181e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 19f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.lang.reflect.Constructor; 20f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.lang.reflect.Field; 21f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.lang.reflect.Method; 221e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.lang.reflect.ParameterizedType; 231e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.lang.reflect.Type; 24f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.lang.reflect.TypeVariable; 251e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.util.ArrayList; 261e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.util.Arrays; 271e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport java.util.List; 28f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilsonimport java.util.concurrent.Callable; 291e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonimport junit.framework.TestCase; 30649e3c0004d965fe388ad454eeb20e307a12edd2Jesse Wilsonimport tests.util.ClassLoaderBuilder; 311e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 32f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson/** 33f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * This class creates another class loader to load multiple copies of various 34f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * classes into the VM at once. Then it verifies that reflection resolves the 35f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * class names using the correct class loader. 36f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson */ 371e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilsonpublic final class ClassLoaderReflectionTest extends TestCase { 381e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 39f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson /* 40f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * Each of these class instances points to a different copy of the class 41f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson * than the one in the application class loader! 42f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson */ 43f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> aClass; 44f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> aListClass; 45f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> bClass; 46f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> bStringClass; 47f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> cClass; 48f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> dClass; 49f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> eClass; 50f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private Class<?> fClass; 51f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 52f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson @Override protected void setUp() throws Exception { 53f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson String prefix = ClassLoaderReflectionTest.class.getName(); 54649e3c0004d965fe388ad454eeb20e307a12edd2Jesse Wilson ClassLoader loader = new ClassLoaderBuilder().withPrivateCopy(prefix).build(); 55f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson aClass = loader.loadClass(prefix + "$A"); 56f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson bClass = loader.loadClass(prefix + "$B"); 57f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson cClass = loader.loadClass(prefix + "$C"); 58f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson dClass = loader.loadClass(prefix + "$D"); 59f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson eClass = loader.loadClass(prefix + "$E"); 60f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson fClass = loader.loadClass(prefix + "$F"); 61f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson aListClass = loader.loadClass(prefix + "$AList"); 62f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson bStringClass = loader.loadClass(prefix + "$BString"); 63f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 641e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 651e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson public void testLoadOneClassInTwoClassLoadersSimultaneously() throws Exception { 661e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson assertEquals(aClass.getName(), A.class.getName()); 671e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson assertNotSame(aClass, A.class); 681e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 691e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 70f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testField() throws Exception { 711e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson assertEquals(aClass, aListClass.getDeclaredField("field").getType()); 721e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 731e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 741e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson /** 751e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson * http://code.google.com/p/android/issues/detail?id=10111 761e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson */ 77f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testGenericSuperclassParameter() throws Exception { 78f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(aListClass.getGenericSuperclass(), ArrayList.class, aClass); 791e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 801e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 81f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testGenericSuperclassRawType() throws Exception { 82f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(bStringClass.getGenericSuperclass(), bClass, String.class); 83f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 84f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 85f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testTypeParameters() throws Exception { 86f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson TypeVariable<? extends Class<?>>[] typeVariables = cClass.getTypeParameters(); 87f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(2, typeVariables.length); 88f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertTypeVariable(typeVariables[0], "K", String.class); 89f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertTypeVariable(typeVariables[1], "V", aClass); 90f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 91f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 92f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testGenericInterfaces() throws Exception { 93f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Type[] types = eClass.getGenericInterfaces(); 94f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(2, types.length); 95f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson // TODO: this test incorrectly assumes that interfaces will be returned in source order! 96f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(types[0], Callable.class, aClass); 97f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(types[1], dClass, aClass); 98f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 99f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 100f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testFieldGenericType() throws Exception { 101f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Field bString = fClass.getDeclaredField("bString"); 102f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(bString.getGenericType(), bClass, String.class); 103f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Field listA = fClass.getDeclaredField("listA"); 104f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(listA.getGenericType(), List.class, aClass); 105f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 106f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 107f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testConstructorGenericType() throws Exception { 108f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Constructor<?> constructor = fClass.getDeclaredConstructors()[0]; 109f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Type[] parameters = constructor.getGenericParameterTypes(); 110f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(parameters[0], bClass, String.class); 111f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(parameters[1], List.class, aClass); 112f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 113f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 114f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testMethodGenericReturnType() throws Exception { 115f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Method method = fClass.getDeclaredMethod("method", bClass, List.class); 116f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(method.getGenericReturnType(), bClass, String.class); 117f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 118f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 119f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public void testMethodGenericParameterTypes() throws Exception { 120f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Method method = fClass.getDeclaredMethod("method", bClass, List.class); 121f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Type[] types = method.getGenericParameterTypes(); 122f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(2, types.length); 123f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(types[0], bClass, String.class); 124f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertParameterizedType(types[1], List.class, aClass); 1251e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 1261e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 1271e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson static class A {} 128f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson static class B<T> { 129f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson T field; 130f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 131f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson static class C<K extends String, V extends A> {} 132f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson interface D<T> {} 133f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson class E implements Callable<A>, D<A> { 134f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson public A call() throws Exception { 135f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson return null; 136f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 137f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 138f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson class F { 139f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson B<String> bString; 140f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson List<A> listA; 141f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson F(B<String> parameter, List<A> anotherParameter) {} 142f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson B<String> method(B<String> parameter, List<A> anotherParameter) { 143f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson return null; 144f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 145f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 1461e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson static class AList extends ArrayList<A> { 1471e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson A field; 1481e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson } 149f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson static class BString extends B<String> {} 1501e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson 151f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private void assertParameterizedType(Type actual, Type raw, Type... args) { 152f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertTrue(actual.toString(), actual instanceof ParameterizedType); 153f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson ParameterizedType parameterizedType = (ParameterizedType) actual; 154f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(raw, parameterizedType.getRawType()); 155f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(Arrays.<Type>asList(args), 156f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson Arrays.asList(parameterizedType.getActualTypeArguments())); 157f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 158f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson 159f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson private void assertTypeVariable(TypeVariable actual, String name, Type... bounds) { 160f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(name, actual.getName()); 161f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson assertEquals(Arrays.<Type>asList(bounds), Arrays.asList(actual.getBounds())); 162f3507d0976cb14ba59e0715f22f4c6b7c97cbae8Jesse Wilson } 1631e9105e7b50d142b0560d98222132a0898e700d5Jesse Wilson} 164