Path: blob/master/test/jdk/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java
41149 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* @modules java.base/java.lang:open30* java.base/sun.reflect.annotation31*/3233import sun.reflect.annotation.AnnotationParser;3435import java.lang.annotation.Annotation;36import java.lang.annotation.Inherited;37import java.lang.annotation.Retention;38import java.lang.annotation.RetentionPolicy;39import java.lang.reflect.Field;40import java.lang.reflect.InvocationTargetException;41import java.util.ArrayList;42import java.util.Arrays;43import java.util.Collections;44import java.util.List;45import java.util.StringJoiner;4647public class AnnotationsInheritanceOrderRedefinitionTest {4849@Retention(RetentionPolicy.RUNTIME)50@Inherited51@interface Ann1 {52String value();53}5455@Retention(RetentionPolicy.RUNTIME)56@Inherited57@interface Ann2 {58String value();59}6061@Retention(RetentionPolicy.RUNTIME)62@Inherited63@interface Ann3 {64String value();65}6667@Ann1("A")68@Ann2("A")69static class A {}7071@Ann3("B")72static class B extends A {}7374@Ann1("C")75@Ann3("C")76static class C extends B {}7778public static void main(String[] args) {7980StringBuilder msgs = new StringBuilder();81boolean ok = true;8283ok &= annotationsEqual(msgs, A.class, true,84ann(Ann1.class, "A"), ann(Ann2.class, "A"));85ok &= annotationsEqual(msgs, A.class, false,86ann(Ann1.class, "A"), ann(Ann2.class, "A"));87ok &= annotationsEqual(msgs, B.class, true,88ann(Ann3.class, "B"));89ok &= annotationsEqual(msgs, B.class, false,90ann(Ann1.class, "A"), ann(Ann2.class, "A"), ann(Ann3.class, "B"));91ok &= annotationsEqual(msgs, C.class, true,92ann(Ann1.class, "C"), ann(Ann3.class, "C"));93ok &= annotationsEqual(msgs, C.class, false,94ann(Ann1.class, "C"), ann(Ann2.class, "A"), ann(Ann3.class, "C"));9596Annotation[] declaredAnnotatiosA = A.class.getDeclaredAnnotations();97Annotation[] annotationsA = A.class.getAnnotations();98Annotation[] declaredAnnotatiosB = B.class.getDeclaredAnnotations();99Annotation[] annotationsB = B.class.getAnnotations();100Annotation[] declaredAnnotatiosC = C.class.getDeclaredAnnotations();101Annotation[] annotationsC = C.class.getAnnotations();102103incrementClassRedefinedCount(A.class);104incrementClassRedefinedCount(B.class);105incrementClassRedefinedCount(C.class);106107ok &= annotationsEqualButNotSame(msgs, A.class, true, declaredAnnotatiosA);108ok &= annotationsEqualButNotSame(msgs, A.class, false, annotationsA);109ok &= annotationsEqualButNotSame(msgs, B.class, true, declaredAnnotatiosB);110ok &= annotationsEqualButNotSame(msgs, B.class, false, annotationsB);111ok &= annotationsEqualButNotSame(msgs, C.class, true, declaredAnnotatiosC);112ok &= annotationsEqualButNotSame(msgs, C.class, false, annotationsC);113114if (!ok) {115throw new RuntimeException("test failure\n" + msgs);116}117}118119// utility methods120121private static boolean annotationsEqualButNotSame(StringBuilder msgs,122Class<?> declaringClass, boolean declaredOnly, Annotation[] oldAnns) {123if (!annotationsEqual(msgs, declaringClass, declaredOnly, oldAnns)) {124return false;125}126Annotation[] anns = declaredOnly127? declaringClass.getDeclaredAnnotations()128: declaringClass.getAnnotations();129List<Annotation> sameAnns = new ArrayList<>();130for (int i = 0; i < anns.length; i++) {131if (anns[i] == oldAnns[i]) {132sameAnns.add(anns[i]);133}134}135if (!sameAnns.isEmpty()) {136msgs.append(declaredOnly ? "declared " : "").append("annotations for ")137.append(declaringClass.getSimpleName())138.append(" not re-parsed after class redefinition: ")139.append(toSimpleString(sameAnns)).append("\n");140return false;141} else {142return true;143}144}145146private static boolean annotationsEqual(StringBuilder msgs,147Class<?> declaringClass, boolean declaredOnly, Annotation... expectedAnns) {148Annotation[] anns = declaredOnly149? declaringClass.getDeclaredAnnotations()150: declaringClass.getAnnotations();151if (!Arrays.equals(anns, expectedAnns)) {152msgs.append(declaredOnly ? "declared " : "").append("annotations for ")153.append(declaringClass.getSimpleName()).append(" are: ")154.append(toSimpleString(anns)).append(", expected: ")155.append(toSimpleString(expectedAnns)).append("\n");156return false;157} else {158return true;159}160}161162private static Annotation ann(Class<? extends Annotation> annotationType,163Object value) {164return AnnotationParser.annotationForMap(annotationType,165Collections.singletonMap("value", value));166}167168private static String toSimpleString(List<Annotation> anns) {169return toSimpleString(anns.toArray(new Annotation[anns.size()]));170}171172private static String toSimpleString(Annotation[] anns) {173StringJoiner joiner = new StringJoiner(", ");174for (Annotation ann : anns) {175joiner.add(toSimpleString(ann));176}177return joiner.toString();178}179180private static String toSimpleString(Annotation ann) {181Class<? extends Annotation> annotationType = ann.annotationType();182Object value;183try {184value = annotationType.getDeclaredMethod("value").invoke(ann);185} catch (IllegalAccessException | InvocationTargetException186| NoSuchMethodException e) {187throw new RuntimeException(e);188}189return "@" + annotationType.getSimpleName() + "(" + value + ")";190}191192private static final Field classRedefinedCountField;193194static {195try {196classRedefinedCountField = Class.class.getDeclaredField("classRedefinedCount");197classRedefinedCountField.setAccessible(true);198} catch (NoSuchFieldException e) {199throw new Error(e);200}201}202203private static void incrementClassRedefinedCount(Class<?> clazz) {204try {205classRedefinedCountField.set(clazz,206((Integer) classRedefinedCountField.get(clazz)) + 1);207} catch (IllegalAccessException e) {208throw new RuntimeException(e);209}210}211}212213214