diff options
Diffstat (limited to 'luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java')
-rw-r--r-- | luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java | 277 |
1 files changed, 275 insertions, 2 deletions
diff --git a/luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java b/luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java index c23775e..4cc69ba 100644 --- a/luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java +++ b/luni/src/test/java/libcore/java/lang/reflect/AnnotationsTest.java @@ -16,6 +16,7 @@ package libcore.java.lang.reflect; +import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; @@ -23,7 +24,11 @@ import java.lang.annotation.RetentionPolicy; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -56,7 +61,13 @@ public final class AnnotationsTest extends TestCase { public void testParameterAnnotations() throws Exception { Method method = Type.class.getMethod("method", String.class, String.class); - Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + Annotation[][] noParameterAnnotations = method.getParameterAnnotations(); + assertEquals(2, noParameterAnnotations.length); + assertEquals(set(), annotationsToTypes(noParameterAnnotations[0])); + assertEquals(set(), annotationsToTypes(noParameterAnnotations[1])); + + Method parameters = Type.class.getMethod("parameters", String.class, String.class); + Annotation[][] parameterAnnotations = parameters.getParameterAnnotations(); assertEquals(2, parameterAnnotations.length); assertEquals(set(AnnotationB.class, AnnotationD.class), annotationsToTypes(parameterAnnotations[0])); @@ -64,6 +75,206 @@ public final class AnnotationsTest extends TestCase { annotationsToTypes(parameterAnnotations[1])); } + public void testAnnotationDefaults() throws Exception { + assertEquals((byte) 5, defaultValue("a")); + assertEquals((short) 6, defaultValue("b")); + assertEquals(7, defaultValue("c")); + assertEquals(8L, defaultValue("d")); + assertEquals(9.0f, defaultValue("e")); + assertEquals(10.0, defaultValue("f")); + assertEquals('k', defaultValue("g")); + assertEquals(true, defaultValue("h")); + assertEquals(Breakfast.WAFFLES, defaultValue("i")); + assertEquals("@" + AnnotationA.class.getName() + "()", defaultValue("j").toString()); + assertEquals("maple", defaultValue("k")); + assertEquals(AnnotationB.class, defaultValue("l")); + assertEquals("[1, 2, 3]", Arrays.toString((int[]) defaultValue("m"))); + assertEquals("[WAFFLES, PANCAKES]", Arrays.toString((Breakfast[]) defaultValue("n"))); + assertEquals(null, defaultValue("o")); + assertEquals(null, defaultValue("p")); + } + + private Object defaultValue(String name) throws NoSuchMethodException { + return HasDefaultsAnnotation.class.getMethod(name).getDefaultValue(); + } + + public void testGetEnclosingClass() { + assertNull(AnnotationsTest.class.getEnclosingClass()); + assertEquals(AnnotationsTest.class, Foo.class.getEnclosingClass()); + assertEquals(AnnotationsTest.class, HasMemberClassesInterface.class.getEnclosingClass()); + assertEquals(HasMemberClassesInterface.class, + HasMemberClassesInterface.D.class.getEnclosingClass()); + assertEquals(AnnotationsTest.class, Foo.class.getEnclosingClass()); + } + + public void testGetDeclaringClass() { + assertNull(AnnotationsTest.class.getDeclaringClass()); + assertEquals(AnnotationsTest.class, Foo.class.getDeclaringClass()); + assertEquals(AnnotationsTest.class, HasMemberClassesInterface.class.getDeclaringClass()); + assertEquals(HasMemberClassesInterface.class, + HasMemberClassesInterface.D.class.getDeclaringClass()); + } + + public void testGetEnclosingClassIsTransitiveForClassesDefinedInAMethod() { + class C {} + assertEquals(AnnotationsTest.class, C.class.getEnclosingClass()); + } + + public void testGetDeclaringClassIsNotTransitiveForClassesDefinedInAMethod() { + class C {} + assertEquals(null, C.class.getDeclaringClass()); + } + + public void testGetEnclosingMethodIsNotTransitive() { + class C { + class D {} + } + assertEquals(null, C.D.class.getEnclosingMethod()); + } + + public void testStaticFieldAnonymousClass() { + // The class declared in the <clinit> is enclosed by the <clinit>'s class. + // http://b/11245138 + assertEquals(AnnotationsTest.class, staticAnonymous.getClass().getEnclosingClass()); + // However, because it is anonymous, it has no declaring class. + // https://code.google.com/p/android/issues/detail?id=61003 + assertNull(staticAnonymous.getClass().getDeclaringClass()); + // Because the class is declared in <clinit> which is not exposed through reflection, + // it has no enclosing method or constructor. + assertNull(staticAnonymous.getClass().getEnclosingMethod()); + assertNull(staticAnonymous.getClass().getEnclosingConstructor()); + } + + public void testGetEnclosingMethodOfTopLevelClass() { + assertNull(AnnotationsTest.class.getEnclosingMethod()); + } + + public void testGetEnclosingConstructorOfTopLevelClass() { + assertNull(AnnotationsTest.class.getEnclosingConstructor()); + } + + public void testClassEnclosedByConstructor() throws Exception { + Foo foo = new Foo("string"); + assertEquals(Foo.class, foo.c.getEnclosingClass()); + assertEquals(Foo.class.getDeclaredConstructor(String.class), + foo.c.getEnclosingConstructor()); + assertNull(foo.c.getEnclosingMethod()); + assertNull(foo.c.getDeclaringClass()); + } + + public void testClassEnclosedByMethod() throws Exception { + Foo foo = new Foo(); + foo.foo("string"); + assertEquals(Foo.class, foo.c.getEnclosingClass()); + assertNull(foo.c.getEnclosingConstructor()); + assertEquals(Foo.class.getDeclaredMethod("foo", String.class), + foo.c.getEnclosingMethod()); + assertNull(foo.c.getDeclaringClass()); + } + + public void testGetClasses() throws Exception { + // getClasses() doesn't include classes inherited from interfaces! + assertSetEquals(HasMemberClasses.class.getClasses(), + HasMemberClassesSuperclass.B.class, HasMemberClasses.H.class); + } + + public void testGetDeclaredClasses() throws Exception { + assertSetEquals(HasMemberClasses.class.getDeclaredClasses(), + HasMemberClasses.G.class, HasMemberClasses.H.class, HasMemberClasses.I.class, + HasMemberClasses.J.class, HasMemberClasses.K.class, HasMemberClasses.L.class); + } + + public void testConstructorGetExceptions() throws Exception { + assertSetEquals(HasThrows.class.getConstructor().getExceptionTypes(), + IOException.class, InvocationTargetException.class, IllegalStateException.class); + assertSetEquals(HasThrows.class.getConstructor(Void.class).getExceptionTypes()); + } + + public void testClassMethodGetExceptions() throws Exception { + assertSetEquals(HasThrows.class.getMethod("foo").getExceptionTypes(), + IOException.class, InvocationTargetException.class, IllegalStateException.class); + assertSetEquals(HasThrows.class.getMethod("foo", Void.class).getExceptionTypes()); + } + + public void testProxyMethodGetExceptions() throws Exception { + InvocationHandler emptyInvocationHandler = new InvocationHandler() { + @Override public Object invoke(Object proxy, Method method, Object[] args) { + return null; + } + }; + + Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), + new Class[] { ThrowsInterface.class }, emptyInvocationHandler); + assertSetEquals(proxy.getClass().getMethod("foo").getExceptionTypes(), + IOException.class, InvocationTargetException.class, IllegalStateException.class); + assertSetEquals(proxy.getClass().getMethod("foo", Void.class).getExceptionTypes()); + } + + public void testClassModifiers() { + int modifiers = AnnotationsTest.class.getModifiers(); + assertTrue(Modifier.isPublic(modifiers)); + assertFalse(Modifier.isProtected(modifiers)); + assertFalse(Modifier.isPrivate(modifiers)); + assertFalse(Modifier.isAbstract(modifiers)); + assertFalse(Modifier.isStatic(modifiers)); + assertTrue(Modifier.isFinal(modifiers)); + assertFalse(Modifier.isStrict(modifiers)); + } + + public void testInnerClassModifiers() { + int modifiers = Foo.class.getModifiers(); + assertFalse(Modifier.isPublic(modifiers)); + assertFalse(Modifier.isProtected(modifiers)); + assertTrue(Modifier.isPrivate(modifiers)); + assertFalse(Modifier.isAbstract(modifiers)); + assertTrue(Modifier.isStatic(modifiers)); + assertFalse(Modifier.isFinal(modifiers)); + assertFalse(Modifier.isStrict(modifiers)); + } + + public void testAnonymousClassModifiers() { + int modifiers = staticAnonymous.getClass().getModifiers(); + assertFalse(Modifier.isPublic(modifiers)); + assertFalse(Modifier.isProtected(modifiers)); + assertFalse(Modifier.isPrivate(modifiers)); + assertFalse(Modifier.isAbstract(modifiers)); + assertTrue(Modifier.isStatic(modifiers)); + assertFalse(Modifier.isFinal(modifiers)); + assertFalse(Modifier.isStrict(modifiers)); + } + + public void testInnerClassName() { + assertEquals("AnnotationsTest", AnnotationsTest.class.getSimpleName()); + assertEquals("Foo", Foo.class.getSimpleName()); + assertEquals("", staticAnonymous.getClass().getSimpleName()); + } + + public void testIsAnonymousClass() { + assertFalse(AnnotationsTest.class.isAnonymousClass()); + assertFalse(Foo.class.isAnonymousClass()); + assertTrue(staticAnonymous.getClass().isAnonymousClass()); + } + + private static final Object staticAnonymous = new Object() {}; + + private static class Foo { + Class<?> c; + private Foo() { + } + private Foo(String s) { + c = new Object() {}.getClass(); + } + private Foo(int i) { + c = new Object() {}.getClass(); + } + private void foo(String s) { + c = new Object() {}.getClass(); + } + private void foo(int i) { + c = new Object() {}.getClass(); + } + } + @Retention(RetentionPolicy.RUNTIME) public @interface AnnotationA {} @@ -81,12 +292,68 @@ public final class AnnotationsTest extends TestCase { public static class Type { @AnnotationA @AnnotationC public Type() {} @AnnotationA @AnnotationD public String field; - @AnnotationB @AnnotationC public void method(@AnnotationB @AnnotationD String parameter1, + @AnnotationB @AnnotationC public void method(String parameter1, String parameter2) {} + @AnnotationB @AnnotationC public void parameters(@AnnotationB @AnnotationD String parameter1, @AnnotationC @AnnotationD String parameter2) {} } public static class ExtendsType extends Type {} + static enum Breakfast { WAFFLES, PANCAKES } + + @Retention(RetentionPolicy.RUNTIME) + public @interface HasDefaultsAnnotation { + byte a() default 5; + short b() default 6; + int c() default 7; + long d() default 8; + float e() default 9.0f; + double f() default 10.0; + char g() default 'k'; + boolean h() default true; + Breakfast i() default Breakfast.WAFFLES; + AnnotationA j() default @AnnotationA(); + String k() default "maple"; + Class l() default AnnotationB.class; + int[] m() default { 1, 2, 3 }; + Breakfast[] n() default { Breakfast.WAFFLES, Breakfast.PANCAKES }; + Breakfast o(); + int p(); + } + + static class HasMemberClassesSuperclass { + class A {} + public class B {} + static class C {} + } + + public interface HasMemberClassesInterface { + class D {} + public class E {} + static class F {} + } + + public static class HasMemberClasses extends HasMemberClassesSuperclass + implements HasMemberClassesInterface { + class G {} + public class H {} + static class I {} + enum J {} + interface K {} + @interface L {} + } + + public static class HasThrows { + public HasThrows() throws IOException, InvocationTargetException, IllegalStateException {} + public HasThrows(Void v) {} + public void foo() throws IOException, InvocationTargetException, IllegalStateException {} + public void foo(Void v) {} + } + + public static interface ThrowsInterface { + void foo() throws IOException, InvocationTargetException, IllegalStateException; + void foo(Void v); + } private void assertAnnotatedElement( AnnotatedElement element, Class<? extends Annotation>... expectedAnnotations) { @@ -134,4 +401,10 @@ public final class AnnotationsTest extends TestCase { private <T> Set<T> set(T... instances) { return new HashSet<T>(Arrays.asList(instances)); } + + private void assertSetEquals(Object[] actual, Object... expected) { + Set<Object> actualSet = new HashSet<Object>(Arrays.asList(actual)); + Set<Object> expectedSet = new HashSet<Object>(Arrays.asList(expected)); + assertEquals(expectedSet, actualSet); + } } |