1/* 2 * Copyright (C) 2010 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 17package libcore.java.lang.reflect; 18 19import java.lang.reflect.Constructor; 20import java.lang.reflect.Field; 21import java.lang.reflect.Method; 22import java.lang.reflect.ParameterizedType; 23import java.lang.reflect.Type; 24import java.lang.reflect.TypeVariable; 25import java.util.ArrayList; 26import java.util.Arrays; 27import java.util.List; 28import java.util.concurrent.Callable; 29import junit.framework.TestCase; 30import tests.util.ClassLoaderBuilder; 31 32/** 33 * This class creates another class loader to load multiple copies of various 34 * classes into the VM at once. Then it verifies that reflection resolves the 35 * class names using the correct class loader. 36 */ 37public final class ClassLoaderReflectionTest extends TestCase { 38 39 /* 40 * Each of these class instances points to a different copy of the class 41 * than the one in the application class loader! 42 */ 43 private Class<?> aClass; 44 private Class<?> aListClass; 45 private Class<?> bClass; 46 private Class<?> bStringClass; 47 private Class<?> cClass; 48 private Class<?> dClass; 49 private Class<?> eClass; 50 private Class<?> fClass; 51 52 @Override protected void setUp() throws Exception { 53 String prefix = ClassLoaderReflectionTest.class.getName(); 54 ClassLoader loader = new ClassLoaderBuilder().withPrivateCopy(prefix).build(); 55 aClass = loader.loadClass(prefix + "$A"); 56 bClass = loader.loadClass(prefix + "$B"); 57 cClass = loader.loadClass(prefix + "$C"); 58 dClass = loader.loadClass(prefix + "$D"); 59 eClass = loader.loadClass(prefix + "$E"); 60 fClass = loader.loadClass(prefix + "$F"); 61 aListClass = loader.loadClass(prefix + "$AList"); 62 bStringClass = loader.loadClass(prefix + "$BString"); 63 } 64 65 public void testLoadOneClassInTwoClassLoadersSimultaneously() throws Exception { 66 assertEquals(aClass.getName(), A.class.getName()); 67 assertNotSame(aClass, A.class); 68 } 69 70 public void testField() throws Exception { 71 assertEquals(aClass, aListClass.getDeclaredField("field").getType()); 72 } 73 74 /** 75 * http://code.google.com/p/android/issues/detail?id=10111 76 */ 77 public void testGenericSuperclassParameter() throws Exception { 78 assertParameterizedType(aListClass.getGenericSuperclass(), ArrayList.class, aClass); 79 } 80 81 public void testGenericSuperclassRawType() throws Exception { 82 assertParameterizedType(bStringClass.getGenericSuperclass(), bClass, String.class); 83 } 84 85 public void testTypeParameters() throws Exception { 86 TypeVariable<? extends Class<?>>[] typeVariables = cClass.getTypeParameters(); 87 assertEquals(2, typeVariables.length); 88 assertTypeVariable(typeVariables[0], "K", String.class); 89 assertTypeVariable(typeVariables[1], "V", aClass); 90 } 91 92 public void testGenericInterfaces() throws Exception { 93 Type[] types = eClass.getGenericInterfaces(); 94 assertEquals(2, types.length); 95 // TODO: this test incorrectly assumes that interfaces will be returned in source order! 96 assertParameterizedType(types[0], Callable.class, aClass); 97 assertParameterizedType(types[1], dClass, aClass); 98 } 99 100 public void testFieldGenericType() throws Exception { 101 Field bString = fClass.getDeclaredField("bString"); 102 assertParameterizedType(bString.getGenericType(), bClass, String.class); 103 Field listA = fClass.getDeclaredField("listA"); 104 assertParameterizedType(listA.getGenericType(), List.class, aClass); 105 } 106 107 public void testConstructorGenericType() throws Exception { 108 Constructor<?> constructor = fClass.getDeclaredConstructors()[0]; 109 Type[] parameters = constructor.getGenericParameterTypes(); 110 assertParameterizedType(parameters[0], bClass, String.class); 111 assertParameterizedType(parameters[1], List.class, aClass); 112 } 113 114 public void testMethodGenericReturnType() throws Exception { 115 Method method = fClass.getDeclaredMethod("method", bClass, List.class); 116 assertParameterizedType(method.getGenericReturnType(), bClass, String.class); 117 } 118 119 public void testMethodGenericParameterTypes() throws Exception { 120 Method method = fClass.getDeclaredMethod("method", bClass, List.class); 121 Type[] types = method.getGenericParameterTypes(); 122 assertEquals(2, types.length); 123 assertParameterizedType(types[0], bClass, String.class); 124 assertParameterizedType(types[1], List.class, aClass); 125 } 126 127 static class A {} 128 static class B<T> { 129 T field; 130 } 131 static class C<K extends String, V extends A> {} 132 interface D<T> {} 133 class E implements Callable<A>, D<A> { 134 public A call() throws Exception { 135 return null; 136 } 137 } 138 class F { 139 B<String> bString; 140 List<A> listA; 141 F(B<String> parameter, List<A> anotherParameter) {} 142 B<String> method(B<String> parameter, List<A> anotherParameter) { 143 return null; 144 } 145 } 146 static class AList extends ArrayList<A> { 147 A field; 148 } 149 static class BString extends B<String> {} 150 151 private void assertParameterizedType(Type actual, Type raw, Type... args) { 152 assertTrue(actual.toString(), actual instanceof ParameterizedType); 153 ParameterizedType parameterizedType = (ParameterizedType) actual; 154 assertEquals(raw, parameterizedType.getRawType()); 155 assertEquals(Arrays.<Type>asList(args), 156 Arrays.asList(parameterizedType.getActualTypeArguments())); 157 } 158 159 private void assertTypeVariable(TypeVariable actual, String name, Type... bounds) { 160 assertEquals(name, actual.getName()); 161 assertEquals(Arrays.<Type>asList(bounds), Arrays.asList(actual.getBounds())); 162 } 163} 164