1 /* 2 * Copyright (c) 2016, 2019, 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 8168921 27 * @summary Test of toString on normal annotations 28 */ 29 30 // See also the sibling compile-time test 31 // test/langtools/tools/javac/processing/model/element/AnnotationToStringTest.java 32 33 import java.lang.annotation.*; 34 import java.lang.reflect.*; 35 import java.util.*; 36 37 /** 38 * The expected string values are stored in @ExpectedString 39 * annotations. The essence of the test is comparing the toString() 40 * result of annotations to the corresponding ExpectedString.value(). 41 */ 42 43 public class AnnotationToStringTest { 44 public static void main(String... args) throws Exception { 45 int failures = 0; 46 47 failures += check(PrimHost.class.getAnnotation(ExpectedString.class).value(), 48 PrimHost.class.getAnnotation(MostlyPrimitive.class).toString()); 49 failures += classyTest(); 50 failures += arrayAnnotationTest(); 51 52 if (failures > 0) 53 throw new RuntimeException(failures + " failures"); 54 } 55 56 private static int check(String expected, String actual) { 57 if (!expected.equals(actual)) { 58 System.err.printf("ERROR: Expected ''%s'';%ngot ''%s''.\n", 59 expected, actual); 60 return 1; 61 } else 62 return 0; 63 } 64 65 @ExpectedString( 66 "@MostlyPrimitive(c0='a', "+ 67 "c1='\\'', " + 68 "i0=1, " + 69 "i1=2, " + 70 "f0=1.0f, " + 71 "f1=0.0f/0.0f, " + 72 "d0=0.0, " + 73 "d1=1.0/0.0, " + 74 "l0=5L, " + 75 "l1=9223372036854775807L, " + 76 "l2=-9223372036854775808L, " + 77 "l3=-2147483648L, " + 78 "s0=\"Hello world.\", " + 79 "s1=\"a\\\"b\", " + 80 "class0=Obj[].class, " + 81 "classArray={Obj[].class})") 82 @MostlyPrimitive( 83 c0='a', 84 c1='\'', 85 i0=1, 86 i1=2, 87 f0=1.0f, 88 f1=Float.NaN, 89 d0=0.0, 90 d1=2.0/0.0, 91 l0=5, 92 l1=Long.MAX_VALUE, 93 l2=Long.MIN_VALUE, 94 l3=Integer.MIN_VALUE, 95 s0="Hello world.", 96 s1="a\"b", 97 class0=Obj[].class, 98 classArray={Obj[].class} 99 ) 100 static class PrimHost{} 101 102 private static int classyTest() { 103 int failures = 0; 104 for (Field f : AnnotationHost.class.getFields()) { 105 Annotation a = f.getAnnotation(Classy.class); 106 System.out.println(a); 107 failures += check(f.getAnnotation(ExpectedString.class).value(), 108 a.toString()); 109 } 110 return failures; 111 } 112 113 static class AnnotationHost { 114 @ExpectedString( 115 "@Classy(value=Obj.class)") 116 @Classy(value=Obj.class) 117 public int f0; 118 119 @ExpectedString( 120 "@Classy(value=Obj[].class)") 121 @Classy(value=Obj[].class) 122 public int f1; 123 124 @ExpectedString( 125 "@Classy(value=Obj[][].class)") 126 @Classy(value=Obj[][].class) 127 public int f2; 128 129 @ExpectedString( 130 "@Classy(value=Obj[][][].class)") 131 @Classy(value=Obj[][][].class) 132 public int f3; 133 134 @ExpectedString( 135 "@Classy(value=int.class)") 136 @Classy(value=int.class) 137 public int f4; 138 139 @ExpectedString( 140 "@Classy(value=int[][][].class)") 141 @Classy(value=int[][][].class) 142 public int f5; 143 } 144 145 /** 146 * Each field should have two annotations, the first being 147 * @ExpectedString and the second the annotation under test. 148 */ 149 private static int arrayAnnotationTest() { 150 int failures = 0; 151 for (Field f : ArrayAnnotationHost.class.getFields()) { 152 Annotation[] annotations = f.getAnnotations(); 153 System.out.println(annotations[1]); 154 failures += check(((ExpectedString)annotations[0]).value(), 155 annotations[1].toString()); 156 } 157 return failures; 158 } 159 160 static class ArrayAnnotationHost { 161 @ExpectedString( 162 "@BooleanArray(value={true, false, true})") 163 @BooleanArray(value={true, false, true}) 164 public boolean[] f0; 165 166 @ExpectedString( 167 "@FloatArray(value={3.0f, 4.0f, 0.0f/0.0f, -1.0f/0.0f, 1.0f/0.0f})") 168 @FloatArray(value={3.0f, 4.0f, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY}) 169 public float[] f1; 170 171 @ExpectedString( 172 "@DoubleArray(value={1.0, 2.0, 0.0/0.0, 1.0/0.0, -1.0/0.0})") 173 @DoubleArray(value={1.0, 2.0, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,}) 174 public double[] f2; 175 176 @ExpectedString( 177 "@ByteArray(value={10, 11, 12})") 178 @ByteArray(value={10, 11, 12}) 179 public byte[] f3; 180 181 @ExpectedString( 182 "@ShortArray(value={0, 4, 5})") 183 @ShortArray(value={0, 4, 5}) 184 public short[] f4; 185 186 @ExpectedString( 187 "@CharArray(value={'a', 'b', 'c', '\\''})") 188 @CharArray(value={'a', 'b', 'c', '\''}) 189 public char[] f5; 190 191 @ExpectedString( 192 "@IntArray(value={1})") 193 @IntArray(value={1}) 194 public int[] f6; 195 196 @ExpectedString( 197 "@LongArray(value={-9223372036854775808L, -2147483649L, -2147483648L," + 198 " -2147483647L, 2147483648L, 9223372036854775807L})") 199 @LongArray(value={Long.MIN_VALUE, Integer.MIN_VALUE-1L, Integer.MIN_VALUE, 200 -Integer.MAX_VALUE, Integer.MAX_VALUE+1L, Long.MAX_VALUE}) 201 public long[] f7; 202 203 @ExpectedString( 204 "@StringArray(value={\"A\", \"B\", \"C\", \"\\\"Quote\\\"\"})") 205 @StringArray(value={"A", "B", "C", "\"Quote\""}) 206 public String[] f8; 207 208 @ExpectedString( 209 "@ClassArray(value={int.class, Obj[].class})") 210 @ClassArray(value={int.class, Obj[].class}) 211 public Class<?>[] f9; 212 213 @ExpectedString( 214 "@EnumArray(value={SOURCE})") 215 @EnumArray(value={RetentionPolicy.SOURCE}) 216 public RetentionPolicy[] f10; 217 } 218 } 219 220 // ------------ Supporting types ------------ 221 222 class Obj {} 223 224 @Retention(RetentionPolicy.RUNTIME) 225 @interface ExpectedString { 226 String value(); 227 } 228 229 @Retention(RetentionPolicy.RUNTIME) 230 @interface Classy { 231 Class<?> value(); 232 } 233 234 @Retention(RetentionPolicy.RUNTIME) 235 @interface BooleanArray { 236 boolean[] value(); 237 } 238 239 @Retention(RetentionPolicy.RUNTIME) 240 @interface FloatArray { 241 float[] value(); 242 } 243 244 @Retention(RetentionPolicy.RUNTIME) 245 @interface DoubleArray { 246 double[] value(); 247 } 248 249 @Retention(RetentionPolicy.RUNTIME) 250 @interface ByteArray { 251 byte[] value(); 252 } 253 254 @Retention(RetentionPolicy.RUNTIME) 255 @interface ShortArray { 256 short[] value(); 257 } 258 259 @Retention(RetentionPolicy.RUNTIME) 260 @interface CharArray { 261 char[] value(); 262 } 263 264 @Retention(RetentionPolicy.RUNTIME) 265 @interface IntArray { 266 int[] value(); 267 } 268 269 @Retention(RetentionPolicy.RUNTIME) 270 @interface LongArray { 271 long[] value(); 272 } 273 274 @Retention(RetentionPolicy.RUNTIME) 275 @interface ClassArray { 276 Class<?>[] value() default {int.class, Obj[].class}; 277 } 278 279 @Retention(RetentionPolicy.RUNTIME) 280 @interface StringArray { 281 String[] value(); 282 } 283 284 @Retention(RetentionPolicy.RUNTIME) 285 @interface EnumArray { 286 RetentionPolicy[] value(); 287 } 288 289 @Retention(RetentionPolicy.RUNTIME) 290 @interface MostlyPrimitive { 291 char c0(); 292 char c1(); 293 int i0(); 294 int i1(); 295 float f0(); 296 float f1(); 297 double d0(); 298 double d1(); 299 long l0(); 300 long l1(); 301 long l2(); 302 long l3(); 303 String s0(); 304 String s1(); 305 Class<?> class0(); 306 Class<?>[] classArray(); 307 }