| /* |
| * Copyright (c) 2013, 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 8023651 8044629 |
| * @summary Test that the receiver annotations and the return annotations of |
| * constructors behave correctly. |
| * @run testng ConstructorReceiverTest |
| */ |
| |
| import java.lang.annotation.*; |
| import java.lang.reflect.*; |
| import java.util.Arrays; |
| import org.testng.annotations.DataProvider; |
| import org.testng.annotations.Test; |
| |
| import static org.testng.Assert.*; |
| |
| public class ConstructorReceiverTest { |
| public static final Integer EMPTY_ANNOTATED_TYPE = Integer.valueOf(-1); |
| |
| // Format is { |
| // { Class to get ctor for, |
| // ctor param class, |
| // value of anno of return type, |
| // value of anno for receiver, |
| // or null if there should be no receiver, |
| // or EMPTY_ANNOTATED_TYPE of there should be a receiver but |
| // no annotation |
| // }, |
| // ... |
| // } |
| public static final Object[][] TESTS = { |
| { ConstructorReceiverTest.class, null, Integer.valueOf(5), null }, |
| { ConstructorReceiverTest.Middle.class, ConstructorReceiverTest.class, Integer.valueOf(10), Integer.valueOf(15) }, |
| { ConstructorReceiverTest.Middle.Inner.class, ConstructorReceiverTest.Middle.class, Integer.valueOf(100), Integer.valueOf(150) }, |
| { ConstructorReceiverTest.Middle.Inner.Innermost.class, ConstructorReceiverTest.Middle.Inner.class, Integer.valueOf(1000), Integer.valueOf(1500) }, |
| { ConstructorReceiverTest.Middle.InnerNoReceiver.class, ConstructorReceiverTest.Middle.class, Integer.valueOf(300), EMPTY_ANNOTATED_TYPE }, |
| { ConstructorReceiverTest.Nested.class, null, Integer.valueOf(20), null }, |
| { ConstructorReceiverTest.Nested.NestedMiddle.class, ConstructorReceiverTest.Nested.class, Integer.valueOf(200), Integer.valueOf(250)}, |
| { ConstructorReceiverTest.Nested.NestedMiddle.NestedInner.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(2000), Integer.valueOf(2500)}, |
| { ConstructorReceiverTest.Nested.NestedMiddle.NestedInnerNoReceiver.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(4000), EMPTY_ANNOTATED_TYPE}, |
| { ConstructorReceiverTest.Nested.NestedMiddle.SecondNestedInnerNoReceiver.class, ConstructorReceiverTest.Nested.NestedMiddle.class, Integer.valueOf(5000), EMPTY_ANNOTATED_TYPE}, |
| }; |
| |
| |
| @DataProvider |
| public Object[][] data() { return TESTS; } |
| |
| @Test(dataProvider = "data") |
| public void testAnnotatedReciver(Class<?> toTest, Class<?> ctorParamType, |
| Integer returnVal, Integer receiverVal) throws NoSuchMethodException { |
| Constructor c; |
| if (ctorParamType == null) |
| c = toTest.getDeclaredConstructor(); |
| else |
| c = toTest.getDeclaredConstructor(ctorParamType); |
| |
| AnnotatedType annotatedReceiverType = c.getAnnotatedReceiverType(); |
| |
| // Some Constructors doesn't conceptually have a receiver, they should return null |
| if (receiverVal == null) { |
| assertNull(annotatedReceiverType, "getAnnotatedReciverType should return null for Constructor: " + c); |
| return; |
| } |
| |
| // check that getType() matches the receiver |
| assertEquals(annotatedReceiverType.getType(), |
| ctorParamType, |
| "getType() doesn't match receiver type: " + ctorParamType); |
| |
| Annotation[] receiverAnnotations = annotatedReceiverType.getAnnotations(); |
| |
| // Some Constructors have no annotations on but in theory can have a receiver |
| if (receiverVal.equals(EMPTY_ANNOTATED_TYPE)) { |
| assertEquals(receiverAnnotations.length, 0, "expecting an empty annotated type for: " + c); |
| return; |
| } |
| |
| // The rest should have annotations |
| assertEquals(receiverAnnotations.length, 1, "expecting a 1 element array. Looking at 'length': "); |
| assertEquals(((Annot)receiverAnnotations[0]).value(), receiverVal.intValue(), " wrong annotation found. Found " + |
| receiverAnnotations[0] + |
| " should find @Annot with value=" + |
| receiverVal); |
| } |
| |
| @Test(dataProvider = "data") |
| public void testAnnotatedReturn(Class<?> toTest, Class<?> ctorParamType, |
| Integer returnVal, Integer receiverVal) throws NoSuchMethodException { |
| Constructor c; |
| if (ctorParamType == null) |
| c = toTest.getDeclaredConstructor(); |
| else |
| c = toTest.getDeclaredConstructor(ctorParamType); |
| |
| AnnotatedType annotatedReturnType = c.getAnnotatedReturnType(); |
| Annotation[] returnAnnotations = annotatedReturnType.getAnnotations(); |
| |
| assertEquals(returnAnnotations.length, 1, "expecting a 1 element array. Looking at 'length': "); |
| assertEquals(((Annot)returnAnnotations[0]).value(), returnVal.intValue(), " wrong annotation found. Found " + |
| returnAnnotations[0] + |
| " should find @Annot with value=" + |
| returnVal); |
| } |
| |
| @Annot(5) ConstructorReceiverTest() {} |
| |
| private class Middle { |
| @Annot(10) public Middle(@Annot(15) ConstructorReceiverTest ConstructorReceiverTest.this) {} |
| |
| public class Inner { |
| @Annot(100) Inner(@Annot(150) Middle Middle.this) {} |
| |
| class Innermost { |
| @Annot(1000) private Innermost(@Annot(1500) Inner Inner.this) {} |
| } |
| } |
| |
| class InnerNoReceiver { |
| @Annot(300) InnerNoReceiver(Middle Middle.this) {} |
| } |
| } |
| |
| public static class Nested { |
| @Annot(20) public Nested() {} |
| |
| class NestedMiddle { |
| @Annot(200) public NestedMiddle(@Annot(250) Nested Nested.this) {} |
| |
| class NestedInner { |
| @Annot(2000) public NestedInner(@Annot(2500) NestedMiddle NestedMiddle.this) {} |
| } |
| |
| class NestedInnerNoReceiver { |
| @Annot(4000) public NestedInnerNoReceiver() {} |
| } |
| |
| class SecondNestedInnerNoReceiver { |
| @Annot(5000) public SecondNestedInnerNoReceiver(NestedMiddle NestedMiddle.this) {} |
| } |
| } |
| } |
| |
| @Retention(RetentionPolicy.RUNTIME) |
| @Target(ElementType.TYPE_USE) |
| public static @interface Annot { |
| int value(); |
| } |
| } |