1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8162817
  27  * @summary Test of toString on normal annotations
  28  */
  29 
  30 import java.lang.annotation.*;
  31 import java.lang.reflect.*;
  32 import java.util.*;
  33 
  34 /**
  35  * The expected string values are stored in @ExpectedString
  36  * annotations. The essence of the test is comparing the toString()
  37  * result of annotations to the corresponding ExpectedString.value().
  38  */
  39 
  40 public class AnnotationToStringTest {
  41     public static void main(String... args) throws Exception {
  42         int failures = 0;
  43 
  44         failures += check(PrimHost.class.getAnnotation(ExpectedString.class).value(),
  45                           PrimHost.class.getAnnotation(MostlyPrimitive.class).toString());
  46         failures += classyTest();
  47         failures += arrayAnnotationTest();
  48 
  49         if (failures > 0)
  50             throw new RuntimeException(failures + " failures");
  51     }
  52 
  53     private static int check(String expected, String actual) {
  54         if (!expected.equals(actual)) {
  55             System.err.printf("ERROR: Expected ''%s'';%ngot             ''%s''.\n",
  56                               expected, actual);
  57             return 1;
  58         } else
  59             return 0;
  60     }
  61 
  62     @ExpectedString(
  63         "@MostlyPrimitive(c0='a', "+
  64         "c1='\\'', " +
  65         "i0=1, " +
  66         "i1=2, " +
  67         "f0=1.0f, " +
  68         "f1=0.0f/0.0f, " +
  69         "d0=0.0, " +
  70         "d1=1.0/0.0, " +
  71         "l0=5, " +
  72         "l1=9223372036854775807L, " +
  73         "s0=\"Hello world.\", " +
  74         "s1=\"a\\\"b\", " +
  75         "class0=Obj[].class)")
  76     @MostlyPrimitive(
  77         c0='a',
  78         c1='\'',
  79         i0=1,
  80         i1=2,
  81         f0=1.0f,
  82         f1=Float.NaN,
  83         d0=0.0,
  84         d1=2.0/0.0,
  85         l0=5,
  86         l1=Long.MAX_VALUE,
  87         s0="Hello world.",
  88         s1="a\"b",
  89         class0=Obj[].class
  90     )
  91     static class PrimHost{}
  92 
  93     private static int classyTest() {
  94         int failures = 0;
  95         for (Field f : AnnotationHost.class.getFields()) {
  96             Annotation a = f.getAnnotation(Classy.class);
  97             System.out.println(a);
  98             failures += check(f.getAnnotation(ExpectedString.class).value(),
  99                               a.toString());
 100         }
 101         return failures;
 102     }
 103 
 104     static class AnnotationHost {
 105         @ExpectedString(
 106        "@Classy(value=Obj.class)")
 107         @Classy(value=Obj.class)
 108         public int f0;
 109 
 110         @ExpectedString(
 111        "@Classy(value=Obj[].class)")
 112         @Classy(value=Obj[].class)
 113         public int f1;
 114 
 115         @ExpectedString(
 116        "@Classy(value=Obj[][].class)")
 117         @Classy(value=Obj[][].class)
 118         public int f2;
 119 
 120         @ExpectedString(
 121        "@Classy(value=Obj[][][].class)")
 122         @Classy(value=Obj[][][].class)
 123         public int f3;
 124 
 125         @ExpectedString(
 126        "@Classy(value=int.class)")
 127         @Classy(value=int.class)
 128         public int f4;
 129 
 130         @ExpectedString(
 131        "@Classy(value=int[][][].class)")
 132         @Classy(value=int[][][].class)
 133         public int f5;
 134     }
 135 
 136     /**
 137      * Each field should have two annotations, the first being
 138      * @ExpectedString and the second the annotation under test.
 139      */
 140     private static int arrayAnnotationTest() {
 141         int failures = 0;
 142         for (Field f : ArrayAnnotationHost.class.getFields()) {
 143             Annotation[] annotations = f.getAnnotations();
 144             System.out.println(annotations[1]);
 145             failures += check(((ExpectedString)annotations[0]).value(),
 146                               annotations[1].toString());
 147         }
 148         return failures;
 149     }
 150 
 151     static class ArrayAnnotationHost {
 152         @ExpectedString(
 153        "@BooleanArray(value={true, false, true})")
 154         @BooleanArray(value={true, false, true})
 155         public boolean[]   f0;
 156 
 157         @ExpectedString(
 158        "@FloatArray(value={3.0f, 4.0f, 0.0f/0.0f, -1.0f/0.0f, 1.0f/0.0f})")
 159         @FloatArray(value={3.0f, 4.0f, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY})
 160         public float[]     f1;
 161 
 162         @ExpectedString(
 163        "@DoubleArray(value={1.0, 2.0, 0.0/0.0, 1.0/0.0, -1.0/0.0})")
 164         @DoubleArray(value={1.0, 2.0, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,})
 165         public double[]    f2;
 166 
 167         @ExpectedString(
 168        "@ByteArray(value={10, 11, 12})")
 169         @ByteArray(value={10, 11, 12})
 170         public byte[]      f3;
 171 
 172         @ExpectedString(
 173        "@ShortArray(value={0, 4, 5})")
 174         @ShortArray(value={0, 4, 5})
 175         public short[]     f4;
 176 
 177         @ExpectedString(
 178        "@CharArray(value={'a', 'b', 'c', '\\''})")
 179         @CharArray(value={'a', 'b', 'c', '\''})
 180         public char[]      f5;
 181 
 182         @ExpectedString(
 183        "@IntArray(value={1})")
 184         @IntArray(value={1})
 185         public int[]       f6;
 186 
 187         @ExpectedString(
 188        "@LongArray(value={-2147483647, 2147483648L, 9223372036854775807L})")
 189         @LongArray(value={-Integer.MAX_VALUE, Integer.MAX_VALUE+1L, Long.MAX_VALUE})
 190         public long[]      f7;
 191 
 192         @ExpectedString(
 193        "@StringArray(value={\"A\", \"B\", \"C\", \"\\\"Quote\\\"\"})")
 194         @StringArray(value={"A", "B", "C", "\"Quote\""})
 195         public String[]    f8;
 196 
 197         @ExpectedString(
 198        "@ClassArray(value={int.class, Obj[].class})")
 199         @ClassArray(value={int.class, Obj[].class})
 200         public Class<?>[]  f9;
 201 
 202         @ExpectedString(
 203        "@EnumArray(value={SOURCE})")
 204         @EnumArray(value={RetentionPolicy.SOURCE})
 205         public RetentionPolicy[]  f10;
 206     }
 207 }
 208 
 209 // ------------ Supporting types ------------
 210 
 211 class Obj {}
 212 
 213 @Retention(RetentionPolicy.RUNTIME)
 214 @interface ExpectedString {
 215     String value();
 216 }
 217 
 218 @Retention(RetentionPolicy.RUNTIME)
 219 @interface Classy {
 220     Class<?> value();
 221 }
 222 
 223 @Retention(RetentionPolicy.RUNTIME)
 224 @interface BooleanArray {
 225     boolean[] value();
 226 }
 227 
 228 @Retention(RetentionPolicy.RUNTIME)
 229 @interface FloatArray {
 230     float[] value();
 231 }
 232 
 233 @Retention(RetentionPolicy.RUNTIME)
 234 @interface DoubleArray {
 235     double[] value();
 236 }
 237 
 238 @Retention(RetentionPolicy.RUNTIME)
 239 @interface ByteArray {
 240     byte[] value();
 241 }
 242 
 243 @Retention(RetentionPolicy.RUNTIME)
 244 @interface ShortArray {
 245     short[] value();
 246 }
 247 
 248 @Retention(RetentionPolicy.RUNTIME)
 249 @interface CharArray {
 250     char[] value();
 251 }
 252 
 253 @Retention(RetentionPolicy.RUNTIME)
 254 @interface IntArray {
 255     int[] value();
 256 }
 257 
 258 @Retention(RetentionPolicy.RUNTIME)
 259 @interface LongArray {
 260     long[] value();
 261 }
 262 
 263 @Retention(RetentionPolicy.RUNTIME)
 264 @interface ClassArray {
 265     Class<?>[] value() default {int.class, Obj[].class};
 266 }
 267 
 268 @Retention(RetentionPolicy.RUNTIME)
 269 @interface StringArray {
 270     String[] value();
 271 }
 272 
 273 @Retention(RetentionPolicy.RUNTIME)
 274 @interface EnumArray {
 275     RetentionPolicy[] value();
 276 }
 277 
 278 @Retention(RetentionPolicy.RUNTIME)
 279 @interface MostlyPrimitive {
 280     char   c0();
 281     char   c1();
 282     int    i0();
 283     int    i1();
 284     float  f0();
 285     float  f1();
 286     double d0();
 287     double d1();
 288     long   l0();
 289     long   l1();
 290     String s0();
 291     String s1();
 292     Class<?> class0();
 293 }