Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java
38813 views
/*1* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 801194026* @summary Test inheritance, order and class redefinition behaviour of RUNTIME27* class annotations28* @author plevart29*/3031import sun.reflect.annotation.AnnotationParser;3233import java.lang.annotation.Annotation;34import java.lang.annotation.Inherited;35import java.lang.annotation.Retention;36import java.lang.annotation.RetentionPolicy;37import java.lang.reflect.Field;38import java.lang.reflect.InvocationTargetException;39import java.util.ArrayList;40import java.util.Arrays;41import java.util.Collections;42import java.util.List;43import java.util.StringJoiner;4445public class AnnotationsInheritanceOrderRedefinitionTest {4647@Retention(RetentionPolicy.RUNTIME)48@Inherited49@interface Ann1 {50String value();51}5253@Retention(RetentionPolicy.RUNTIME)54@Inherited55@interface Ann2 {56String value();57}5859@Retention(RetentionPolicy.RUNTIME)60@Inherited61@interface Ann3 {62String value();63}6465@Ann1("A")66@Ann2("A")67static class A {}6869@Ann3("B")70static class B extends A {}7172@Ann1("C")73@Ann3("C")74static class C extends B {}7576public static void main(String[] args) {7778StringBuilder msgs = new StringBuilder();79boolean ok = true;8081ok &= annotationsEqual(msgs, A.class, true,82ann(Ann1.class, "A"), ann(Ann2.class, "A"));83ok &= annotationsEqual(msgs, A.class, false,84ann(Ann1.class, "A"), ann(Ann2.class, "A"));85ok &= annotationsEqual(msgs, B.class, true,86ann(Ann3.class, "B"));87ok &= annotationsEqual(msgs, B.class, false,88ann(Ann1.class, "A"), ann(Ann2.class, "A"), ann(Ann3.class, "B"));89ok &= annotationsEqual(msgs, C.class, true,90ann(Ann1.class, "C"), ann(Ann3.class, "C"));91ok &= annotationsEqual(msgs, C.class, false,92ann(Ann1.class, "C"), ann(Ann2.class, "A"), ann(Ann3.class, "C"));9394Annotation[] declaredAnnotatiosA = A.class.getDeclaredAnnotations();95Annotation[] annotationsA = A.class.getAnnotations();96Annotation[] declaredAnnotatiosB = B.class.getDeclaredAnnotations();97Annotation[] annotationsB = B.class.getAnnotations();98Annotation[] declaredAnnotatiosC = C.class.getDeclaredAnnotations();99Annotation[] annotationsC = C.class.getAnnotations();100101incrementClassRedefinedCount(A.class);102incrementClassRedefinedCount(B.class);103incrementClassRedefinedCount(C.class);104105ok &= annotationsEqualButNotSame(msgs, A.class, true, declaredAnnotatiosA);106ok &= annotationsEqualButNotSame(msgs, A.class, false, annotationsA);107ok &= annotationsEqualButNotSame(msgs, B.class, true, declaredAnnotatiosB);108ok &= annotationsEqualButNotSame(msgs, B.class, false, annotationsB);109ok &= annotationsEqualButNotSame(msgs, C.class, true, declaredAnnotatiosC);110ok &= annotationsEqualButNotSame(msgs, C.class, false, annotationsC);111112if (!ok) {113throw new RuntimeException("test failure\n" + msgs);114}115}116117// utility methods118119private static boolean annotationsEqualButNotSame(StringBuilder msgs,120Class<?> declaringClass, boolean declaredOnly, Annotation[] oldAnns) {121if (!annotationsEqual(msgs, declaringClass, declaredOnly, oldAnns)) {122return false;123}124Annotation[] anns = declaredOnly125? declaringClass.getDeclaredAnnotations()126: declaringClass.getAnnotations();127List<Annotation> sameAnns = new ArrayList<>();128for (int i = 0; i < anns.length; i++) {129if (anns[i] == oldAnns[i]) {130sameAnns.add(anns[i]);131}132}133if (!sameAnns.isEmpty()) {134msgs.append(declaredOnly ? "declared " : "").append("annotations for ")135.append(declaringClass.getSimpleName())136.append(" not re-parsed after class redefinition: ")137.append(toSimpleString(sameAnns)).append("\n");138return false;139} else {140return true;141}142}143144private static boolean annotationsEqual(StringBuilder msgs,145Class<?> declaringClass, boolean declaredOnly, Annotation... expectedAnns) {146Annotation[] anns = declaredOnly147? declaringClass.getDeclaredAnnotations()148: declaringClass.getAnnotations();149if (!Arrays.equals(anns, expectedAnns)) {150msgs.append(declaredOnly ? "declared " : "").append("annotations for ")151.append(declaringClass.getSimpleName()).append(" are: ")152.append(toSimpleString(anns)).append(", expected: ")153.append(toSimpleString(expectedAnns)).append("\n");154return false;155} else {156return true;157}158}159160private static Annotation ann(Class<? extends Annotation> annotationType,161Object value) {162return AnnotationParser.annotationForMap(annotationType,163Collections.singletonMap("value", value));164}165166private static String toSimpleString(List<Annotation> anns) {167return toSimpleString(anns.toArray(new Annotation[anns.size()]));168}169170private static String toSimpleString(Annotation[] anns) {171StringJoiner joiner = new StringJoiner(", ");172for (Annotation ann : anns) {173joiner.add(toSimpleString(ann));174}175return joiner.toString();176}177178private static String toSimpleString(Annotation ann) {179Class<? extends Annotation> annotationType = ann.annotationType();180Object value;181try {182value = annotationType.getDeclaredMethod("value").invoke(ann);183} catch (IllegalAccessException | InvocationTargetException184| NoSuchMethodException e) {185throw new RuntimeException(e);186}187return "@" + annotationType.getSimpleName() + "(" + value + ")";188}189190private static final Field classRedefinedCountField;191192static {193try {194classRedefinedCountField = Class.class.getDeclaredField("classRedefinedCount");195classRedefinedCountField.setAccessible(true);196} catch (NoSuchFieldException e) {197throw new Error(e);198}199}200201private static void incrementClassRedefinedCount(Class<?> clazz) {202try {203classRedefinedCountField.set(clazz,204((Integer) classRedefinedCountField.get(clazz)) + 1);205} catch (IllegalAccessException e) {206throw new RuntimeException(e);207}208}209}210211212