• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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