/* * Copyright (c) 2014, 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 8039916 * @summary Test that a call to getType() on an AnnotatedType returned from an * Executable.getAnnotated* returns the same type as the corresponding * Executable.getGeneric* call. * @run testng TestExecutableGetAnnotatedType */ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.annotation.*; import java.lang.reflect.*; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import static org.testng.Assert.*; public class TestExecutableGetAnnotatedType { @Test(dataProvider = "genericExecutableData") public void testGenericMethodExceptions(Executable e) throws Exception { testExceptions(e); } @Test(dataProvider = "executableData") public void testMethodExceptions(Executable e) throws Exception { testExceptions(e); } @Test(dataProvider = "genericExecutableData") public void testGenericMethodParameterTypes(Executable e) throws Exception { testMethodParameters(e); } @Test(dataProvider = "executableData") public void testMethodParameterTypes(Executable e) throws Exception { testMethodParameters(e); } @Test(dataProvider = "genericExecutableData") public void testGenericParameterTypes(Executable e) throws Exception { testParameters(e.getParameters()); } @Test(dataProvider = "executableData") public void testParameterTypes(Executable e) throws Exception { testParameters(e.getParameters()); } @Test(dataProvider = "genericMethodData") public void testGenericReceiverType(Executable e) throws Exception { testReceiverType0(e); } @Test(dataProvider = "methodData") public void testReceiverType(Executable e) throws Exception { testReceiverType0(e); } @Test(dataProvider = "genericMethodData") public void testGenericMethodReturnType(Object o) throws Exception { // testng gets confused if the param to this method has type Method Method m = (Method)o; testReturnType(m); } @Test(dataProvider = "methodData") public void testMethodReturnType(Object o) throws Exception { // testng gets confused if the param to this method has type Method Method m = (Method)o; testReturnType(m); } private void testExceptions(Executable e) { Type[] ts = e.getGenericExceptionTypes(); AnnotatedType[] ats = e.getAnnotatedExceptionTypes(); assertEquals(ts.length, ats.length); for (int i = 0; i < ts.length; i++) { Type t = ts[i]; AnnotatedType at = ats[i]; assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n"); } } private void testMethodParameters(Executable e) { Type[] ts = e.getGenericParameterTypes(); AnnotatedType[] ats = e.getAnnotatedParameterTypes(); assertEquals(ts.length, ats.length); for (int i = 0; i < ts.length; i++) { Type t = ts[i]; AnnotatedType at = ats[i]; assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n"); } } private void testParameters(Parameter[] params) { for (Parameter p : params) { Type t = p.getParameterizedType(); AnnotatedType at = p.getAnnotatedType(); assertSame(at.getType(), t, p.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n"); } } private void testReceiverType0(Executable e) { if (Modifier.isStatic(e.getModifiers())) assertNull(e.getAnnotatedReceiverType()); else assertSame(e.getAnnotatedReceiverType().getType(), e.getDeclaringClass()); } private void testReturnType(Method m) { Type t = m.getGenericReturnType(); AnnotatedType at = m.getAnnotatedReturnType(); assertSame(at.getType(), t, m.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n"); } @DataProvider public Object[][] methodData() throws Exception { return filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class) .toArray(new Object[0][0]); } @DataProvider public Object[][] genericMethodData() throws Exception { return filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class) .toArray(new Object[0][0]); } @DataProvider public Object[][] executableData() throws Exception { @SuppressWarnings("raw") List l = filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class); l.addAll(filterData(Arrays.stream(Methods1.class.getConstructors()), Methods1.class)); l.addAll(filterData(Arrays.stream(Ctors1.class.getConstructors()), Ctors1.class)); return ((List)l).toArray(new Object[0][0]); } @DataProvider public Object[][] genericExecutableData() throws Exception { @SuppressWarnings("raw") List l = filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class); l.addAll(filterData(Arrays.stream(GenericMethods1.class.getConstructors()), GenericMethods1.class)); l.addAll(filterData(Arrays.stream(GenericCtors1.class.getConstructors()), GenericCtors1.class)); return ((List)l).toArray(new Object[0][0]); } private List filterData(Stream l, Class c) { return l.filter(m -> (m.getDeclaringClass() == c)) // remove object methods .map(m -> { Object[] o = new Object[1]; o[0] = m; return o; }) .collect(Collectors.toList()); } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) public @interface TA {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) public @interface TB {} @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) public @interface TC {} public static class Methods1 { public static void m1() throws Error, RuntimeException {;} public static long m2(int a, double b) throws Error, RuntimeException { return 0L; } public static Object m3(String s, List l) throws Error, RuntimeException { return null; } public static Object m4(String s, List l) { return null; } public static Object m4(String s, List l, boolean ... b){ return null; } public static void m10() throws @TA Error, @TB @TC RuntimeException {;} public static @TB long m20(@TC int a, @TA double b) throws @TA Error, @TB @TC RuntimeException { return 0L; } public static @TC Object m30(@TA String s, @TB List l) throws @TA Error, @TB @TC RuntimeException { return null; } public static @TA Object m40(@TB String s, @TC List<@TA String> l) { return null; } public static @TA Object m40(@TB String s, @TC List<@TA String> l, @TB boolean ... b) { return null; } public Methods1(int a, double b) {} public Methods1(String s, List l, boolean ... b) {} public Methods1(@TC long a, @TA float b) {} public Methods1(@TA int i, @TB String s, @TC List<@TA String> l, @TB boolean ... b) {} } // test default ctor public static class Ctors1 { } public static class GenericMethods1 { public E m1(E e, Object o) throws Error, RuntimeException { return null; } public E m2(List e, int i) throws Error, RuntimeException { return null; } public E m3(double d, List e) throws Error, RuntimeException { return null; } public E m4(byte[] b, GenericMethods1 e) { return null; } public E m5(GenericMethods1 e) { return null; } public E m6(char c, E e) { return null; } public E m7(char c, E e, byte ... b) { return null; } public static M n1(M e) { return null; } public static M n2(List e) { return null; } public static M n3(List e) throws Error, M { return null; } public static M n4(GenericMethods1 e) throws Error, RuntimeException { return null; } public static M n5(GenericMethods1 e) { return null; } public static M n6(M e) { return null; } public E o1(E e) { return null; } public E o2(List e) { return null; } public E o3(GenericMethods1 this, List e) throws M, N { return null; } public E o4(GenericMethods1 e) throws Error, RuntimeException { return null; } public E o5(GenericMethods1 e) { return null; } public E o6(E e) { return null; } // with annotations public @TA E m10(E e, @TC Object o) throws @TA Error, @TB @TC RuntimeException { return null; } public @TB E m20(@TA List<@TA ? extends @TA List> e, @TC int i) throws @TA Error, @TB @TC RuntimeException { return null; } public @TB E m30(@TC double d, List e) throws @TA Error, @TB @TC RuntimeException { return null; } public <@TA E extends @TA List> @TA E m40(@TA byte @TB [] b, GenericMethods1<@TA ? extends E> e) { return null; } public <@TB E extends @TB List> E m50(@TA GenericMethods1 e) { return null; } public <@TB E extends @TA List & Cloneable> E m60(@TC char c, E e) { return null; } public <@TB E extends @TA List & Cloneable> E m70(@TC char c, E e, @TA @TB byte ... b) { return null; } public static <@TA M> @TA M n10(M e) { return null; } public static <@TA @TB @TC M> M n20(List<@TA ? extends List> e) { return null; } @TA @TB @TC public static M n30(List<@TB M> e) throws @TA Error, @TB @TC M { return null; } public static <@TC M extends Number> M n40(GenericMethods1 e) throws @TA Error, @TB @TC RuntimeException { return null; } @TA public static M n50(GenericMethods1 e) { return null; } public static <@TA M extends @TB List & @TC @TB Cloneable> M n60(M e) { return null; } public <@TC M> E o10(@TA E e) { return null; } public @TA E o20(@TB List<@TB ? extends @TB List> e) { return null; } @TC public @TB E o30(@TA @TB @TC GenericMethods1 this, List e) throws @TA M, @TB @TC N { return null; } public <@TA M extends Number> E o40(GenericMethods1 e) throws @TA Error, @TB @TC RuntimeException { return null; } public E o50(GenericMethods1<@TA ? super Number> e) { return null; } public <@TA M extends @TB List & @TC Cloneable> E o60(@TA E e) { return null; } // ctors public GenericMethods1(List e, int i) throws Error, RuntimeException { } public GenericMethods1(char c, E e, byte ... b) { } @TC public GenericMethods1(List<@TC E> e) throws @TA M, @TB @TC N { } public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m) throws @TA Exception { } public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m, @TC byte ... b) throws Exception { } } // test default ctor public static class GenericCtors1 { } }