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