1 /* 2 * Copyright (c) 2016, 2017, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * Create class file using ASM, slightly modified the ASMifier output 28 */ 29 30 import org.testng.Assert; 31 import org.testng.annotations.Test; 32 33 import java.lang.annotation.Annotation; 34 import java.lang.annotation.AnnotationFormatError; 35 import java.util.Arrays; 36 import java.util.Set; 37 import java.util.stream.Collectors; 38 import java.util.stream.Stream; 39 40 /* 41 * @test 42 * @bug 8158510 43 * @summary Verify valid annotation 44 * @modules java.base/jdk.internal.org.objectweb.asm 45 * @modules java.base/sun.reflect.annotation 46 * @clean AnnotationWithVoidReturn AnnotationWithParameter 47 * AnnotationWithExtraInterface AnnotationWithException 48 * AnnotationWithHashCode AnnotationWithDefaultMember 49 * AnnotationWithoutAnnotationAccessModifier HolderX 50 * @compile -XDignore.symbol.file ClassFileGenerator.java GoodAnnotation.java 51 * @run main ClassFileGenerator 52 * @run testng AnnotationVerifier 53 */ 54 55 public class AnnotationVerifier { 56 57 //======================================================= 58 // GoodAnnotation... 59 60 @GoodAnnotation 61 static class HolderA { 62 } 63 64 @Test holderA_goodAnnotation()65 public void holderA_goodAnnotation() { 66 testGetAnnotation(HolderA.class, GoodAnnotation.class, true); 67 } 68 69 @Test holderA_annotations()70 public void holderA_annotations() { 71 testGetAnnotations(HolderA.class, GoodAnnotation.class); 72 } 73 74 //======================================================= 75 // AnnotationWithParameter... 76 77 /* 78 @Retention(RetentionPolicy.RUNTIME) 79 public @interface AnnotationWithParameter { 80 int m(int x) default -1; 81 } 82 */ 83 84 @GoodAnnotation 85 @AnnotationWithParameter 86 static class HolderB { 87 } 88 89 @Test holderB_annotationWithParameter()90 public void holderB_annotationWithParameter() { 91 testGetAnnotation(HolderB.class, AnnotationWithParameter.class, false); 92 } 93 94 @Test holderB_goodAnnotation()95 public void holderB_goodAnnotation() { 96 testGetAnnotation(HolderB.class, GoodAnnotation.class, true); 97 } 98 99 @Test holderB_annotations()100 public void holderB_annotations() { 101 testGetAnnotations(HolderB.class, GoodAnnotation.class); 102 } 103 104 //======================================================= 105 // AnnotationWithVoidReturn... 106 107 /* 108 @Retention(RetentionPolicy.RUNTIME) 109 public @interface AnnotationWithVoidReturn { 110 void m() default 1; 111 } 112 */ 113 114 @GoodAnnotation 115 @AnnotationWithVoidReturn 116 static class HolderC { 117 } 118 119 @Test(expectedExceptions = AnnotationFormatError.class) holderC_annotationWithVoidReturn()120 public void holderC_annotationWithVoidReturn() { 121 testGetAnnotation(HolderC.class, AnnotationWithVoidReturn.class, false); 122 } 123 124 @Test(expectedExceptions = AnnotationFormatError.class) holderC_goodAnnotation()125 public void holderC_goodAnnotation() { 126 testGetAnnotation(HolderC.class, GoodAnnotation.class, false); 127 } 128 129 @Test(expectedExceptions = AnnotationFormatError.class) holderC_annotations()130 public void holderC_annotations() { 131 testGetAnnotations(HolderC.class); 132 } 133 134 //======================================================= 135 // AnnotationWithExtraInterface... 136 137 /* 138 @Retention(RetentionPolicy.RUNTIME) 139 public @interface AnnotationWithExtraInterface extends java.io.Serializable { 140 int m() default 1; 141 } 142 */ 143 144 @GoodAnnotation 145 @AnnotationWithExtraInterface 146 static class HolderD { 147 } 148 149 @Test(expectedExceptions = AnnotationFormatError.class) holderD_annotationWithExtraInterface()150 public void holderD_annotationWithExtraInterface() { 151 testGetAnnotation(HolderD.class, AnnotationWithExtraInterface.class, false); 152 } 153 154 @Test(expectedExceptions = AnnotationFormatError.class) holderD_goodAnnotation()155 public void holderD_goodAnnotation() { 156 testGetAnnotation(HolderD.class, GoodAnnotation.class, false); 157 } 158 159 @Test(expectedExceptions = AnnotationFormatError.class) holderD_annotations()160 public void holderD_annotations() { 161 testGetAnnotations(HolderD.class); 162 } 163 164 //======================================================= 165 // AnnotationWithException... 166 167 /* 168 @Retention(RetentionPolicy.RUNTIME) 169 public @interface AnnotationWithException { 170 int m() throws Exception default 1; 171 } 172 */ 173 174 @GoodAnnotation 175 @AnnotationWithException 176 static class HolderE { 177 } 178 179 @AnnotationWithException 180 static class HolderE2 { 181 } 182 183 @Test holderE_annotationWithException()184 public void holderE_annotationWithException() { 185 testGetAnnotation(HolderE.class, AnnotationWithException.class, true); 186 } 187 188 @Test holderE_goodAnnotation()189 public void holderE_goodAnnotation() { 190 testGetAnnotation(HolderE.class, GoodAnnotation.class, true); 191 } 192 193 @Test holderE_annotations()194 public void holderE_annotations() { 195 testGetAnnotations(HolderE.class, GoodAnnotation.class, AnnotationWithException.class); 196 } 197 198 @Test(expectedExceptions = AnnotationFormatError.class) holderE_annotationWithException_equals()199 public void holderE_annotationWithException_equals() { 200 AnnotationWithException ann1, ann2; 201 try { 202 ann1 = HolderE.class.getAnnotation(AnnotationWithException.class); 203 ann2 = HolderE2.class.getAnnotation(AnnotationWithException.class); 204 } catch (Throwable t) { 205 throw new AssertionError("Unexpected exception", t); 206 } 207 Assert.assertNotNull(ann1); 208 Assert.assertNotNull(ann2); 209 210 testEquals(ann1, ann2, true); // this throws AnnotationFormatError 211 } 212 213 //======================================================= 214 // AnnotationWithHashCode... 215 216 /* 217 @Retention(RetentionPolicy.RUNTIME) 218 public @interface AnnotationWithHashCode { 219 int hashCode() default 1; 220 } 221 */ 222 223 @GoodAnnotation 224 @AnnotationWithHashCode 225 static class HolderF { 226 } 227 228 @AnnotationWithHashCode 229 static class HolderF2 { 230 } 231 232 @Test holderF_annotationWithHashCode()233 public void holderF_annotationWithHashCode() { 234 testGetAnnotation(HolderF.class, AnnotationWithHashCode.class, true); 235 } 236 237 @Test holderF_goodAnnotation()238 public void holderF_goodAnnotation() { 239 testGetAnnotation(HolderF.class, GoodAnnotation.class, true); 240 } 241 242 @Test holderF_annotations()243 public void holderF_annotations() { 244 testGetAnnotations(HolderF.class, GoodAnnotation.class, AnnotationWithHashCode.class); 245 } 246 247 @Test(expectedExceptions = AnnotationFormatError.class) holderF_annotationWithHashCode_equals()248 public void holderF_annotationWithHashCode_equals() { 249 AnnotationWithHashCode ann1, ann2; 250 try { 251 ann1 = HolderF.class.getAnnotation(AnnotationWithHashCode.class); 252 ann2 = HolderF2.class.getAnnotation(AnnotationWithHashCode.class); 253 } catch (Throwable t) { 254 throw new AssertionError("Unexpected exception", t); 255 } 256 Assert.assertNotNull(ann1); 257 Assert.assertNotNull(ann2); 258 259 testEquals(ann1, ann2, true); // this throws AnnotationFormatError 260 } 261 262 //======================================================= 263 // AnnotationWithDefaultMember... 264 265 /* 266 @Retention(RetentionPolicy.RUNTIME) 267 public @interface AnnotationWithDefaultMember { 268 int m() default 1; 269 default int d() default 2 { return 2; } 270 } 271 */ 272 273 @GoodAnnotation 274 @AnnotationWithDefaultMember 275 static class HolderG { 276 } 277 278 @AnnotationWithDefaultMember 279 static class HolderG2 { 280 } 281 282 @Test holderG_annotationWithDefaultMember()283 public void holderG_annotationWithDefaultMember() { 284 testGetAnnotation(HolderG.class, AnnotationWithDefaultMember.class, true); 285 } 286 287 @Test holderG_goodAnnotation()288 public void holderG_goodAnnotation() { 289 testGetAnnotation(HolderG.class, GoodAnnotation.class, true); 290 } 291 292 @Test holderG_annotations()293 public void holderG_annotations() { 294 testGetAnnotations(HolderG.class, GoodAnnotation.class, AnnotationWithDefaultMember.class); 295 } 296 297 @Test(expectedExceptions = AnnotationFormatError.class) holderG_annotationWithDefaultMember_equals()298 public void holderG_annotationWithDefaultMember_equals() { 299 AnnotationWithDefaultMember ann1, ann2; 300 try { 301 ann1 = HolderG.class.getAnnotation(AnnotationWithDefaultMember.class); 302 ann2 = HolderG2.class.getAnnotation(AnnotationWithDefaultMember.class); 303 } catch (Throwable t) { 304 throw new AssertionError("Unexpected exception", t); 305 } 306 Assert.assertNotNull(ann1); 307 Assert.assertNotNull(ann2); 308 309 testEquals(ann1, ann2, true); // this throws AnnotationFormatError 310 } 311 312 //======================================================= 313 // AnnotationWithoutAnnotationAccessModifier... 314 315 /* 316 317 @Retention(RetentionPolicy.RUNTIME) 318 public interface AnnotationWithoutAnnotationAccessModifier extends Annotation { 319 int m() default 1; 320 } 321 322 @GoodAnnotation 323 @AnnotationWithoutAnnotationAccessModifier 324 static class HolderX { 325 } 326 327 */ 328 329 @Test holderX_annotationWithoutAnnotationAccessModifier()330 public void holderX_annotationWithoutAnnotationAccessModifier() { 331 testGetAnnotation(HolderX.class, AnnotationWithoutAnnotationAccessModifier.class, false); 332 } 333 334 @Test holderX_goodAnnotation()335 public void holderX_goodAnnotation() { 336 testGetAnnotation(HolderX.class, GoodAnnotation.class, true); 337 } 338 339 @Test holderX_annotations()340 public void holderX_annotations() { 341 testGetAnnotations(HolderX.class, GoodAnnotation.class); 342 } 343 344 //======================================================= 345 // utils 346 // 347 testGetAnnotation(Class<?> holderClass, Class<? extends Annotation> annType, boolean expectedPresent)348 private static void testGetAnnotation(Class<?> holderClass, 349 Class<? extends Annotation> annType, 350 boolean expectedPresent) { 351 Object result = null; 352 try { 353 try { 354 result = holderClass.getAnnotation(annType); 355 if (expectedPresent != (result != null)) { 356 throw new AssertionError("Expected " + 357 (expectedPresent ? "non-null" : "null") + 358 " result, but got: " + result); 359 } 360 } catch (Throwable t) { 361 result = t; 362 throw t; 363 } 364 } finally { 365 System.out.println("\n" + 366 holderClass.getSimpleName() + 367 ".class.getAnnotation(" + 368 annType.getSimpleName() + 369 ".class) = " + 370 result); 371 } 372 } 373 testGetAnnotations(Class<?> holderClass, Class<? extends Annotation> ... expectedTypes)374 private static void testGetAnnotations(Class<?> holderClass, 375 Class<? extends Annotation> ... expectedTypes) { 376 Object result = null; 377 try { 378 try { 379 Annotation[] anns = holderClass.getAnnotations(); 380 381 Set<Class<? extends Annotation>> gotTypes = 382 Stream.of(anns) 383 .map(Annotation::annotationType) 384 .collect(Collectors.toSet()); 385 386 Set<Class<? extends Annotation>> expTypes = 387 Stream.of(expectedTypes) 388 .collect(Collectors.toSet()); 389 390 if (!expTypes.equals(gotTypes)) { 391 throw new AssertionError("Expected annotation types: " + expTypes + 392 " but got: " + Arrays.toString(anns)); 393 } 394 result = Arrays.toString(anns); 395 } catch (Throwable t) { 396 result = t; 397 throw t; 398 } 399 } finally { 400 System.out.println("\n" + 401 holderClass.getSimpleName() + 402 ".class.getAnnotations() = " + 403 result); 404 } 405 } 406 testEquals(Annotation ann1, Annotation ann2, boolean expectedEquals)407 private static void testEquals(Annotation ann1, Annotation ann2, boolean expectedEquals) { 408 Object result = null; 409 try { 410 try { 411 boolean gotEquals = ann1.equals(ann2); 412 Assert.assertEquals(gotEquals, expectedEquals); 413 result = gotEquals; 414 } catch (Throwable t) { 415 result = t; 416 throw t; 417 } 418 } finally { 419 System.out.println("\n" + ann1 + ".equals(" + ann2 + ") = " + result); 420 } 421 } 422 } 423