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