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 "b0=(byte)0x01, " + 69 "i0=1, " + 70 "i1=2, " + 71 "f0=1.0f, " + 72 "f1=0.0f/0.0f, " + 73 "d0=0.0, " + 74 "d1=1.0/0.0, " + 75 "l0=5L, " + 76 "l1=9223372036854775807L, " + 77 "l2=-9223372036854775808L, " + 78 "l3=-2147483648L, " + 79 "s0=\"Hello world.\", " + 80 "s1=\"a\\\"b\", " + 81 "class0=Obj[].class, " + 82 "classArray={Obj[].class})") 83 @MostlyPrimitive( 84 c0='a', 85 c1='\'', 86 b0=1, 87 i0=1, 88 i1=2, 89 f0=1.0f, 90 f1=Float.NaN, 91 d0=0.0, 92 d1=2.0/0.0, 93 l0=5, 94 l1=Long.MAX_VALUE, 95 l2=Long.MIN_VALUE, 96 l3=Integer.MIN_VALUE, 97 s0="Hello world.", 98 s1="a\"b", 99 class0=Obj[].class, 100 classArray={Obj[].class} 101 ) 102 static class PrimHost{} 103 104 private static int classyTest() { 105 int failures = 0; 106 for (Field f : AnnotationHost.class.getFields()) { 107 Annotation a = f.getAnnotation(Classy.class); 108 System.out.println(a); 109 failures += check(f.getAnnotation(ExpectedString.class).value(), 110 a.toString()); 111 } 112 return failures; 113 } 114 115 static class AnnotationHost { 116 @ExpectedString( 117 "@Classy(Obj.class)") 118 @Classy(Obj.class) 119 public int f0; 120 121 @ExpectedString( 122 "@Classy(Obj[].class)") 123 @Classy(Obj[].class) 124 public int f1; 125 126 @ExpectedString( 127 "@Classy(Obj[][].class)") 128 @Classy(Obj[][].class) 129 public int f2; 130 131 @ExpectedString( 132 "@Classy(Obj[][][].class)") 133 @Classy(Obj[][][].class) 134 public int f3; 135 136 @ExpectedString( 137 "@Classy(int.class)") 138 @Classy(int.class) 139 public int f4; 140 141 @ExpectedString( 142 "@Classy(int[][][].class)") 143 @Classy(int[][][].class) 144 public int f5; 145 } 146 147 /** 148 * Each field should have two annotations, the first being 149 * @ExpectedString and the second the annotation under test. 150 */ 151 private static int arrayAnnotationTest() { 152 int failures = 0; 153 for (Field f : ArrayAnnotationHost.class.getFields()) { 154 Annotation[] annotations = f.getAnnotations(); 155 System.out.println(annotations[1]); 156 failures += check(((ExpectedString)annotations[0]).value(), 157 annotations[1].toString()); 158 } 159 return failures; 160 } 161 162 static class ArrayAnnotationHost { 163 @ExpectedString( 164 "@BooleanArray({true, false, true})") 165 @BooleanArray({true, false, true}) 166 public boolean[] f0; 167 168 @ExpectedString( 169 "@FloatArray({3.0f, 4.0f, 0.0f/0.0f, -1.0f/0.0f, 1.0f/0.0f})") 170 @FloatArray({3.0f, 4.0f, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY}) 171 public float[] f1; 172 173 @ExpectedString( 174 "@DoubleArray({1.0, 2.0, 0.0/0.0, 1.0/0.0, -1.0/0.0})") 175 @DoubleArray({1.0, 2.0, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,}) 176 public double[] f2; 177 178 @ExpectedString( 179 "@ByteArray({(byte)0x0a, (byte)0x0b, (byte)0x0c})") 180 @ByteArray({10, 11, 12}) 181 public byte[] f3; 182 183 @ExpectedString( 184 "@ShortArray({0, 4, 5})") 185 @ShortArray({0, 4, 5}) 186 public short[] f4; 187 188 @ExpectedString( 189 "@CharArray({'a', 'b', 'c', '\\''})") 190 @CharArray({'a', 'b', 'c', '\''}) 191 public char[] f5; 192 193 @ExpectedString( 194 "@IntArray({1})") 195 @IntArray({1}) 196 public int[] f6; 197 198 @ExpectedString( 199 "@LongArray({-9223372036854775808L, -2147483649L, -2147483648L," + 200 " -2147483647L, 2147483648L, 9223372036854775807L})") 201 @LongArray({Long.MIN_VALUE, Integer.MIN_VALUE-1L, Integer.MIN_VALUE, 202 -Integer.MAX_VALUE, Integer.MAX_VALUE+1L, Long.MAX_VALUE}) 203 public long[] f7; 204 205 @ExpectedString( 206 "@StringArray({\"A\", \"B\", \"C\", \"\\\"Quote\\\"\"})") 207 @StringArray({"A", "B", "C", "\"Quote\""}) 208 public String[] f8; 209 210 @ExpectedString( 211 "@ClassArray({int.class, Obj[].class})") 212 @ClassArray({int.class, Obj[].class}) 213 public Class<?>[] f9; 214 215 @ExpectedString( 216 "@EnumArray({SOURCE})") 217 @EnumArray({RetentionPolicy.SOURCE}) 218 public RetentionPolicy[] f10; 219 } 220 } 221 222 // ------------ Supporting types ------------ 223 224 class Obj {} 225 226 @Retention(RetentionPolicy.RUNTIME) 227 @interface ExpectedString { 228 String value(); 229 } 230 231 @Retention(RetentionPolicy.RUNTIME) 232 @interface Classy { 233 Class<?> value(); 234 } 235 236 @Retention(RetentionPolicy.RUNTIME) 237 @interface BooleanArray { 238 boolean[] value(); 239 } 240 241 @Retention(RetentionPolicy.RUNTIME) 242 @interface FloatArray { 243 float[] value(); 244 } 245 246 @Retention(RetentionPolicy.RUNTIME) 247 @interface DoubleArray { 248 double[] value(); 249 } 250 251 @Retention(RetentionPolicy.RUNTIME) 252 @interface ByteArray { 253 byte[] value(); 254 } 255 256 @Retention(RetentionPolicy.RUNTIME) 257 @interface ShortArray { 258 short[] value(); 259 } 260 261 @Retention(RetentionPolicy.RUNTIME) 262 @interface CharArray { 263 char[] value(); 264 } 265 266 @Retention(RetentionPolicy.RUNTIME) 267 @interface IntArray { 268 int[] value(); 269 } 270 271 @Retention(RetentionPolicy.RUNTIME) 272 @interface LongArray { 273 long[] value(); 274 } 275 276 @Retention(RetentionPolicy.RUNTIME) 277 @interface ClassArray { 278 Class<?>[] value() default {int.class, Obj[].class}; 279 } 280 281 @Retention(RetentionPolicy.RUNTIME) 282 @interface StringArray { 283 String[] value(); 284 } 285 286 @Retention(RetentionPolicy.RUNTIME) 287 @interface EnumArray { 288 RetentionPolicy[] value(); 289 } 290 291 @Retention(RetentionPolicy.RUNTIME) 292 @interface MostlyPrimitive { 293 char c0(); 294 char c1(); 295 byte b0(); 296 int i0(); 297 int i1(); 298 float f0(); 299 float f1(); 300 double d0(); 301 double d1(); 302 long l0(); 303 long l1(); 304 long l2(); 305 long l3(); 306 String s0(); 307 String s1(); 308 Class<?> class0(); 309 Class<?>[] classArray(); 310 }