Home | History | Annotate | Download | only in core
      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 android.core;
     18 
     19 import android.test.suitebuilder.annotation.MediumTest;
     20 import android.test.suitebuilder.annotation.SmallTest;
     21 import android.widget.Button;
     22 import junit.framework.TestCase;
     23 
     24 import java.lang.reflect.Constructor;
     25 import java.lang.reflect.Field;
     26 import java.lang.reflect.Method;
     27 import java.lang.reflect.Modifier;
     28 import java.util.HashSet;
     29 import java.util.Set;
     30 
     31 
     32 class ClassWithPrivateConstructor {
     33     private ClassWithPrivateConstructor() {
     34     }
     35 }
     36 
     37 public 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 
    335 class Mou$$aka {
    336     // This space intentionally left blank.
    337 }
    338