| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package libcore.java.lang; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| |
| import junit.framework.TestCase; |
| |
| import dalvik.system.PathClassLoader; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.reflect.Method; |
| import java.util.TreeMap; |
| import java.util.function.Function; |
| |
| public class ClassTest extends TestCase { |
| |
| interface Foo { |
| public void foo(); |
| } |
| |
| interface ParameterizedFoo<T> { |
| public void foo(T param); |
| } |
| |
| interface ParameterizedBar<T> extends ParameterizedFoo<T> { |
| public void bar(T param); |
| } |
| |
| interface ParameterizedBaz extends ParameterizedFoo<String> { |
| |
| } |
| |
| public void test_getGenericSuperclass_nullReturnCases() { |
| // Should always return null for interfaces. |
| assertNull(Foo.class.getGenericSuperclass()); |
| assertNull(ParameterizedFoo.class.getGenericSuperclass()); |
| assertNull(ParameterizedBar.class.getGenericSuperclass()); |
| assertNull(ParameterizedBaz.class.getGenericSuperclass()); |
| |
| assertNull(Object.class.getGenericSuperclass()); |
| assertNull(void.class.getGenericSuperclass()); |
| assertNull(int.class.getGenericSuperclass()); |
| } |
| |
| public void test_getGenericSuperclass_returnsObjectForArrays() { |
| assertSame(Object.class, (new Integer[0]).getClass().getGenericSuperclass()); |
| } |
| |
| public void test_b28833829() throws Exception { |
| File f = File.createTempFile("temp_b28833829", ".dex"); |
| try (InputStream is = |
| getClass().getClassLoader().getResourceAsStream("TestBug28833829.dex"); |
| OutputStream os = new FileOutputStream(f)) { |
| byte[] buffer = new byte[8192]; |
| int bytesRead = 0; |
| while ((bytesRead = is.read(buffer)) >= 0) { |
| os.write(buffer, 0, bytesRead); |
| } |
| } |
| |
| PathClassLoader pcl = new PathClassLoader(f.getAbsolutePath(), null); |
| Class<?> cl = pcl.loadClass( |
| "libcore.java.lang.TestBadInnerClass_Outer$ClassTestBadInnerClass_InnerClass"); |
| |
| // Note that getName() and getSimpleName() are inconsistent here because for |
| // inner classes, the latter is fetched directly from the InnerClass |
| // annotation in the dex file. We do not perform any sort of consistency |
| // checks with the class name or the enclosing class name. Unfortunately, applications |
| // have come to rely on this behaviour. |
| assertEquals("libcore.java.lang.TestBadInnerClass_Outer$ClassTestBadInnerClass_InnerClass", |
| cl.getName()); |
| assertEquals("TestBadInnerClass_InnerXXXXX", cl.getSimpleName()); |
| } |
| |
| interface A { |
| public static String name = "A"; |
| } |
| interface B { |
| public static String name = "B"; |
| } |
| class X implements A { } |
| class Y extends X implements B { } |
| public void test_getField() { |
| try { |
| assertEquals(A.class.getField("name"), X.class.getField("name")); |
| } catch (NoSuchFieldException e) { |
| fail("Got exception"); |
| } |
| try { |
| assertEquals(B.class.getField("name"), Y.class.getField("name")); |
| } catch (NoSuchFieldException e) { |
| fail("Got exception"); |
| } |
| } |
| |
| interface C { |
| void foo(); |
| } |
| interface D extends C { |
| void foo(); |
| } |
| abstract class Z implements D { } |
| |
| public void test_getMethod() { |
| try { |
| assertEquals(Z.class.getMethod("foo"), D.class.getMethod("foo")); |
| } catch (NoSuchMethodException e) { |
| fail("Got exception"); |
| } |
| } |
| |
| public static class TestGetVirtualMethod_Super { |
| protected String protectedMethod() { |
| return "protectedMethod"; |
| } |
| |
| public String publicMethod() { |
| return "publicMethod"; |
| } |
| |
| /* package */ String packageMethod() { |
| return "packageMethod"; |
| } |
| } |
| |
| public static class TestGetVirtualMethod extends TestGetVirtualMethod_Super { |
| public static void staticMethod(String foo) { |
| } |
| |
| public String publicMethod2() { |
| return "publicMethod2"; |
| } |
| |
| protected String protectedMethod2() { |
| return "protectedMethod2"; |
| } |
| |
| private String privateMethod() { |
| return "privateMethod"; |
| } |
| |
| /* package */ String packageMethod2() { |
| return "packageMethod2"; |
| } |
| } |
| |
| public void test_getVirtualMethod() throws Exception { |
| final Class<?>[] noArgs = new Class<?>[] { }; |
| |
| TestGetVirtualMethod instance = new TestGetVirtualMethod(); |
| TestGetVirtualMethod_Super super_instance = new TestGetVirtualMethod_Super(); |
| |
| // Package private methods from the queried class as well as super classes |
| // must be returned. |
| Method m = TestGetVirtualMethod.class.getInstanceMethod("packageMethod2", noArgs); |
| assertNotNull(m); |
| assertEquals("packageMethod2", m.invoke(instance)); |
| m = TestGetVirtualMethod.class.getInstanceMethod("packageMethod", noArgs); |
| assertNotNull(m); |
| assertEquals("packageMethod", m.invoke(instance)); |
| |
| // Protected methods from both the queried class as well as super classes must |
| // be returned. |
| m = TestGetVirtualMethod.class.getInstanceMethod("protectedMethod2", noArgs); |
| assertNotNull(m); |
| assertEquals("protectedMethod2", m.invoke(instance)); |
| m = TestGetVirtualMethod.class.getInstanceMethod("protectedMethod", noArgs); |
| assertNotNull(m); |
| assertEquals("protectedMethod", m.invoke(instance)); |
| |
| // Public methods from the queried classes and all its super classes must be |
| // returned. |
| m = TestGetVirtualMethod.class.getInstanceMethod("publicMethod2", noArgs); |
| assertNotNull(m); |
| assertEquals("publicMethod2", m.invoke(instance)); |
| m = TestGetVirtualMethod.class.getInstanceMethod("publicMethod", noArgs); |
| assertNotNull(m); |
| assertEquals("publicMethod", m.invoke(instance)); |
| |
| m = TestGetVirtualMethod.class.getInstanceMethod("privateMethod", noArgs); |
| assertNotNull(m); |
| |
| assertNull(TestGetVirtualMethod.class.getInstanceMethod("staticMethod", noArgs)); |
| } |
| |
| public void test_toString() throws Exception { |
| final String outerClassName = getClass().getName(); |
| final String packageProtectedClassName = PackageProtectedClass.class.getName(); |
| |
| assertToString("int", int.class); |
| assertToString("class [I", int[].class); |
| assertToString("class java.lang.Object", Object.class); |
| assertToString("class [Ljava.lang.Object;", Object[].class); |
| assertToString("class java.lang.Integer", Integer.class); |
| assertToString("interface java.util.function.Function", Function.class); |
| assertToString( |
| "class " + outerClassName + "$PublicStaticInnerClass", |
| PublicStaticInnerClass.class); |
| assertToString( |
| "class " + outerClassName + "$DefaultStaticInnerClass", |
| DefaultStaticInnerClass.class); |
| assertToString( |
| "interface " + outerClassName + "$PublicInnerInterface", |
| PublicInnerInterface.class); |
| assertToString( |
| "class " + packageProtectedClassName, |
| PackageProtectedClass.class); |
| assertToString( |
| "class " + outerClassName + "$PrivateStaticInnerClass", |
| PrivateStaticInnerClass.class); |
| assertToString("interface java.lang.annotation.Retention", Retention.class); |
| assertToString("class java.lang.annotation.RetentionPolicy", RetentionPolicy.class); |
| assertToString("class java.util.TreeMap", TreeMap.class); |
| assertToString( |
| "interface " + outerClassName + "$WildcardInterface", |
| WildcardInterface.class); |
| } |
| |
| private static void assertToString(String expected, Class<?> clazz) { |
| assertEquals(expected, clazz.toString()); |
| } |
| |
| public void test_getTypeName() throws Exception { |
| final String outerClassName = getClass().getName(); |
| final String packageProtectedClassName = PackageProtectedClass.class.getName(); |
| |
| assertGetTypeName("int", int.class); |
| assertGetTypeName("int[]", int[].class); |
| assertGetTypeName("java.lang.Object", Object.class); |
| assertGetTypeName("java.lang.Object[]", Object[].class); |
| assertGetTypeName("java.lang.Integer", Integer.class); |
| assertGetTypeName("java.util.function.Function", Function.class); |
| assertGetTypeName(outerClassName + "$PublicStaticInnerClass", PublicStaticInnerClass.class); |
| assertGetTypeName( |
| outerClassName + "$DefaultStaticInnerClass", |
| DefaultStaticInnerClass.class); |
| assertGetTypeName(outerClassName + "$PublicInnerInterface", PublicInnerInterface.class); |
| assertGetTypeName(packageProtectedClassName, PackageProtectedClass.class); |
| assertGetTypeName( |
| outerClassName + "$PrivateStaticInnerClass", |
| PrivateStaticInnerClass.class); |
| assertGetTypeName("java.lang.annotation.Retention", Retention.class); |
| assertGetTypeName("java.lang.annotation.RetentionPolicy", RetentionPolicy.class); |
| assertGetTypeName("java.util.TreeMap", TreeMap.class); |
| assertGetTypeName(outerClassName + "$WildcardInterface", WildcardInterface.class); |
| } |
| |
| private void assertGetTypeName(String expected, Class<?> clazz) { |
| assertEquals(expected, clazz.getTypeName()); |
| } |
| |
| public void test_toGenericString() throws Exception { |
| final String outerClassName = getClass().getName(); |
| final String packageProtectedClassName = PackageProtectedClass.class.getName(); |
| |
| assertToGenericString("int", int.class); |
| assertToGenericString("public abstract final class [I", int[].class); |
| assertToGenericString("public class java.lang.Object", Object.class); |
| assertToGenericString("public abstract final class [Ljava.lang.Object;", Object[].class); |
| assertToGenericString("public final class java.lang.Integer", Integer.class); |
| assertToGenericString( |
| "public abstract interface java.util.function.Function<T,R>", |
| Function.class); |
| assertToGenericString("public static class " + outerClassName + "$PublicStaticInnerClass", |
| PublicStaticInnerClass.class); |
| assertToGenericString("static class " + outerClassName + "$DefaultStaticInnerClass", |
| DefaultStaticInnerClass.class); |
| assertToGenericString( |
| "public abstract static interface " + outerClassName + "$PublicInnerInterface", |
| PublicInnerInterface.class); |
| assertToGenericString("class " + packageProtectedClassName, PackageProtectedClass.class); |
| assertToGenericString( |
| "private static class " + outerClassName + "$PrivateStaticInnerClass", |
| PrivateStaticInnerClass.class); |
| assertToGenericString( |
| "public abstract @interface java.lang.annotation.Retention", Retention.class); |
| assertToGenericString("public final enum java.lang.annotation.RetentionPolicy", |
| RetentionPolicy.class); |
| assertToGenericString("public class java.util.TreeMap<K,V>", TreeMap.class); |
| assertToGenericString( |
| "abstract static interface " + outerClassName + "$WildcardInterface<T,U>", |
| WildcardInterface.class); |
| } |
| |
| private static void assertToGenericString(String expected, Class<?> clazz) { |
| assertEquals(expected, clazz.toGenericString()); |
| } |
| |
| private static class PrivateStaticInnerClass {} |
| static class DefaultStaticInnerClass {} |
| public static class PublicStaticInnerClass {} |
| public interface PublicInnerInterface {} |
| interface WildcardInterface< |
| T extends Number, |
| U extends Function<? extends Number, ? super Number>> |
| extends Comparable<T> {} |
| } |