/
githubmirror
/
panama-vector
Обзор
Документация
Войти
/
githubmirror
/
panama-vector
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
test/jdk/java/lang/annotation/DuplicateAnnotationsTest.java
141 строка
6 KB
Chen Liang
8350704: Create tests to ensure the failure behavior of core reflection APIs
04 апр 2025, 03:58
04 апр 2025, 03:58
a449aee
Код
Авторство
О чём код?
/* * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8345614 8350704 * @summary Ensure behavior with duplicated annotations - class, method, or * field fails fast on duplicate annotations, but parameter allows them * @library /test/lib * @run junit DuplicateAnnotationsTest */ import java.io.IOException; import java.lang.annotation.AnnotationFormatError; import java.lang.classfile.*; import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; import java.lang.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute; import java.lang.constant.ClassDesc; import java.lang.reflect.AnnotatedElement; import java.nio.file.Path; import java.util.Arrays; import java.util.List; import jdk.test.lib.ByteCodeLoader; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import static org.junit.jupiter.api.Assertions.*; class DuplicateAnnotationsTest { static ClassModel cm; @BeforeAll static void setup() throws IOException { Path annoDuplicatedClass = Path.of(System.getProperty("test.classes")).resolve("AnnotationDuplicated.class"); cm = ClassFile.of().parse(annoDuplicatedClass); } interface Extractor { AnnotatedElement find(Class<?> cl) throws ReflectiveOperationException; } // Compiler hint static Extractor extract(Extractor e) { return e; } static Arguments[] arguments() { Annotation annotationOne = Annotation.of(ClassDesc.of("java.lang.Deprecated"), AnnotationElement.ofBoolean("forRemoval", true)); Annotation annotationTwo = Annotation.of(ClassDesc.of("java.lang.Deprecated"), AnnotationElement.ofString("since", "24")); RuntimeVisibleAnnotationsAttribute rvaa = RuntimeVisibleAnnotationsAttribute.of( List.of(annotationOne, annotationTwo) ); return new Arguments[]{ Arguments.of( "class", true, ClassTransform.endHandler(cob -> cob.with(rvaa)), extract(c -> c) ), Arguments.of( "field", true, ClassTransform.transformingFields(FieldTransform.endHandler(fb -> fb.with(rvaa))), extract(c -> c.getDeclaredField("field")) ), Arguments.of( "method", true, ClassTransform.transformingMethods(MethodTransform.endHandler(mb -> mb.with(rvaa))), extract(c -> c.getDeclaredConstructor(int.class)) ), Arguments.of( "parameter", false, // Surprisingly, parameters always allowed duplicate annotations ClassTransform.transformingMethods(MethodTransform.endHandler(mb -> mb.with( RuntimeVisibleParameterAnnotationsAttribute.of( List.of(List.of(annotationOne, annotationTwo)) ) ))), extract(c -> c.getDeclaredConstructor(int.class).getParameters()[0]) ), }; } /** * A test case represents a declaration that can be annotated. * Different declarations have different behaviors when multiple annotations * of the same interface are present (without a container annotation). * * @param caseName the type of declaration, for pretty printing in JUnit * @param fails whether this case should fail upon encountering duplicate annotations * @param ct transform to install duplicate annotations on the specific declaration * @param extractor function to access the AnnotatedElement representing that declaration */ @MethodSource("arguments") @ParameterizedTest void test(String caseName, boolean fails, ClassTransform ct, Extractor extractor) throws IOException, ReflectiveOperationException { var clazz = ByteCodeLoader.load("AnnotationDuplicated", ClassFile.of().transformClass(cm, ct)); var element = assertDoesNotThrow(() -> extractor.find(clazz)); Executable exec = () -> element.getAnnotation(Deprecated.class); if (fails) { var ex = assertThrows(AnnotationFormatError.class, exec, "no duplicate annotation access"); assertTrue(ex.getMessage().contains("Deprecated"), () -> "missing problematic annotation: " + ex.getMessage()); assertTrue(ex.getMessage().contains("AnnotationDuplicated"), () -> "missing container class: " + ex.getMessage()); } else { assertDoesNotThrow(exec, "obtaining duplicate annotations should be fine"); assertEquals(2, Arrays.stream(element.getAnnotations()) .filter(anno -> anno instanceof Deprecated) .count()); } } } // Duplicate annotations on class, field, method (constructor), method parameter class AnnotationDuplicated { int field; AnnotationDuplicated(int arg) { } }