1/* 2 * Copyright (C) 2008 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.Modifier; 23import java.util.ArrayList; 24import java.util.HashSet; 25import java.util.Set; 26import junit.framework.TestCase; 27 28public final class OldAndroidClassTest extends TestCase { 29 private static final String packageName = "libcore.java.lang.reflect"; 30 31 public void testNewInstance() throws Exception { 32 Class helloClass = Class.forName(OldAndroidClassTest.class.getName()); 33 Object instance = helloClass.newInstance(); 34 assertNotNull(instance); 35 } 36 37 public void testForName() throws Exception { 38 try { 39 Class.forName("this.class.DoesNotExist"); 40 fail(); 41 } catch (ClassNotFoundException expected) { 42 } 43 } 44 45 public void testNewInstancePrivateConstructor() throws Exception { 46 try { 47 Class.forName(packageName + ".ClassWithPrivateConstructor").newInstance(); 48 fail(); 49 } catch (IllegalAccessException expected) { 50 } 51 } 52 53 public void testGetDeclaredMethod() throws Exception { 54 Class helloClass = Class.forName(OldAndroidClassTest.class.getName()); 55 Method method = helloClass.getDeclaredMethod("method", (Class[]) null); 56 method.invoke(new OldAndroidClassTest(), (Object[]) null); 57 } 58 59 public void testGetDeclaredMethodWithArgs() throws Exception { 60 Class helloClass = Class.forName(OldAndroidClassTest.class.getName()); 61 Method method = helloClass.getDeclaredMethod("methodWithArgs", Object.class); 62 63 Object invokeArgs[] = new Object[1]; 64 invokeArgs[0] = "Hello"; 65 Object ret = method.invoke(new OldAndroidClassTest(), invokeArgs); 66 assertEquals(ret, invokeArgs[0]); 67 } 68 69 public void testGetDeclaredMethodPrivate() throws Exception { 70 Class helloClass = Class.forName(OldAndroidClassTest.class.getName()); 71 Method method = helloClass.getDeclaredMethod("privateMethod", (Class[]) null); 72 method.invoke(new OldAndroidClassTest(), (Object[]) null); 73 } 74 75 public void testGetSuperclass() throws Exception { 76 Class helloClass = Class.forName(OldAndroidClassTest.class.getName()); 77 Class objectClass = Class.forName("java.lang.Object"); 78 assertEquals(helloClass.getSuperclass().getSuperclass().getSuperclass(), objectClass); 79 } 80 81 public void testIsAssignableFrom() throws Exception { 82 Class helloClass = Class.forName(OldAndroidClassTest.class.getName()); 83 Class objectClass = Class.forName("java.lang.Object"); 84 assertTrue(objectClass.isAssignableFrom(helloClass)); 85 assertFalse(helloClass.isAssignableFrom(objectClass)); 86 } 87 88 public void testGetConstructor() throws Exception { 89 Class helloClass = Class.forName(OldAndroidClassTest.class.getName()); 90 Constructor constructor = helloClass.getConstructor((Class[]) null); 91 assertNotNull(constructor); 92 } 93 94 public void testGetModifiers() throws Exception { 95 Class helloClass = Class.forName(OldAndroidClassTest.class.getName()); 96 assertTrue(Modifier.isPublic(helloClass.getModifiers())); 97 } 98 99 public void testGetMethod() throws Exception { 100 Class helloClass = Class.forName(OldAndroidClassTest.class.getName()); 101 helloClass.getMethod("method", (Class[]) null); 102 try { 103 Class[] argTypes = new Class[1]; 104 argTypes[0] = helloClass; 105 helloClass.getMethod("method", argTypes); 106 fail(); 107 } catch (NoSuchMethodException expected) { 108 } 109 } 110 111 // http://code.google.com/p/android/issues/detail?id=14 112 public void testFieldSet() throws Exception { 113 OldAndroidClassTest.SimpleClass obj = new OldAndroidClassTest.SimpleClass(); 114 Field field = obj.getClass().getDeclaredField("str"); 115 field.set(obj, null); 116 } 117 118 public class SimpleClass { 119 public String str; 120 } 121 122 public Object methodWithArgs(Object o) { 123 return o; 124 } 125 126 boolean methodInvoked; 127 128 public void method() { 129 methodInvoked = true; 130 } 131 132 boolean privateMethodInvoked; 133 134 public void privateMethod() { 135 privateMethodInvoked = true; 136 } 137 138 // Regression for 1018067: Class.getMethods() returns the same method over 139 // and over again from all base classes 140 public void testClassGetMethodsNoDupes() { 141 Method[] methods = ArrayList.class.getMethods(); 142 Set<String> set = new HashSet<String>(); 143 144 for (Method method : methods) { 145 String signature = method.toString(); 146 147 int par = signature.indexOf('('); 148 int dot = signature.lastIndexOf('.', par); 149 150 signature = signature.substring(dot + 1); 151 152 assertFalse("Duplicate " + signature, set.contains(signature)); 153 set.add(signature); 154 } 155 } 156 157 interface MyInterface { 158 void foo(); 159 } 160 161 interface MyOtherInterface extends MyInterface { 162 void bar(); 163 } 164 165 abstract class MyClass implements MyOtherInterface { 166 public void gabba() { 167 } 168 169 public void hey() { 170 } 171 } 172 173 // Check if we also reflect methods from interfaces 174 public void testGetMethodsInterfaces() { 175 Method[] methods = MyInterface.class.getMethods(); 176 assertTrue(hasMethod(methods, ".foo(")); 177 178 methods = MyOtherInterface.class.getMethods(); 179 assertTrue(hasMethod(methods, ".foo(")); 180 assertTrue(hasMethod(methods, ".bar(")); 181 182 methods = MyClass.class.getMethods(); 183 assertTrue(hasMethod(methods, ".foo(")); 184 assertTrue(hasMethod(methods, ".bar(")); 185 186 assertTrue(hasMethod(methods, ".gabba(")); 187 assertTrue(hasMethod(methods, ".hey(")); 188 189 assertTrue(hasMethod(methods, ".toString(")); 190 } 191 192 private boolean hasMethod(Method[] methods, String signature) { 193 for (Method method : methods) { 194 if (method.toString().contains(signature)) { 195 return true; 196 } 197 } 198 return false; 199 } 200 201 // Test for Class.getPackage(); 202 public void testClassGetPackage() { 203 assertNotNull(getClass().getPackage()); 204 assertEquals(packageName, getClass().getPackage().getName()); 205 assertEquals("Unknown", getClass().getPackage().getSpecificationTitle()); 206 207 Package p = Object.class.getPackage(); 208 assertNotNull(p); 209 assertEquals("java.lang", p.getName()); 210 assertSame(p, Object.class.getPackage()); 211 } 212 213 // Regression test for #1123708: Problem with getCanonicalName(), 214 // getSimpleName(), and getPackage(). 215 // 216 // A couple of interesting cases need to be checked: Top-level classes, 217 // member classes, local classes, and anonymous classes. Also, boundary 218 // cases with '$' in the class names are checked, since the '$' is used 219 // as the separator between outer and inner class, so this might lead 220 // to problems (it did in the previous implementation). 221 // 222 // Caution: Adding local or anonymous classes elsewhere in this 223 // file might affect the test. 224 private class MemberClass { 225 } 226 227 private class Mi$o$oup { 228 } 229 230 public void testVariousClassNames() { 231 Class<?> clazz = this.getClass(); 232 String pkg = (clazz.getPackage() == null ? "" : clazz.getPackage().getName() + "."); 233 234 // Simple, top-level class 235 236 assertEquals(pkg + "OldAndroidClassTest", clazz.getName()); 237 assertEquals("OldAndroidClassTest", clazz.getSimpleName()); 238 assertEquals(pkg + "OldAndroidClassTest", clazz.getCanonicalName()); 239 240 clazz = MemberClass.class; 241 242 assertEquals(pkg + "OldAndroidClassTest$MemberClass", clazz.getName()); 243 assertEquals("MemberClass", clazz.getSimpleName()); 244 assertEquals(pkg + "OldAndroidClassTest.MemberClass", clazz.getCanonicalName()); 245 246 class LocalClass { 247 // This space intentionally left blank. 248 } 249 250 clazz = LocalClass.class; 251 252 assertEquals(pkg + "OldAndroidClassTest$1LocalClass", clazz.getName()); 253 assertEquals("LocalClass", clazz.getSimpleName()); 254 assertNull(clazz.getCanonicalName()); 255 256 clazz = new Object() { }.getClass(); 257 258 assertEquals(pkg + "OldAndroidClassTest$1", clazz.getName()); 259 assertEquals("", clazz.getSimpleName()); 260 assertNull(clazz.getCanonicalName()); 261 262 // Weird special cases with dollar in name. 263 264 clazz = Mou$$aka.class; 265 266 assertEquals(pkg + "Mou$$aka", clazz.getName()); 267 assertEquals("Mou$$aka", clazz.getSimpleName()); 268 assertEquals(pkg + "Mou$$aka", clazz.getCanonicalName()); 269 270 clazz = Mi$o$oup.class; 271 272 assertEquals(pkg + "OldAndroidClassTest$Mi$o$oup", clazz.getName()); 273 assertEquals("Mi$o$oup", clazz.getSimpleName()); 274 assertEquals(pkg + "OldAndroidClassTest.Mi$o$oup", clazz.getCanonicalName()); 275 276 class Ma$hedPotatoe$ { 277 } 278 279 clazz = Ma$hedPotatoe$.class; 280 281 assertEquals(pkg + "OldAndroidClassTest$1Ma$hedPotatoe$", clazz.getName()); 282 assertEquals("Ma$hedPotatoe$", clazz.getSimpleName()); 283 assertNull(clazz.getCanonicalName()); 284 } 285 286 public void testLocalMemberClass() { 287 Class<?> clazz = this.getClass(); 288 289 assertFalse(clazz.isMemberClass()); 290 assertFalse(clazz.isLocalClass()); 291 292 clazz = MemberClass.class; 293 294 assertTrue(clazz.isMemberClass()); 295 assertFalse(clazz.isLocalClass()); 296 297 class OtherLocalClass { 298 } 299 300 clazz = OtherLocalClass.class; 301 302 assertFalse(clazz.isMemberClass()); 303 assertTrue(clazz.isLocalClass()); 304 305 clazz = new Object() { }.getClass(); 306 307 assertFalse(clazz.isMemberClass()); 308 assertFalse(clazz.isLocalClass()); 309 } 310} 311 312class ClassWithPrivateConstructor { 313 private ClassWithPrivateConstructor() { 314 } 315} 316 317class Mou$$aka { 318} 319