< prev index next >

test/jdk/java/lang/annotation/typeAnnotations/TestObjectMethods.java

Print this page

        

*** 21,41 **** * questions. */ /* * @test ! * @bug 8058202 * @summary Test java.lang.Object methods on AnnotatedType objects. */ import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; /** * Test toString, equals, and hashCode on various AnnotatedType objects. */ public class TestObjectMethods { private static int errors = 0; /* * There are various subtypes of AnnotatedType implementations: --- 21,43 ---- * questions. */ /* * @test ! * @bug 8058202 8212081 * @summary Test java.lang.Object methods on AnnotatedType objects. */ import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; + import java.util.regex.*; /** * Test toString, equals, and hashCode on various AnnotatedType objects. */ + public class TestObjectMethods { private static int errors = 0; /* * There are various subtypes of AnnotatedType implementations:
*** 59,70 **** for (Class<?> clazz : testClasses) { testEqualsReflexivity(clazz); testEquals(clazz); } ! testToString(TypeHost.class, false); ! testToString(AnnotatedTypeHost.class, true); testAnnotationsMatterForEquals(TypeHost.class, AnnotatedTypeHost.class); testGetAnnotations(TypeHost.class, false); testGetAnnotations(AnnotatedTypeHost.class, true); --- 61,72 ---- for (Class<?> clazz : testClasses) { testEqualsReflexivity(clazz); testEquals(clazz); } ! testToString(TypeHost.class); ! testToString(AnnotatedTypeHost.class); testAnnotationsMatterForEquals(TypeHost.class, AnnotatedTypeHost.class); testGetAnnotations(TypeHost.class, false); testGetAnnotations(AnnotatedTypeHost.class, true);
*** 78,110 **** /* * For non-array types, verify toString version of the annotated * type ends with the same string as the generic type. */ ! static void testToString(Class<?> clazz, boolean leadingAnnotations) { System.err.println("Testing toString on methods of class " + clazz.getName()); Method[] methods = clazz.getDeclaredMethods(); for (Method m : methods) { AnnotatedType annotType = m.getAnnotatedReturnType(); String annotTypeString = annotType.toString(); Type type = m.getGenericReturnType(); ! String typeString = type.toString(); boolean isArray = annotType instanceof AnnotatedArrayType; boolean isVoid = "void".equals(typeString); boolean valid; ! if (!isArray) { ! if (leadingAnnotations && !isVoid) { ! valid = ! annotTypeString.endsWith(typeString) && ! !annotTypeString.startsWith(typeString); ! } else { valid = annotTypeString.equals(typeString); ! } ! } else { // Find final non-array component type and gets its name. typeString = null; AnnotatedType componentType = annotType; while (componentType instanceof AnnotatedArrayType) { --- 80,128 ---- /* * For non-array types, verify toString version of the annotated * type ends with the same string as the generic type. */ ! static void testToString(Class<?> clazz) { System.err.println("Testing toString on methods of class " + clazz.getName()); Method[] methods = clazz.getDeclaredMethods(); for (Method m : methods) { + // Expected information about the type annotations stored + // in a *declaration* annotation. + AnnotTypeInfo annotTypeInfo = m.getAnnotation(AnnotTypeInfo.class); + int expectedAnnotCount = annotTypeInfo.count(); + Relation relation = annotTypeInfo.relation(); + AnnotatedType annotType = m.getAnnotatedReturnType(); String annotTypeString = annotType.toString(); Type type = m.getGenericReturnType(); ! String typeString = (type instanceof Class) ? ! type.getTypeName() : ! type.toString(); boolean isArray = annotType instanceof AnnotatedArrayType; boolean isVoid = "void".equals(typeString); boolean valid; ! ! switch(relation) { ! case EQUAL: valid = annotTypeString.equals(typeString); ! break; ! ! case POSTFIX: ! valid = annotTypeString.endsWith(typeString) && ! !annotTypeString.startsWith(typeString); ! break; ! ! case STRIPPED: ! String stripped = annotationRegex.matcher(annotTypeString).replaceAll(""); ! valid = typeString.replace(" ", "").equals(stripped.replace(" ", "")); ! break; ! ! case ARRAY: // Find final non-array component type and gets its name. typeString = null; AnnotatedType componentType = annotType; while (componentType instanceof AnnotatedArrayType) {
*** 112,121 **** --- 130,166 ---- componentType = annotatedArrayType.getAnnotatedGenericComponentType(); } String componentName = componentType.getType().getTypeName(); valid = annotTypeString.contains(componentName); + break; + + default: + throw new AssertionError("Shouldn't be reached"); + } + + // Verify number of type annotations matches expected value + Matcher matcher = annotationRegex.matcher(annotTypeString); + if (expectedAnnotCount > 0) { + int i = expectedAnnotCount; + int annotCount = 0; + while (i > 0) { + boolean found = matcher.find(); + if (found) { + i--; + annotCount++; + } else { + errors++; + System.err.println("\tExpected annotation not found: " + annotTypeString); + } + } + } + + boolean found = matcher.find(); + if (found) { + errors++; + System.err.println("\tAnnotation found unexpectedly: " + annotTypeString); } if (!valid) { errors++; System.err.println(typeString + "\n" + annotTypeString +
*** 123,132 **** --- 168,179 ---- "\n\n"); } } } + private static final Pattern annotationRegex = Pattern.compile("@TestObjectMethods\\$AnnotType\\(value=(\\p{Digit})+\\)"); + static void testGetAnnotations(Class<?> clazz, boolean annotationsExpectedOnMethods) { System.err.println("Testing getAnnotations on methods of class " + clazz.getName()); Method[] methods = clazz.getDeclaredMethods(); for (Method m : methods) { Type type = m.getGenericReturnType();
*** 228,238 **** System.err.println("Method " + methodName + " not found."); } } } - static void testWildcards() { System.err.println("Testing wildcards"); // public @AnnotType(10) Set<? extends Number> fooNumberSet() {return null;} // public @AnnotType(11) Set<@AnnotType(13) ? extends Number> fooNumberSet2() {return null;} AnnotatedWildcardType awt1 = extractWildcard("fooNumberSet"); --- 275,284 ----
*** 267,314 **** // the same name and signatures but with the AnnotatedTypeHost // methods having annotations on their return type, where // possible. static class TypeHost<E, F extends Number> { public void fooVoid() {return;} public int foo() {return 0;} public String fooString() {return null;} public int[] fooIntArray() {return null;} public String[] fooStringArray() {return null;} public String [][] fooStringArrayArray() {return null;} public Set<String> fooSetString() {return null;} public E fooE() {return null;} public F fooF() {return null;} public <G> G fooG() {return null;} public Set<? extends Number> fooNumberSet() {return null;} public Set<? extends Integer> fooNumberSet2() {return null;} } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) static @interface AnnotType { int value() default 0; } static class AnnotatedTypeHost<E, F extends Number> { public /*@AnnotType(0)*/ void fooVoid() {return;} // Illegal to annotate void ! public @AnnotType(1) int foo() {return 0;} ! public @AnnotType(2) String fooString() {return null;} public int @AnnotType(3) [] fooIntArray() {return null;} public String @AnnotType(4) [] fooStringArray() {return null;} - public @AnnotType(5) String @AnnotType(0) [] @AnnotType(1) [] fooStringArrayArray() {return null;} ! public @AnnotType(6) Set<String> fooSetString() {return null;} ! public @AnnotType(7) E fooE() {return null;} ! public @AnnotType(8) F fooF() {return null;} ! public @AnnotType(9) <G> G fooG() {return null;} ! public @AnnotType(10) Set<? extends Number> fooNumberSet() {return null;} ! public @AnnotType(11) Set<@AnnotType(13) ? extends Number> fooNumberSet2() {return null;} } } --- 313,462 ---- // the same name and signatures but with the AnnotatedTypeHost // methods having annotations on their return type, where // possible. static class TypeHost<E, F extends Number> { + @AnnotTypeInfo public void fooVoid() {return;} + @AnnotTypeInfo public int foo() {return 0;} + + @AnnotTypeInfo public String fooString() {return null;} + @AnnotTypeInfo public int[] fooIntArray() {return null;} + + @AnnotTypeInfo public String[] fooStringArray() {return null;} + + @AnnotTypeInfo public String [][] fooStringArrayArray() {return null;} + @AnnotTypeInfo public Set<String> fooSetString() {return null;} + + @AnnotTypeInfo + public Set<Number> fooSetNumber() {return null;} + + @AnnotTypeInfo public E fooE() {return null;} + + @AnnotTypeInfo public F fooF() {return null;} + + @AnnotTypeInfo public <G> G fooG() {return null;} + @AnnotTypeInfo public Set<? extends Number> fooNumberSet() {return null;} + + @AnnotTypeInfo public Set<? extends Integer> fooNumberSet2() {return null;} + + @AnnotTypeInfo + public Set<? extends Long> fooNumberSet3() {return null;} } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) static @interface AnnotType { int value() default 0; } + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + static @interface AnnotTypeInfo { + /** + * Expected number of @AnnotType + */ + int count() default 0; + + /** + * Relation to genericString output. + */ + Relation relation() default Relation.EQUAL; + } + + /** + * Expected relationship of toString output of AnnotatedType to + * toGenericString output of underlying type. + */ + static private enum Relation { + EQUAL, + + /** + * The toGenericString output is a postfix of the + * AnnotatedType output; a leading annotation is expected. + */ + POSTFIX, + + /** + * If the annotations are stripped from the AnnotatedType + * output and whitespace adjusted accordingly, it should equal + * the toGenericString output. + */ + STRIPPED, + + /** + * The output of AnnotatedType for arrays would require more + * extensive transformation to map to toGenericString output. + */ + ARRAY; + } + static class AnnotatedTypeHost<E, F extends Number> { + @AnnotTypeInfo public /*@AnnotType(0)*/ void fooVoid() {return;} // Illegal to annotate void ! @AnnotTypeInfo(count =1, relation = Relation.POSTFIX) ! @AnnotType(1) ! public int foo() {return 0;} ! ! @AnnotTypeInfo(count = 1, relation = Relation.POSTFIX) ! @AnnotType(2) ! public String fooString() {return null;} + @AnnotTypeInfo(count = 1, relation = Relation.ARRAY) public int @AnnotType(3) [] fooIntArray() {return null;} + + @AnnotTypeInfo(count = 1, relation = Relation.ARRAY) public String @AnnotType(4) [] fooStringArray() {return null;} ! @AnnotTypeInfo(count = 3, relation = Relation.ARRAY) ! @AnnotType(5) ! public String @AnnotType(0) [] @AnnotType(1) [] fooStringArrayArray() {return null;} ! ! @AnnotTypeInfo(count = 1, relation = Relation.POSTFIX) ! @AnnotType(6) ! public Set<String> fooSetString() {return null;} ! ! @AnnotTypeInfo(count = 2, relation = Relation.STRIPPED) ! @AnnotType(7) ! public Set<@AnnotType(8) Number> fooSetNumber() {return null;} ! ! @AnnotTypeInfo(count = 1, relation = Relation.POSTFIX) ! @AnnotType(9) ! public E fooE() {return null;} ! ! @AnnotTypeInfo(count = 1, relation = Relation.POSTFIX) ! @AnnotType(10) ! public F fooF() {return null;} ! ! @AnnotTypeInfo(count = 1, relation = Relation.POSTFIX) ! @AnnotType(11) ! public <G> G fooG() {return null;} ! ! @AnnotTypeInfo(count = 1, relation = Relation.POSTFIX) ! @AnnotType(12) ! public Set<? extends Number> fooNumberSet() {return null;} ! @AnnotTypeInfo(count = 2, relation = Relation.STRIPPED) ! @AnnotType(13) ! public Set<@AnnotType(14) ? extends Number> fooNumberSet2() {return null;} ! ! @AnnotTypeInfo(count = 2, relation = Relation.STRIPPED) ! @AnnotType(15) ! public Set< ? extends @AnnotType(16) Long> fooNumberSet3() {return null;} } }
< prev index next >