summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java219
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementTestSupport.java313
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/Annotations57649Test.java (renamed from luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java)2
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotationsTest.java112
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/ClassTest.java266
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/ConstructorTest.java161
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/FieldTest.java161
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/MethodTest.java161
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/PackageTest.java129
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/ParameterTest.java99
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotation/MultipleAnnotation.java25
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotation/package-info.java24
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationexplicitsingle/MultipleAnnotationExplicitSingle.java26
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationexplicitsingle/package-info.java24
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationoddity/MultipleAnnotationOddity.java26
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationoddity/package-info.java25
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/noannotation/NoAnnotation.java26
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/noannotation/package-info.java (renamed from luni/src/test/java/libcore/java/lang/reflect/package-info.java)8
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/singleannotation/SingleAnnotation.java26
-rw-r--r--luni/src/test/java/libcore/java/lang/reflect/annotations/singleannotation/package-info.java24
20 files changed, 1851 insertions, 6 deletions
diff --git a/luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java b/luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java
index 1950bf34d5..f690295635 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/ReflectionTest.java
@@ -16,22 +16,28 @@
package libcore.java.lang.reflect;
+import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.RandomAccess;
import java.util.Set;
-import junit.framework.Assert;
import junit.framework.TestCase;
public final class ReflectionTest extends TestCase {
@@ -430,4 +436,215 @@ public final class ReflectionTest extends TestCase {
void foobar() {}
}
}
+
+ public void testGetEnclosingClass() {
+ assertNull(ReflectionTest.class.getEnclosingClass());
+ assertEquals(ReflectionTest.class, Foo.class.getEnclosingClass());
+ assertEquals(ReflectionTest.class, HasMemberClassesInterface.class.getEnclosingClass());
+ assertEquals(HasMemberClassesInterface.class,
+ HasMemberClassesInterface.D.class.getEnclosingClass());
+ assertEquals(ReflectionTest.class, Foo.class.getEnclosingClass());
+ }
+
+ public void testGetDeclaringClass() {
+ assertNull(ReflectionTest.class.getDeclaringClass());
+ assertEquals(ReflectionTest.class, Foo.class.getDeclaringClass());
+ assertEquals(ReflectionTest.class, HasMemberClassesInterface.class.getDeclaringClass());
+ assertEquals(HasMemberClassesInterface.class,
+ HasMemberClassesInterface.D.class.getDeclaringClass());
+ }
+
+ public void testGetEnclosingClassIsTransitiveForClassesDefinedInAMethod() {
+ class C {}
+ assertEquals(ReflectionTest.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());
+ }
+
+ private static final Object staticAnonymous = new Object() {};
+
+ public void testStaticFieldAnonymousClass() {
+ // The class declared in the <clinit> is enclosed by the <clinit>'s class.
+ // http://b/11245138
+ assertEquals(ReflectionTest.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(ReflectionTest.class.getEnclosingMethod());
+ }
+
+ public void testGetEnclosingConstructorOfTopLevelClass() {
+ assertNull(ReflectionTest.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 = ReflectionTest.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("ReflectionTest", ReflectionTest.class.getSimpleName());
+ assertEquals("Foo", Foo.class.getSimpleName());
+ assertEquals("", staticAnonymous.getClass().getSimpleName());
+ }
+
+ 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();
+ }
+ }
+
+ 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 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);
+ }
}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementTestSupport.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementTestSupport.java
new file mode 100644
index 0000000000..ec574699b6
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementTestSupport.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.AnnotatedElement;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringJoiner;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+
+/**
+ * Utility methods and annotation definitions for use when testing implementations of
+ * AnnotatedElement.
+ *
+ * <p>For compactness, the repeated annotation methods that take strings use a format based on Java
+ * syntax rather than the toString() of annotations. For example, "@Repeated(1)" rather than
+ * "@libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated(value=1)". Use
+ * {@link #EXPECT_EMPTY} to indicate "no annotationed expected".
+ */
+public class AnnotatedElementTestSupport {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface AnnotationA {}
+
+ @Inherited
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface AnnotationB {}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface AnnotationC {}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface AnnotationD {}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Inherited
+ @Target({ ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD,
+ ElementType.PARAMETER, ElementType.PACKAGE })
+ public @interface Container {
+ Repeated[] value();
+ }
+
+ @Repeatable(Container.class)
+ @Retention(RetentionPolicy.RUNTIME)
+ @Inherited
+ @Target({ ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD,
+ ElementType.PARAMETER, ElementType.PACKAGE })
+ public @interface Repeated {
+ int value();
+ }
+
+ /**
+ * A named constant that can be used with assert methods below that take
+ * "String[] expectedAnnotationStrings" as their final argument to indicate "none".
+ */
+ public static final String[] EXPECT_EMPTY = new String[0];
+
+ private AnnotatedElementTestSupport() {
+ }
+
+ /**
+ * Test the {@link AnnotatedElement} methods associated with "presence". i.e. methods that
+ * deal with annotations being "present" (i.e. "direct" or "inherited" annotations, not
+ * "indirect").
+ *
+ * <p>Asserts that calling {@link AnnotatedElement#getAnnotations()} on the supplied element
+ * returns annotations of the supplied expected classes.
+ *
+ * <p>Where the expected classes contains some subset from
+ * {@link AnnotationA}, {@link AnnotationB} and {@link AnnotationC}, this method also asserts
+ * that {@link AnnotatedElement#isAnnotationPresent(Class)} and
+ * {@link AnnotatedElement#getAnnotation(Class)} works as expected.
+ *
+ * <p>This method also confirms that {@link AnnotatedElement#isAnnotationPresent(Class)} and
+ * {@link AnnotatedElement#getAnnotation(Class)} work correctly with a {@code null} argument.
+ */
+ static void checkAnnotatedElementPresentMethods(
+ AnnotatedElement element, Class<? extends Annotation>... expectedAnnotations) {
+ Set<Class<? extends Annotation>> actualTypes = annotationsToTypes(element.getAnnotations());
+ Set<Class<? extends Annotation>> expectedTypes = set(expectedAnnotations);
+ assertEquals(expectedTypes, actualTypes);
+
+ // getAnnotations() should be consistent with isAnnotationPresent() and getAnnotation()
+ assertPresent(expectedTypes.contains(AnnotationA.class), element, AnnotationA.class);
+ assertPresent(expectedTypes.contains(AnnotationB.class), element, AnnotationB.class);
+ assertPresent(expectedTypes.contains(AnnotationC.class), element, AnnotationC.class);
+
+ try {
+ element.isAnnotationPresent(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ element.getAnnotation(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ /**
+ * Test the {@link AnnotatedElement} methods associated with "direct" annotations.
+ *
+ * <p>Asserts that calling {@link AnnotatedElement#getDeclaredAnnotations()} on the supplied
+ * element returns annotations of the supplied expected classes.
+ *
+ * <p>Where the expected classes contains some subset from
+ * {@link AnnotationA}, {@link AnnotationB} and {@link AnnotationC}, this method also asserts
+ * that {@link AnnotatedElement#getDeclaredAnnotation(Class)} works as expected.
+ *
+ * <p>This method also confirms that {@link AnnotatedElement#isAnnotationPresent(Class)} and
+ * {@link AnnotatedElement#getAnnotation(Class)} work correctly with a {@code null} argument.
+ */
+ static void checkAnnotatedElementDirectMethods(
+ AnnotatedElement element,
+ Class<? extends Annotation>... expectedDeclaredAnnotations) {
+ Set<Class<? extends Annotation>> actualTypes = annotationsToTypes(element.getDeclaredAnnotations());
+ Set<Class<? extends Annotation>> expectedTypes = set(expectedDeclaredAnnotations);
+ assertEquals(expectedTypes, actualTypes);
+
+ assertDeclared(expectedTypes.contains(AnnotationA.class), element, AnnotationA.class);
+ assertDeclared(expectedTypes.contains(AnnotationB.class), element, AnnotationB.class);
+ assertDeclared(expectedTypes.contains(AnnotationC.class), element, AnnotationC.class);
+
+ try {
+ element.getDeclaredAnnotation(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ /**
+ * Extracts the annotation types ({@link Annotation#annotationType()} from the supplied
+ * annotations.
+ */
+ static Set<Class<? extends Annotation>> annotationsToTypes(Annotation[] annotations) {
+ Set<Class<? extends Annotation>> result = new HashSet<Class<? extends Annotation>>();
+ for (Annotation annotation : annotations) {
+ result.add(annotation.annotationType());
+ }
+ return result;
+ }
+
+ private static void assertPresent(boolean present, AnnotatedElement element,
+ Class<? extends Annotation> annotation) {
+ if (present) {
+ assertNotNull(element.getAnnotation(annotation));
+ assertTrue(element.isAnnotationPresent(annotation));
+ } else {
+ assertNull(element.getAnnotation(annotation));
+ assertFalse(element.isAnnotationPresent(annotation));
+ }
+ }
+
+ private static void assertDeclared(boolean present, AnnotatedElement element,
+ Class<? extends Annotation> annotation) {
+ if (present) {
+ assertNotNull(element.getDeclaredAnnotation(annotation));
+ } else {
+ assertNull(element.getDeclaredAnnotation(annotation));
+ }
+ }
+
+ @SafeVarargs
+ static <T> Set<T> set(T... instances) {
+ return new HashSet<>(Arrays.asList(instances));
+ }
+
+ /**
+ * Asserts that {@link AnnotatedElement#isAnnotationPresent(Class)} returns the expected result.
+ */
+ static void assertIsAnnotationPresent(
+ AnnotatedElement element, Class<? extends Annotation> annotationType,
+ boolean expected) {
+ assertEquals("element.isAnnotationPresent() for " + element + " and " + annotationType,
+ expected, element.isAnnotationPresent(annotationType));
+ }
+
+ /**
+ * Asserts that {@link AnnotatedElement#getDeclaredAnnotation(Class)} returns the expected
+ * result. The result is specified using a String. See {@link AnnotatedElementTestSupport} for
+ * the string syntax.
+ */
+ static void assertGetDeclaredAnnotation(AnnotatedElement annotatedElement,
+ Class<? extends Annotation> annotationType, String expectedAnnotationString) {
+ Annotation annotation = annotatedElement.getDeclaredAnnotation(annotationType);
+ assertAnnotationMatches(annotation, expectedAnnotationString);
+ }
+
+ /**
+ * Asserts that {@link AnnotatedElement#getDeclaredAnnotationsByType(Class)} returns the
+ * expected result. The result is specified using a String. See
+ * {@link AnnotatedElementTestSupport} for the string syntax.
+ */
+ static void assertGetDeclaredAnnotationsByType(
+ AnnotatedElement annotatedElement, Class<? extends Annotation> annotationType,
+ String[] expectedAnnotationStrings) {
+ Annotation[] annotations = annotatedElement.getDeclaredAnnotationsByType(annotationType);
+ assertAnnotationsMatch(annotations, expectedAnnotationStrings);
+ }
+
+ /**
+ * Asserts that {@link AnnotatedElement#getAnnotationsByType(Class)} returns the
+ * expected result. The result is specified using a String. See
+ * {@link AnnotatedElementTestSupport} for the string syntax.
+ */
+ static void assertGetAnnotationsByType(AnnotatedElement annotatedElement,
+ Class<? extends Annotation> annotationType, String[] expectedAnnotationStrings)
+ throws Exception {
+ Annotation[] annotations = annotatedElement.getAnnotationsByType(annotationType);
+ assertAnnotationsMatch(annotations, expectedAnnotationStrings);
+ }
+
+ private static void assertAnnotationMatches(
+ Annotation annotation, String expectedAnnotationString) {
+ if (expectedAnnotationString == null) {
+ assertNull(annotation);
+ } else {
+ assertNotNull(annotation);
+ assertEquals(expectedAnnotationString, createAnnotationTestString(annotation));
+ }
+ }
+
+ /**
+ * Asserts that the supplied annotations match the expectation Strings. See
+ * {@link AnnotatedElementTestSupport} for the string syntax.
+ */
+ static void assertAnnotationsMatch(Annotation[] annotations,
+ String[] expectedAnnotationStrings) {
+
+ // Due to Android's dex format insisting that Annotations are sorted by name the ordering of
+ // annotations is determined by the (simple?) name of the Annotation, not just the order
+ // that they are defined in the source. Tests have to be sensitive to that when handling
+ // mixed usage of "Container" and "Repeated" - the "Container" annotations will be
+ // discovered before "Repeated" due to their sort ordering.
+ //
+ // This code assumes that repeated annotations with the same name will be specified in the
+ // source their natural sort order when attributes are considered, just to make the testing
+ // simpler.
+ // e.g. @Repeated(1) @Repeated(2), never @Repeated(2) @Repeated(1)
+
+ // Sorting the expected and actual strings _should_ work providing the assumptions above
+ // hold. It may mask random ordering issues but it's harder to deal with that while the
+ // source ordering is no observed. Providing no developers are ascribing meaning to the
+ // relative order of annotations things should be ok.
+ Arrays.sort(expectedAnnotationStrings);
+
+ String[] actualAnnotationStrings = createAnnotationTestStrings(annotations);
+ Arrays.sort(actualAnnotationStrings);
+
+ assertEquals(
+ Arrays.asList(expectedAnnotationStrings),
+ Arrays.asList(actualAnnotationStrings));
+ }
+
+ private static String[] createAnnotationTestStrings(Annotation[] annotations) {
+ String[] annotationStrings = new String[annotations.length];
+ for (int i = 0; i < annotations.length; i++) {
+ annotationStrings[i] = createAnnotationTestString(annotations[i]);
+ }
+ return annotationStrings;
+ }
+
+ private static String createAnnotationTestString(Annotation annotation) {
+ return "@" + annotation.annotationType().getSimpleName() + createArgumentsTestString(
+ annotation);
+ }
+
+ private static String createArgumentsTestString(Annotation annotation) {
+ if (annotation instanceof Repeated) {
+ Repeated repeated = (Repeated) annotation;
+ return "(" + repeated.value() + ")";
+ } else if (annotation instanceof Container) {
+ Container container = (Container) annotation;
+ String[] repeatedValues = createAnnotationTestStrings(container.value());
+ StringJoiner joiner = new StringJoiner(", ", "{", "}");
+ for (String repeatedValue : repeatedValues) {
+ joiner.add(repeatedValue);
+ }
+ String repeatedValuesString = joiner.toString();
+ return "(" + repeatedValuesString + ")";
+ }
+ throw new AssertionError("Unknown annotation: " + annotation);
+ }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/Annotations57649Test.java
index 60e294bd6c..94c265eae9 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/Annotations57649Test.java
@@ -1,4 +1,4 @@
-package libcore.java.lang.reflect;
+package libcore.java.lang.reflect.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotationsTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotationsTest.java
new file mode 100644
index 0000000000..a694981c70
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotationsTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2011 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.reflect.annotations;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationA;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationB;
+
+import dalvik.system.VMRuntime;
+
+/**
+ * Tests for the behavior of Annotation instances at runtime.
+ */
+public class AnnotationsTest extends TestCase {
+
+ 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();
+ }
+
+ 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 static Object defaultValue(String name) throws NoSuchMethodException {
+ return HasDefaultsAnnotation.class.getMethod(name).getDefaultValue();
+ }
+
+ @Retention(RetentionPolicy.CLASS)
+ public @interface ClassRetentionAnnotation {}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface RuntimeRetentionAnnotation {}
+
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SourceRetentionAnnotation {}
+
+ @ClassRetentionAnnotation @RuntimeRetentionAnnotation @SourceRetentionAnnotation
+ public static class RetentionAnnotations {}
+
+ public void testRetentionPolicy() {
+ // b/29500035
+ int savedTargetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion();
+ try {
+ // Test N and later behavior
+ VMRuntime.getRuntime().setTargetSdkVersion(24);
+ Annotation classRetentionAnnotation =
+ RetentionAnnotations.class.getAnnotation(ClassRetentionAnnotation.class);
+ assertNull(classRetentionAnnotation);
+
+ // Test pre-N behavior
+ VMRuntime.getRuntime().setTargetSdkVersion(23);
+ classRetentionAnnotation =
+ RetentionAnnotations.class.getAnnotation(ClassRetentionAnnotation.class);
+ assertNotNull(classRetentionAnnotation);
+ } finally {
+ VMRuntime.getRuntime().setTargetSdkVersion(savedTargetSdkVersion);
+ }
+ assertNotNull(RetentionAnnotations.class.getAnnotation(RuntimeRetentionAnnotation.class));
+ assertNull(RetentionAnnotations.class.getAnnotation(SourceRetentionAnnotation.class));
+ }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/ClassTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/ClassTest.java
new file mode 100644
index 0000000000..5488ed19d0
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/ClassTest.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Inherited;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationA;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationB;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
+
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.checkAnnotatedElementPresentMethods;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.checkAnnotatedElementDirectMethods;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertGetDeclaredAnnotation;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertIsAnnotationPresent;
+
+public class ClassTest extends TestCase {
+
+ public void setUp() throws Exception {
+ super.setUp();
+ // Required by all the tests.
+ Repeated.class.isAnnotationPresent(Inherited.class);
+ }
+
+ @AnnotationA
+ @AnnotationB
+ private static class Type {
+ }
+
+ public static class ExtendsType extends Type {}
+
+ public void testClassDirectAnnotations() {
+ checkAnnotatedElementPresentMethods(Type.class, AnnotationA.class, AnnotationB.class);
+ checkAnnotatedElementDirectMethods(Type.class, AnnotationA.class, AnnotationB.class);
+ }
+
+ public void testClassInheritedAnnotations() {
+ checkAnnotatedElementPresentMethods(ExtendsType.class, AnnotationB.class);
+ checkAnnotatedElementDirectMethods(ExtendsType.class);
+ }
+
+ @Repeated(1)
+ private static class SingleAnnotation {}
+
+ @Repeated(1)
+ @Repeated(2)
+ private static class MultipleAnnotation {}
+
+ @Container({@Repeated(1)})
+ private static class MultipleAnnotationExplicitSingle {}
+
+ @Repeated(1)
+ @Container({@Repeated(2), @Repeated(3)})
+ private static class MultipleAnnotationOddity {}
+
+ private static class NoAnnotation {}
+
+ private static class InheritedNoNewAnnotation extends SingleAnnotation {}
+
+ @Repeated(2)
+ private static class InheritedSingleWithNewSingleAnnotation extends SingleAnnotation {}
+
+ @Repeated(2)
+ @Repeated(3)
+ private static class InheritedSingleWithNewMultipleAnnotations extends SingleAnnotation {}
+
+ @Repeated(2)
+ private static class InheritedMultipleWithNewSingleAnnotation extends MultipleAnnotation {}
+
+ @Repeated(2)
+ @Repeated(3)
+ private static class InheritedMultipleWithNewMultipleAnnotations extends MultipleAnnotation {}
+
+ public void testIsAnnotationPresent() throws Exception {
+ Class<Repeated> repeated = Repeated.class;
+ assertIsAnnotationPresent(NoAnnotation.class, repeated, false);
+ assertIsAnnotationPresent(SingleAnnotation.class, repeated, true);
+ assertIsAnnotationPresent(MultipleAnnotation.class, repeated, false);
+ assertIsAnnotationPresent(MultipleAnnotationExplicitSingle.class, repeated, false);
+ assertIsAnnotationPresent(MultipleAnnotationOddity.class, repeated, true);
+ assertIsAnnotationPresent(InheritedNoNewAnnotation.class, repeated, true);
+ assertIsAnnotationPresent(InheritedSingleWithNewSingleAnnotation.class, repeated, true);
+ assertIsAnnotationPresent(InheritedSingleWithNewMultipleAnnotations.class, repeated, true);
+ assertIsAnnotationPresent(InheritedMultipleWithNewSingleAnnotation.class, repeated, true);
+ assertIsAnnotationPresent(InheritedMultipleWithNewMultipleAnnotations.class, repeated,
+ false);
+
+ Class<Container> container = Container.class;
+ assertIsAnnotationPresent(NoAnnotation.class, repeated, false);
+ assertIsAnnotationPresent(SingleAnnotation.class, container, false);
+ assertIsAnnotationPresent(MultipleAnnotation.class, container, true);
+ assertIsAnnotationPresent(MultipleAnnotationExplicitSingle.class, container, true);
+ assertIsAnnotationPresent(MultipleAnnotationOddity.class, container, true);
+ assertIsAnnotationPresent(InheritedNoNewAnnotation.class, container, false);
+ assertIsAnnotationPresent(InheritedSingleWithNewSingleAnnotation.class, container, false);
+ assertIsAnnotationPresent(InheritedSingleWithNewMultipleAnnotations.class, container, true);
+ assertIsAnnotationPresent(InheritedMultipleWithNewSingleAnnotation.class, container, true);
+ assertIsAnnotationPresent(InheritedMultipleWithNewMultipleAnnotations.class, container,
+ true);
+ }
+
+ public void testGetDeclaredAnnotation() throws Exception {
+ Class<Repeated> repeated = Repeated.class;
+ assertGetDeclaredAnnotation(NoAnnotation.class, repeated, null);
+ assertGetDeclaredAnnotation(SingleAnnotation.class, repeated, "@Repeated(1)");
+ assertGetDeclaredAnnotation(MultipleAnnotation.class, repeated, null);
+ assertGetDeclaredAnnotation(MultipleAnnotationExplicitSingle.class, repeated, null);
+ assertGetDeclaredAnnotation(MultipleAnnotationOddity.class, repeated, "@Repeated(1)");
+ assertGetDeclaredAnnotation(InheritedNoNewAnnotation.class, repeated, null);
+ assertGetDeclaredAnnotation(InheritedSingleWithNewSingleAnnotation.class, repeated,
+ "@Repeated(2)");
+ assertGetDeclaredAnnotation(InheritedSingleWithNewMultipleAnnotations.class, repeated,
+ null);
+ assertGetDeclaredAnnotation(InheritedMultipleWithNewSingleAnnotation.class, repeated,
+ "@Repeated(2)");
+ assertGetDeclaredAnnotation(InheritedMultipleWithNewMultipleAnnotations.class, repeated,
+ null);
+
+ Class<Container> container = Container.class;
+ assertGetDeclaredAnnotation(NoAnnotation.class, container, null);
+ assertGetDeclaredAnnotation(SingleAnnotation.class, container, null);
+ assertGetDeclaredAnnotation(MultipleAnnotation.class, container,
+ "@Container({@Repeated(1), @Repeated(2)})");
+ assertGetDeclaredAnnotation(MultipleAnnotationExplicitSingle.class, container,
+ "@Container({@Repeated(1)})");
+ assertGetDeclaredAnnotation(MultipleAnnotationOddity.class, container,
+ "@Container({@Repeated(2), @Repeated(3)})");
+ assertGetDeclaredAnnotation(InheritedNoNewAnnotation.class, container, null);
+ assertGetDeclaredAnnotation(InheritedSingleWithNewSingleAnnotation.class, container, null);
+ assertGetDeclaredAnnotation(InheritedSingleWithNewMultipleAnnotations.class, container,
+ "@Container({@Repeated(2), @Repeated(3)})");
+ assertGetDeclaredAnnotation(InheritedMultipleWithNewSingleAnnotation.class, container,
+ null);
+ assertGetDeclaredAnnotation(InheritedMultipleWithNewMultipleAnnotations.class, container,
+ "@Container({@Repeated(2), @Repeated(3)})");
+ }
+
+ public void testGetDeclaredAnnotationsByType() throws Exception {
+ Class<Repeated> repeated = Repeated.class;
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ NoAnnotation.class, repeated, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ SingleAnnotation.class, repeated, new String[] { "@Repeated(1)" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ MultipleAnnotation.class, repeated, new String[] { "@Repeated(1)", "@Repeated(2)" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ MultipleAnnotationExplicitSingle.class, repeated, new String[] { "@Repeated(1)" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ MultipleAnnotationOddity.class, repeated,
+ new String[] { "@Repeated(1)", "@Repeated(2)", "@Repeated(3)" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedNoNewAnnotation.class, repeated, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedSingleWithNewSingleAnnotation.class, repeated,
+ new String[] { "@Repeated(2)" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedSingleWithNewMultipleAnnotations.class, repeated,
+ new String[] { "@Repeated(2)", "@Repeated(3)" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedMultipleWithNewSingleAnnotation.class, repeated,
+ new String[] { "@Repeated(2)" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedMultipleWithNewMultipleAnnotations.class, repeated,
+ new String[] { "@Repeated(2)", "@Repeated(3)" });
+
+ Class<Container> container = Container.class;
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ NoAnnotation.class, container, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ SingleAnnotation.class, container, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ MultipleAnnotation.class, container,
+ new String[] { "@Container({@Repeated(1), @Repeated(2)})" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ MultipleAnnotationExplicitSingle.class, container,
+ new String[] { "@Container({@Repeated(1)})" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ MultipleAnnotationOddity.class, container,
+ new String[] { "@Container({@Repeated(2), @Repeated(3)})" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedNoNewAnnotation.class, container, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedSingleWithNewSingleAnnotation.class, container, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedSingleWithNewMultipleAnnotations.class, container,
+ new String[] { "@Container({@Repeated(2), @Repeated(3)})" });
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedMultipleWithNewSingleAnnotation.class, container, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ InheritedMultipleWithNewMultipleAnnotations.class, container,
+ new String[] { "@Container({@Repeated(2), @Repeated(3)})" });
+ }
+
+ public void testGetAnnotationsByType() throws Exception {
+ Class<Repeated> repeated = Repeated.class;
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ NoAnnotation.class, repeated, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ SingleAnnotation.class, repeated, new String[] { "@Repeated(1)" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ MultipleAnnotation.class, repeated, new String[] { "@Repeated(1)", "@Repeated(2)" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ MultipleAnnotationExplicitSingle.class, repeated, new String[] { "@Repeated(1)" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ MultipleAnnotationOddity.class, repeated,
+ new String[] { "@Repeated(1)", "@Repeated(2)", "@Repeated(3)" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedNoNewAnnotation.class, repeated, new String[] { "@Repeated(1)" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedSingleWithNewSingleAnnotation.class, repeated,
+ new String[] { "@Repeated(2)" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedSingleWithNewMultipleAnnotations.class, repeated,
+ new String[] { "@Repeated(2)", "@Repeated(3)" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedMultipleWithNewSingleAnnotation.class, repeated,
+ new String[] { "@Repeated(2)" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedMultipleWithNewMultipleAnnotations.class, repeated,
+ new String[] { "@Repeated(2)", "@Repeated(3)" });
+
+ Class<Container> container = Container.class;
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ NoAnnotation.class, container, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ SingleAnnotation.class, container, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ MultipleAnnotation.class, container,
+ new String[] { "@Container({@Repeated(1), @Repeated(2)})" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ MultipleAnnotationExplicitSingle.class, container,
+ new String[] { "@Container({@Repeated(1)})" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ MultipleAnnotationOddity.class, container,
+ new String[] { "@Container({@Repeated(2), @Repeated(3)})" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedNoNewAnnotation.class, container, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedSingleWithNewSingleAnnotation.class, container, EXPECT_EMPTY);
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedSingleWithNewMultipleAnnotations.class, container,
+ new String[] { "@Container({@Repeated(2), @Repeated(3)})" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedMultipleWithNewSingleAnnotation.class, container,
+ new String[] { "@Container({@Repeated(1), @Repeated(2)})" });
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ InheritedMultipleWithNewMultipleAnnotations.class, container,
+ new String[] { "@Container({@Repeated(2), @Repeated(3)})" });
+ }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/ConstructorTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/ConstructorTest.java
new file mode 100644
index 0000000000..828b6016f2
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/ConstructorTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationA;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationC;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
+
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.checkAnnotatedElementPresentMethods;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertGetDeclaredAnnotation;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertIsAnnotationPresent;
+
+public class ConstructorTest extends TestCase {
+
+ private static class Type {
+ @AnnotationA
+ @AnnotationC
+ public Type() {}
+ }
+
+ public void testConstructorAnnotations() throws Exception {
+ Constructor<Type> constructor = Type.class.getConstructor();
+ checkAnnotatedElementPresentMethods(constructor, AnnotationA.class, AnnotationC.class);
+ }
+
+ // A class with multiple constructors that differ by their argument count.
+ private static class AnnotatedClass {
+ @Repeated(1)
+ public AnnotatedClass() {}
+
+ @Repeated(1)
+ @Repeated(2)
+ public AnnotatedClass(int a) {}
+
+ @Container({@Repeated(1)})
+ public AnnotatedClass(int a, int b) {}
+
+ @Repeated(1)
+ @Container({@Repeated(2), @Repeated(3)})
+ public AnnotatedClass(int a, int b, int c) {}
+
+ public AnnotatedClass(int a, int b, int c, int d) {}
+ }
+
+ // Tests for isAnnotationPresent and getDeclaredAnnotation.
+ public void testDeclaredAnnotation() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ Class<? extends Annotation> repeated = Repeated.class;
+ checkDeclaredAnnotation(c, 4, repeated, null);
+ checkDeclaredAnnotation(c, 3, repeated, "@Repeated(1)");
+ checkDeclaredAnnotation(c, 2, repeated, null);
+ checkDeclaredAnnotation(c, 1, repeated, null);
+ checkDeclaredAnnotation(c, 0, repeated, "@Repeated(1)");
+
+ Class<? extends Annotation> container = Container.class;
+ checkDeclaredAnnotation(c, 4, container, null);
+ checkDeclaredAnnotation(c, 3, container, "@Container({@Repeated(2), @Repeated(3)})");
+ checkDeclaredAnnotation(c, 2, container, "@Container({@Repeated(1)})");
+ checkDeclaredAnnotation(c, 1, container, "@Container({@Repeated(1), @Repeated(2)})");
+ checkDeclaredAnnotation(c, 0, container, null);
+ }
+
+ private static void checkDeclaredAnnotation(Class<?> c, int constructorArgCount,
+ Class<? extends Annotation> annotationType,
+ String expectedAnnotationString) throws Exception {
+ Constructor constructor = getConstructor(c, constructorArgCount);
+
+ // isAnnotationPresent
+ assertIsAnnotationPresent(constructor, annotationType,
+ expectedAnnotationString != null);
+
+ // getDeclaredAnnotation
+ assertGetDeclaredAnnotation(constructor, annotationType, expectedAnnotationString);
+ }
+
+ public void testGetDeclaredAnnotationsByType() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ Class<? extends Annotation> repeated = Repeated.class;
+ assertGetDeclaredAnnotationsByType(c, 4, repeated, EXPECT_EMPTY);
+ assertGetDeclaredAnnotationsByType(c, 3, repeated,
+ "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+ assertGetDeclaredAnnotationsByType(c, 2, repeated, "@Repeated(1)");
+ assertGetDeclaredAnnotationsByType(c, 1, repeated, "@Repeated(1)", "@Repeated(2)");
+ assertGetDeclaredAnnotationsByType(c, 0, repeated, "@Repeated(1)");
+
+ Class<? extends Annotation> container = Container.class;
+ assertGetDeclaredAnnotationsByType(c, 4, container, EXPECT_EMPTY);
+ assertGetDeclaredAnnotationsByType(c, 3, container,
+ "@Container({@Repeated(2), @Repeated(3)})");
+ assertGetDeclaredAnnotationsByType(c, 2, container, "@Container({@Repeated(1)})");
+ assertGetDeclaredAnnotationsByType(c, 1, container,
+ "@Container({@Repeated(1), @Repeated(2)})");
+ assertGetDeclaredAnnotationsByType(c, 0, container, EXPECT_EMPTY);
+ }
+
+ private static void assertGetDeclaredAnnotationsByType(Class<?> c, int constructorArgCount,
+ Class<? extends Annotation> annotationType,
+ String... expectedAnnotationStrings) throws Exception {
+ Constructor<?> constructor = getConstructor(c, constructorArgCount);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ constructor, annotationType, expectedAnnotationStrings);
+ }
+
+ public void testGetAnnotationsByType() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ Class<? extends Annotation> repeated = Repeated.class;
+ assertGetAnnotationsByType(c, 4, repeated, EXPECT_EMPTY);
+ assertGetAnnotationsByType(c, 3, repeated, "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+ assertGetAnnotationsByType(c, 2, repeated, "@Repeated(1)");
+ assertGetAnnotationsByType(c, 1, repeated, "@Repeated(1)", "@Repeated(2)");
+ assertGetAnnotationsByType(c, 0, repeated, "@Repeated(1)");
+
+ Class<? extends Annotation> container = Container.class;
+ assertGetAnnotationsByType(c, 4, container, EXPECT_EMPTY);
+ assertGetAnnotationsByType(c, 3, container, "@Container({@Repeated(2), @Repeated(3)})");
+ assertGetAnnotationsByType(c, 2, container, "@Container({@Repeated(1)})");
+ assertGetAnnotationsByType(c, 1, container, "@Container({@Repeated(1), @Repeated(2)})");
+ assertGetAnnotationsByType(c, 0, container, EXPECT_EMPTY);
+ }
+
+ private static void assertGetAnnotationsByType(Class<?> c, int constructorArgCount,
+ Class<? extends Annotation> annotationType,
+ String... expectedAnnotationStrings) throws Exception {
+ Constructor<?> constructor = getConstructor(c, constructorArgCount);
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ constructor, annotationType, expectedAnnotationStrings);
+ }
+
+ private static Constructor<?> getConstructor(Class<?> c, int constructorArgCount)
+ throws NoSuchMethodException {
+
+ Class<?>[] args = new Class[constructorArgCount];
+ for (int i = 0; i < constructorArgCount; i++) {
+ args[i] = Integer.TYPE;
+ }
+ return c.getDeclaredConstructor(args);
+ }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/FieldTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/FieldTest.java
new file mode 100644
index 0000000000..8ab7d8ea05
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/FieldTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationA;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationD;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
+
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.checkAnnotatedElementPresentMethods;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertGetDeclaredAnnotation;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertIsAnnotationPresent;
+
+public class FieldTest extends TestCase {
+
+ private static class Type {
+ @AnnotationA
+ @AnnotationD
+ public String field;
+ }
+
+ public void testFieldAnnotations() throws Exception {
+ Field field = Type.class.getField("field");
+ checkAnnotatedElementPresentMethods(field, AnnotationA.class, AnnotationD.class);
+ }
+
+ private static class AnnotatedClass {
+ @Repeated(1)
+ private Object singleAnnotation;
+
+ @Repeated(1)
+ @Repeated(2)
+ private Object multipleAnnotation;
+
+ @Container({@Repeated(1)})
+ private Object multipleAnnotationExplicitSingle;
+
+ @Repeated(1)
+ @Container({@Repeated(2), @Repeated(3)})
+ private Object multipleAnnotationOddity;
+
+ private Object noAnnotation;
+ }
+
+ // Tests for isAnnotationPresent and getDeclaredAnnotation.
+ public void testDeclaredAnnotation() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ Class<? extends Annotation> repeated = Repeated.class;
+ checkDeclaredAnnotation(c, "noAnnotation", repeated, null);
+ checkDeclaredAnnotation(c, "multipleAnnotationOddity", repeated, "@Repeated(1)");
+ checkDeclaredAnnotation(c, "multipleAnnotationExplicitSingle", repeated, null);
+ checkDeclaredAnnotation(c, "multipleAnnotation", repeated, null);
+ checkDeclaredAnnotation(c, "singleAnnotation", repeated, "@Repeated(1)");
+
+ Class<? extends Annotation> container = Container.class;
+ checkDeclaredAnnotation(c, "noAnnotation", container, null);
+ checkDeclaredAnnotation(c, "multipleAnnotationOddity", container,
+ "@Container({@Repeated(2), @Repeated(3)})");
+ checkDeclaredAnnotation(c, "multipleAnnotationExplicitSingle", container,
+ "@Container({@Repeated(1)})");
+ checkDeclaredAnnotation(c, "multipleAnnotation", container,
+ "@Container({@Repeated(1), @Repeated(2)})");
+ checkDeclaredAnnotation(c, "singleAnnotation", container, null);
+ }
+
+ private static void checkDeclaredAnnotation(
+ Class<?> c, String fieldName, Class<? extends Annotation> annotationType,
+ String expectedAnnotationString) throws Exception {
+ Field field = c.getDeclaredField(fieldName);
+
+ // isAnnotationPresent
+ assertIsAnnotationPresent(field, annotationType, expectedAnnotationString != null);
+
+ // getDeclaredAnnotation
+ assertGetDeclaredAnnotation(field, annotationType, expectedAnnotationString);
+ }
+
+ public void testGetDeclaredAnnotationsByType() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ Class<? extends Annotation> repeated = Repeated.class;
+ assertGetDeclaredAnnotationsByType(c, repeated, "noAnnotation", EXPECT_EMPTY);
+ assertGetDeclaredAnnotationsByType(c, repeated, "multipleAnnotationOddity",
+ "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+ assertGetDeclaredAnnotationsByType(c, repeated, "multipleAnnotationExplicitSingle",
+ "@Repeated(1)");
+ assertGetDeclaredAnnotationsByType(c, repeated, "multipleAnnotation",
+ "@Repeated(1)", "@Repeated(2)");
+ assertGetDeclaredAnnotationsByType(c, repeated, "singleAnnotation", "@Repeated(1)");
+
+ Class<? extends Annotation> container = Container.class;
+ assertGetDeclaredAnnotationsByType(c, container, "noAnnotation", EXPECT_EMPTY);
+ assertGetDeclaredAnnotationsByType(c, container, "multipleAnnotationOddity",
+ "@Container({@Repeated(2), @Repeated(3)})");
+ assertGetDeclaredAnnotationsByType(c, container, "multipleAnnotationExplicitSingle",
+ "@Container({@Repeated(1)})");
+ assertGetDeclaredAnnotationsByType(c, container, "multipleAnnotation",
+ "@Container({@Repeated(1), @Repeated(2)})");
+ assertGetDeclaredAnnotationsByType(c, container, "singleAnnotation", EXPECT_EMPTY);
+ }
+
+ private static void assertGetDeclaredAnnotationsByType(
+ Class<?> c, Class<? extends Annotation> annotationType, String fieldName,
+ String... expectedAnnotationStrings) throws Exception {
+ Field field = c.getDeclaredField(fieldName);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ field, annotationType, expectedAnnotationStrings);
+ }
+
+ public void testGetAnnotationsByType() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ Class<? extends Annotation> repeated = Repeated.class;
+ assertGetAnnotationsByType(c, repeated, "noAnnotation", EXPECT_EMPTY);
+ assertGetAnnotationsByType(c, repeated, "multipleAnnotationOddity",
+ "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+ assertGetAnnotationsByType(c, repeated, "multipleAnnotationExplicitSingle",
+ "@Repeated(1)");
+ assertGetAnnotationsByType(c, repeated, "multipleAnnotation",
+ "@Repeated(1)", "@Repeated(2)");
+ assertGetAnnotationsByType(c, repeated, "singleAnnotation", "@Repeated(1)");
+
+ Class<? extends Annotation> container = Container.class;
+ assertGetAnnotationsByType(c, container, "noAnnotation", EXPECT_EMPTY);
+ assertGetAnnotationsByType(c, container, "multipleAnnotationOddity",
+ "@Container({@Repeated(2), @Repeated(3)})");
+ assertGetAnnotationsByType(c, container, "multipleAnnotationExplicitSingle",
+ "@Container({@Repeated(1)})");
+ assertGetAnnotationsByType(c, container, "multipleAnnotation",
+ "@Container({@Repeated(1), @Repeated(2)})");
+ assertGetAnnotationsByType(c, container, "singleAnnotation", EXPECT_EMPTY);
+ }
+
+ private static void assertGetAnnotationsByType(
+ Class<?> c, Class<? extends Annotation> annotationType,
+ String fieldName, String... expectedAnnotationStrings) throws Exception {
+ Field field = c.getDeclaredField(fieldName);
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ field, annotationType, expectedAnnotationStrings);
+ }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/MethodTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/MethodTest.java
new file mode 100644
index 0000000000..c732a9d531
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/MethodTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationB;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationC;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
+
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.checkAnnotatedElementPresentMethods;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertGetDeclaredAnnotation;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertIsAnnotationPresent;
+
+public class MethodTest extends TestCase {
+
+ private static class Type {
+ @AnnotationB
+ @AnnotationC
+ public void method(String parameter1, String parameter2) {}
+ }
+
+ public void testMethodAnnotations() throws Exception {
+ Method method = Type.class.getMethod("method", String.class, String.class);
+ checkAnnotatedElementPresentMethods(method, AnnotationB.class, AnnotationC.class);
+ }
+
+ private static class AnnotatedClass {
+ @Repeated(1)
+ public void singleAnnotation() {}
+
+ @Repeated(1)
+ @Repeated(2)
+ public void multipleAnnotation() {}
+
+ @Container({@Repeated(1)})
+ public void multipleAnnotationExplicitSingle() {}
+
+ @Repeated(1)
+ @Container({@Repeated(2), @Repeated(3)})
+ public void multipleAnnotationOddity() {}
+
+ public void noAnnotation() {}
+ }
+
+ // Tests for isAnnotationPresent and getDeclaredAnnotation.
+ public void testDeclaredAnnotation() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ Class<? extends Annotation> repeated = Repeated.class;
+ checkDeclaredAnnotation(c, "noAnnotation", repeated, null);
+ checkDeclaredAnnotation(c, "multipleAnnotationOddity", repeated, "@Repeated(1)");
+ checkDeclaredAnnotation(c, "multipleAnnotationExplicitSingle", repeated, null);
+ checkDeclaredAnnotation(c, "multipleAnnotation", repeated, null);
+ checkDeclaredAnnotation(c, "singleAnnotation", repeated, "@Repeated(1)");
+
+ Class<? extends Annotation> container = Container.class;
+ checkDeclaredAnnotation(c, "noAnnotation", container, null);
+ checkDeclaredAnnotation(c, "multipleAnnotationOddity", container,
+ "@Container({@Repeated(2), @Repeated(3)})");
+ checkDeclaredAnnotation(c, "multipleAnnotationExplicitSingle", container,
+ "@Container({@Repeated(1)})");
+ checkDeclaredAnnotation(c, "multipleAnnotation", container,
+ "@Container({@Repeated(1), @Repeated(2)})");
+ checkDeclaredAnnotation(c, "singleAnnotation", container, null);
+ }
+
+ private static void checkDeclaredAnnotation(
+ Class<?> c, String methodName, Class<? extends Annotation> annotationType,
+ String expectedAnnotationString) throws Exception {
+ Method method = c.getDeclaredMethod(methodName);
+
+ // isAnnotationPresent
+ assertIsAnnotationPresent(method, annotationType, expectedAnnotationString != null);
+
+ // getDeclaredAnnotation
+ assertGetDeclaredAnnotation(method, annotationType, expectedAnnotationString);
+ }
+
+ public void testGetDeclaredAnnotationsByType() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ Class<? extends Annotation> repeated = Repeated.class;
+ assertGetDeclaredAnnotationsByType(c, repeated, "noAnnotation", EXPECT_EMPTY);
+ assertGetDeclaredAnnotationsByType(c, repeated, "multipleAnnotationOddity",
+ "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+ assertGetDeclaredAnnotationsByType(c, repeated, "multipleAnnotationExplicitSingle",
+ "@Repeated(1)");
+ assertGetDeclaredAnnotationsByType(c, repeated, "multipleAnnotation",
+ "@Repeated(1)", "@Repeated(2)");
+ assertGetDeclaredAnnotationsByType(c, repeated, "singleAnnotation", "@Repeated(1)");
+
+ Class<? extends Annotation> container = Container.class;
+ assertGetDeclaredAnnotationsByType(c, container, "noAnnotation", EXPECT_EMPTY);
+ assertGetDeclaredAnnotationsByType(c, container, "multipleAnnotationOddity",
+ "@Container({@Repeated(2), @Repeated(3)})");
+ assertGetDeclaredAnnotationsByType(c, container, "multipleAnnotationExplicitSingle",
+ "@Container({@Repeated(1)})");
+ assertGetDeclaredAnnotationsByType(c, container, "multipleAnnotation",
+ "@Container({@Repeated(1), @Repeated(2)})");
+ assertGetDeclaredAnnotationsByType(c, container, "singleAnnotation", EXPECT_EMPTY);
+ }
+
+ private static void assertGetDeclaredAnnotationsByType(
+ Class<?> c, Class<? extends Annotation> annotationType, String methodName,
+ String... expectedAnnotationStrings) throws Exception {
+ Method method = c.getDeclaredMethod(methodName);
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ method, annotationType, expectedAnnotationStrings);
+ }
+
+ public void testGetAnnotationsByType() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ Class<? extends Annotation> repeated = Repeated.class;
+ assertGetAnnotationsByType(c, repeated, "noAnnotation", EXPECT_EMPTY);
+ assertGetAnnotationsByType(c, repeated, "multipleAnnotationOddity",
+ "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+ assertGetAnnotationsByType(c, repeated, "multipleAnnotationExplicitSingle",
+ "@Repeated(1)");
+ assertGetAnnotationsByType(c, repeated, "multipleAnnotation",
+ "@Repeated(1)", "@Repeated(2)");
+ assertGetAnnotationsByType(c, repeated, "singleAnnotation", "@Repeated(1)");
+
+ Class<? extends Annotation> container = Container.class;
+ assertGetAnnotationsByType(c, container, "noAnnotation", EXPECT_EMPTY);
+ assertGetAnnotationsByType(c, container, "multipleAnnotationOddity",
+ "@Container({@Repeated(2), @Repeated(3)})");
+ assertGetAnnotationsByType(c, container, "multipleAnnotationExplicitSingle",
+ "@Container({@Repeated(1)})");
+ assertGetAnnotationsByType(c, container, "multipleAnnotation",
+ "@Container({@Repeated(1), @Repeated(2)})");
+ assertGetAnnotationsByType(c, container, "singleAnnotation", EXPECT_EMPTY);
+ }
+
+ private static void assertGetAnnotationsByType(
+ Class<?> c, Class<? extends Annotation> annotationType,
+ String methodName, String... expectedAnnotationStrings) throws Exception {
+ Method method = c.getDeclaredMethod(methodName);
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ method, annotationType, expectedAnnotationStrings);
+ }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/PackageTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/PackageTest.java
new file mode 100644
index 0000000000..f54a64e437
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/PackageTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
+import libcore.java.lang.reflect.annotations.multipleannotation.MultipleAnnotation;
+import libcore.java.lang.reflect.annotations.multipleannotationexplicitsingle.MultipleAnnotationExplicitSingle;
+import libcore.java.lang.reflect.annotations.multipleannotationoddity.MultipleAnnotationOddity;
+import libcore.java.lang.reflect.annotations.noannotation.NoAnnotation;
+import libcore.java.lang.reflect.annotations.singleannotation.SingleAnnotation;
+
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertGetDeclaredAnnotation;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertIsAnnotationPresent;
+
+public class PackageTest extends TestCase {
+
+ // Tests for isAnnotationPresent and getDeclaredAnnotation.
+ public void testDeclaredAnnotation() throws Exception {
+ Class<Repeated> repeated = Repeated.class;
+ checkDeclaredAnnotation(NoAnnotation.class, repeated, null);
+ checkDeclaredAnnotation(SingleAnnotation.class, repeated, "@Repeated(1)");
+ checkDeclaredAnnotation(MultipleAnnotation.class, repeated, null);
+ checkDeclaredAnnotation(MultipleAnnotationExplicitSingle.class, repeated, null);
+ checkDeclaredAnnotation(MultipleAnnotationOddity.class, repeated, "@Repeated(1)");
+
+ Class<Container> container = Container.class;
+ checkDeclaredAnnotation(NoAnnotation.class, container, null);
+ checkDeclaredAnnotation(SingleAnnotation.class, container, null);
+ checkDeclaredAnnotation(MultipleAnnotation.class, container,
+ "@Container({@Repeated(1), @Repeated(2)})");
+ checkDeclaredAnnotation(MultipleAnnotationExplicitSingle.class, container,
+ "@Container({@Repeated(1)})");
+ checkDeclaredAnnotation(MultipleAnnotationOddity.class, container,
+ "@Container({@Repeated(2), @Repeated(3)})");
+ }
+
+ private static void checkDeclaredAnnotation(
+ Class<?> classInPackage, Class<? extends Annotation> annotationType,
+ String expectedAnnotationString) throws Exception {
+
+ Package aPackage = classInPackage.getPackage();
+ // isAnnotationPresent
+ assertIsAnnotationPresent(aPackage, annotationType, expectedAnnotationString != null);
+
+ // getDeclaredAnnotation
+ assertGetDeclaredAnnotation(aPackage, annotationType, expectedAnnotationString);
+ }
+
+ public void testGetDeclaredAnnotationsByType() throws Exception {
+ Class<Repeated> repeated = Repeated.class;
+
+ assertGetDeclaredAnnotationsByType(NoAnnotation.class, repeated, EXPECT_EMPTY);
+ assertGetDeclaredAnnotationsByType(SingleAnnotation.class, repeated,
+ "@Repeated(1)");
+ assertGetDeclaredAnnotationsByType(MultipleAnnotation.class, repeated,
+ "@Repeated(1)", "@Repeated(2)");
+ assertGetDeclaredAnnotationsByType(MultipleAnnotationExplicitSingle.class, repeated,
+ "@Repeated(1)");
+ assertGetDeclaredAnnotationsByType(MultipleAnnotationOddity.class, repeated,
+ "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+
+ Class<Container> container = Container.class;
+ assertGetDeclaredAnnotationsByType(NoAnnotation.class, container, EXPECT_EMPTY);
+ assertGetDeclaredAnnotationsByType(SingleAnnotation.class, container, EXPECT_EMPTY);
+ assertGetDeclaredAnnotationsByType(MultipleAnnotation.class, container,
+ "@Container({@Repeated(1), @Repeated(2)})");
+ assertGetDeclaredAnnotationsByType(MultipleAnnotationExplicitSingle.class, container,
+ "@Container({@Repeated(1)})");
+ assertGetDeclaredAnnotationsByType(MultipleAnnotationOddity.class, container,
+ "@Container({@Repeated(2), @Repeated(3)})");
+ }
+
+ private static void assertGetDeclaredAnnotationsByType(
+ Class<?> classInPackage, Class<? extends Annotation> annotationType,
+ String... expectedAnnotationStrings) throws Exception {
+ Package aPackage = classInPackage.getPackage();
+ AnnotatedElementTestSupport.assertGetDeclaredAnnotationsByType(
+ aPackage, annotationType, expectedAnnotationStrings);
+ }
+
+ public void testGetAnnotationsByType() throws Exception {
+ Class<Repeated> repeated = Repeated.class;
+ assertGetAnnotationsByType(NoAnnotation.class, repeated, EXPECT_EMPTY);
+ assertGetAnnotationsByType(SingleAnnotation.class, repeated, "@Repeated(1)");
+ assertGetAnnotationsByType(MultipleAnnotation.class, repeated,
+ "@Repeated(1)", "@Repeated(2)");
+ assertGetAnnotationsByType(MultipleAnnotationExplicitSingle.class, repeated,
+ "@Repeated(1)");
+ assertGetAnnotationsByType(MultipleAnnotationOddity.class, repeated,
+ "@Repeated(1)", "@Repeated(2)", "@Repeated(3)");
+
+ Class<Container> container = Container.class;
+ assertGetAnnotationsByType(NoAnnotation.class, container, EXPECT_EMPTY);
+ assertGetAnnotationsByType(SingleAnnotation.class, container, EXPECT_EMPTY);
+ assertGetAnnotationsByType(MultipleAnnotation.class, container,
+ "@Container({@Repeated(1), @Repeated(2)})");
+ assertGetAnnotationsByType(MultipleAnnotationExplicitSingle.class, container,
+ "@Container({@Repeated(1)})");
+ assertGetAnnotationsByType(MultipleAnnotationOddity.class, container,
+ "@Container({@Repeated(2), @Repeated(3)})");
+ }
+
+ private static void assertGetAnnotationsByType(Class<?> classInPackage,
+ Class<? extends Annotation> annotationType,
+ String... expectedAnnotationStrings) throws Exception {
+ Package aPackage = classInPackage.getPackage();
+ AnnotatedElementTestSupport.assertGetAnnotationsByType(
+ aPackage, annotationType, expectedAnnotationStrings);
+ }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/ParameterTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/ParameterTest.java
new file mode 100644
index 0000000000..f40ac9f15e
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/ParameterTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations;
+
+import junit.framework.TestCase;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationB;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationC;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.AnnotationD;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
+
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.EXPECT_EMPTY;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.annotationsToTypes;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.assertAnnotationsMatch;
+import static libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.set;
+
+public class ParameterTest extends TestCase {
+ private static class Type {
+ @AnnotationB
+ @AnnotationC
+ public void method(String parameter1, String parameter2) {}
+
+ @AnnotationB
+ @AnnotationC
+ public void parameters(@AnnotationB @AnnotationD String parameter1,
+ @AnnotationC @AnnotationD String parameter2) {}
+ }
+
+ public void testParameterAnnotations() throws Exception {
+ Method method = Type.class.getMethod("method", String.class, String.class);
+ 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]));
+ assertEquals(set(AnnotationC.class, AnnotationD.class),
+ annotationsToTypes(parameterAnnotations[1]));
+ }
+
+ private static class AnnotatedClass {
+ public void singleAnnotation(@Repeated(1) String p0) {}
+
+ public void multipleAnnotation(@Repeated(1) @Repeated(2) String p0) {}
+
+ public void multipleAnnotationExplicitSingle(@Container({@Repeated(1)}) String p0) {}
+
+ public void multipleAnnotationOddity(
+ @Repeated(1) @Container({@Repeated(2), @Repeated(3)}) String p0) {}
+
+ public void noAnnotation(String p0) {}
+ }
+
+ public void testGetParameterAnnotations() throws Exception {
+ Class<?> c = AnnotatedClass.class;
+
+ assertParameter0Annotations(c, "noAnnotation", EXPECT_EMPTY);
+ assertParameter0Annotations(c, "multipleAnnotationOddity",
+ "@Repeated(1)", "@Container({@Repeated(2), @Repeated(3)})");
+ assertParameter0Annotations(c, "multipleAnnotationExplicitSingle",
+ "@Container({@Repeated(1)})");
+ assertParameter0Annotations(c, "multipleAnnotation",
+ "@Container({@Repeated(1), @Repeated(2)})");
+ assertParameter0Annotations(c, "singleAnnotation",
+ "@Repeated(1)");
+ }
+
+ private static void assertParameter0Annotations(
+ Class<?> c, String methodName, String... expectedAnnotationStrings) throws Exception {
+ Annotation[][] allAnnotations =
+ c.getDeclaredMethod(methodName, String.class).getParameterAnnotations();
+ final int expectedParameterCount = 1;
+ assertEquals(expectedParameterCount, allAnnotations.length);
+
+ Annotation[] p0Annotations = allAnnotations[0];
+ assertAnnotationsMatch(p0Annotations, expectedAnnotationStrings);
+ }
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotation/MultipleAnnotation.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotation/MultipleAnnotation.java
new file mode 100644
index 0000000000..d3e77ae479
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotation/MultipleAnnotation.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations.multipleannotation;
+
+import libcore.java.lang.reflect.annotations.PackageTest;
+
+/**
+ * This class exists so that (after it is loaded) the ClassLoader will be aware of the associated
+ * package and return a {@link Package} object. See {@link PackageTest}.
+ */
+public class MultipleAnnotation {
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotation/package-info.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotation/package-info.java
new file mode 100644
index 0000000000..1ab457ecf7
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotation/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/**
+ * See {@link libcore.java.lang.reflect.annotations.PackageTest}.
+ */
+@Repeated(1)
+@Repeated(2)
+package libcore.java.lang.reflect.annotations.multipleannotation;
+
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationexplicitsingle/MultipleAnnotationExplicitSingle.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationexplicitsingle/MultipleAnnotationExplicitSingle.java
new file mode 100644
index 0000000000..d14ff198b2
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationexplicitsingle/MultipleAnnotationExplicitSingle.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations.multipleannotationexplicitsingle;
+
+import libcore.java.lang.reflect.annotations.PackageTest;
+
+/**
+ * This class exists so that (after it is loaded) the ClassLoader will be aware of the associated
+ * package and return a {@link Package} object. See {@link PackageTest}.
+ */
+public class MultipleAnnotationExplicitSingle {
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationexplicitsingle/package-info.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationexplicitsingle/package-info.java
new file mode 100644
index 0000000000..cf41d87bbb
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationexplicitsingle/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/**
+ * See {@link libcore.java.lang.reflect.annotations.PackageTest}.
+ */
+@Container({@Repeated(1)})
+package libcore.java.lang.reflect.annotations.multipleannotationexplicitsingle;
+
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated; \ No newline at end of file
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationoddity/MultipleAnnotationOddity.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationoddity/MultipleAnnotationOddity.java
new file mode 100644
index 0000000000..b85f50ff8a
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationoddity/MultipleAnnotationOddity.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations.multipleannotationoddity;
+
+import libcore.java.lang.reflect.annotations.PackageTest;
+
+/**
+ * This class exists so that (after it is loaded) the ClassLoader will be aware of the associated
+ * package and return a {@link Package} object. See {@link PackageTest}.
+ */
+public class MultipleAnnotationOddity {
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationoddity/package-info.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationoddity/package-info.java
new file mode 100644
index 0000000000..afbd99eda8
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/multipleannotationoddity/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/**
+ * See {@link libcore.java.lang.reflect.annotations.PackageTest}.
+ */
+@Repeated(1)
+@Container({@Repeated(2), @Repeated(3)})
+package libcore.java.lang.reflect.annotations.multipleannotationoddity;
+
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Container;
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated; \ No newline at end of file
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/noannotation/NoAnnotation.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/noannotation/NoAnnotation.java
new file mode 100644
index 0000000000..e7fd957565
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/noannotation/NoAnnotation.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations.noannotation;
+
+import libcore.java.lang.reflect.annotations.PackageTest;
+
+/**
+ * This class exists so that (after it is loaded) the ClassLoader will be aware of the associated
+ * package and return a {@link Package} object. See {@link PackageTest}.
+ */
+public class NoAnnotation {
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/package-info.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/noannotation/package-info.java
index 1a84c2ef91..2942f1a740 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/package-info.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/noannotation/package-info.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//Used by AnnotationsTest.
-@AnnotationsTest.RepeatableAnnotation
-@AnnotationsTest.RepeatableAnnotation
-package libcore.java.lang.reflect; \ No newline at end of file
+/**
+ * See {@link libcore.java.lang.reflect.annotations.PackageTest}.
+ */
+package libcore.java.lang.reflect.annotations.noannotation; \ No newline at end of file
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/singleannotation/SingleAnnotation.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/singleannotation/SingleAnnotation.java
new file mode 100644
index 0000000000..453b2996e5
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/singleannotation/SingleAnnotation.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 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.reflect.annotations.singleannotation;
+
+import libcore.java.lang.reflect.annotations.PackageTest;
+
+/**
+ * This class exists so that (after it is loaded) the ClassLoader will be aware of the associated
+ * package and return a {@link Package} object. See {@link PackageTest}.
+ */
+public class SingleAnnotation {
+}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/singleannotation/package-info.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/singleannotation/package-info.java
new file mode 100644
index 0000000000..3686f80799
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/singleannotation/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/**
+ * See {@link libcore.java.lang.reflect.annotations.PackageTest}.
+ */
+@Repeated(1)
+package libcore.java.lang.reflect.annotations.singleannotation;
+
+import libcore.java.lang.reflect.annotations.AnnotatedElementTestSupport.Repeated;
+