1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8039916
  27  * @summary Test that a call to getType() on an AnnotatedType returned from an
  28  *          Executable.getAnnotated* returns the same type as the corresponding
  29  *          Executable.getGeneric* call.
  30  * @run testng TestExecutableGetAnnotatedType
  31  */
  32 
  33 import org.testng.annotations.DataProvider;
  34 import org.testng.annotations.Test;
  35 
  36 import java.lang.annotation.*;
  37 import java.lang.reflect.*;
  38 import java.util.Arrays;
  39 import java.util.List;
  40 import java.util.stream.Collectors;
  41 import java.util.stream.Stream;
  42 
  43 import static org.testng.Assert.*;
  44 
  45 public class TestExecutableGetAnnotatedType {
  46     @Test(dataProvider = "genericExecutableData")
  47     public void testGenericMethodExceptions(Executable e) throws Exception {
  48         testExceptions(e);
  49     }
  50 
  51     @Test(dataProvider = "executableData")
  52     public void testMethodExceptions(Executable e) throws Exception {
  53         testExceptions(e);
  54     }
  55 
  56     @Test(dataProvider = "genericExecutableData")
  57     public void testGenericMethodParameterTypes(Executable e) throws Exception {
  58         testMethodParameters(e);
  59     }
  60 
  61     @Test(dataProvider = "executableData")
  62     public void testMethodParameterTypes(Executable e) throws Exception {
  63         testMethodParameters(e);
  64     }
  65 
  66     @Test(dataProvider = "genericExecutableData")
  67     public void testGenericParameterTypes(Executable e) throws Exception {
  68         testParameters(e.getParameters());
  69     }
  70 
  71     @Test(dataProvider = "executableData")
  72     public void testParameterTypes(Executable e) throws Exception {
  73         testParameters(e.getParameters());
  74     }
  75 
  76     // should test constructors as well, see JDK-8044629
  77     @Test(dataProvider = "genericMethodData")
  78     public void testGenericReceiverType(Executable e) throws Exception {
  79         testReceiverType0(e);
  80     }
  81 
  82     // should test constructors as well, see JDK-8044629
  83     @Test(dataProvider = "methodData")
  84     public void testReceiverType(Executable e) throws Exception {
  85         testReceiverType0(e);
  86     }
  87 
  88     @Test(dataProvider = "genericMethodData")
  89     public void testGenericMethodReturnType(Object o) throws Exception {
  90         // testng gets confused if the param to this method has type Method
  91         Method m = (Method)o;
  92         testReturnType(m);
  93     }
  94 
  95     @Test(dataProvider = "methodData")
  96     public void testMethodReturnType(Object o) throws Exception {
  97         // testng gets confused if the param to this method has type Method
  98         Method m = (Method)o;
  99         testReturnType(m);
 100     }
 101 
 102     private void testExceptions(Executable e) {
 103         Type[] ts = e.getGenericExceptionTypes();
 104         AnnotatedType[] ats = e.getAnnotatedExceptionTypes();
 105         assertEquals(ts.length, ats.length);
 106 
 107         for (int i = 0; i < ts.length; i++) {
 108             Type t = ts[i];
 109             AnnotatedType at = ats[i];
 110             assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
 111         }
 112     }
 113 
 114     private void testMethodParameters(Executable e) {
 115         Type[] ts = e.getGenericParameterTypes();
 116         AnnotatedType[] ats = e.getAnnotatedParameterTypes();
 117         assertEquals(ts.length, ats.length);
 118 
 119         for (int i = 0; i < ts.length; i++) {
 120             Type t = ts[i];
 121             AnnotatedType at = ats[i];
 122             assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
 123         }
 124     }
 125 
 126     private void testParameters(Parameter[] params) {
 127         for (Parameter p : params) {
 128             Type t = p.getParameterizedType();
 129             AnnotatedType at = p.getAnnotatedType();
 130             assertSame(at.getType(), t, p.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
 131         }
 132     }
 133 
 134     private void testReceiverType0(Executable e) {
 135         if (Modifier.isStatic(e.getModifiers()))
 136             assertNull(e.getAnnotatedReceiverType());
 137         else
 138             assertSame(e.getAnnotatedReceiverType().getType(), e.getDeclaringClass());
 139     }
 140 
 141     private void testReturnType(Method m) {
 142         Type t = m.getGenericReturnType();
 143         AnnotatedType at = m.getAnnotatedReturnType();
 144         assertSame(at.getType(), t, m.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
 145     }
 146 
 147     @DataProvider
 148     public Object[][] methodData() throws Exception {
 149         return filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class)
 150             .toArray(new Object[0][0]);
 151     }
 152 
 153     @DataProvider
 154     public Object[][] genericMethodData()  throws Exception {
 155         return filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class)
 156             .toArray(new Object[0][0]);
 157     }
 158 
 159     @DataProvider
 160     public Object[][] executableData() throws Exception {
 161     @SuppressWarnings("raw")
 162         List l = filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class);
 163         l.addAll(filterData(Arrays.stream(Methods1.class.getConstructors()), Methods1.class));
 164         l.addAll(filterData(Arrays.stream(Ctors1.class.getConstructors()), Ctors1.class));
 165         return ((List<Object[][]>)l).toArray(new Object[0][0]);
 166     }
 167 
 168     @DataProvider
 169     public Object[][] genericExecutableData() throws Exception {
 170     @SuppressWarnings("raw")
 171         List l = filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class);
 172         l.addAll(filterData(Arrays.stream(GenericMethods1.class.getConstructors()), GenericMethods1.class));
 173         l.addAll(filterData(Arrays.stream(GenericCtors1.class.getConstructors()), GenericCtors1.class));
 174         return ((List<Object[][]>)l).toArray(new Object[0][0]);
 175     }
 176 
 177     private List<?> filterData(Stream<? extends Executable> l, Class<?> c) {
 178         return l.filter(m -> (m.getDeclaringClass() == c)) // remove object methods
 179             .map(m -> { Object[] o = new Object[1]; o[0] = m; return o; })
 180             .collect(Collectors.toList());
 181     }
 182 
 183     @Retention(RetentionPolicy.RUNTIME)
 184     @Target(ElementType.TYPE_USE)
 185     public @interface TA {}
 186 
 187     @Retention(RetentionPolicy.RUNTIME)
 188     @Target(ElementType.TYPE_USE)
 189     public @interface TB {}
 190 
 191     @Retention(RetentionPolicy.RUNTIME)
 192     @Target(ElementType.TYPE_USE)
 193     public @interface TC {}
 194 
 195     public static class Methods1 {
 196         public static void m1() throws Error, RuntimeException {;}
 197         public static long m2(int a, double b) throws Error, RuntimeException { return 0L; }
 198         public static Object m3(String s, List l) throws Error, RuntimeException { return null; }
 199         public static Object m4(String s, List<String> l) { return null; }
 200         public static Object m4(String s, List<String> l, boolean ... b){ return null; }
 201 
 202         public static void m10() throws @TA Error, @TB @TC RuntimeException {;}
 203         public static @TB long m20(@TC int a, @TA double b) throws @TA Error, @TB @TC RuntimeException { return 0L; }
 204         public static @TC Object m30(@TA String s, @TB List l) throws @TA Error, @TB @TC RuntimeException { return null; }
 205         public static @TA Object m40(@TB String s, @TC List<@TA String> l) { return null; }
 206         public static @TA Object m40(@TB String s, @TC List<@TA String> l, @TB boolean ... b) { return null; }
 207 
 208         public Methods1(int a, double b) {}
 209         public Methods1(String s, List<String> l, boolean ... b) {}
 210         public Methods1(@TC long a, @TA float b) {}
 211         public Methods1(@TA int i, @TB String s, @TC List<@TA String> l, @TB boolean ... b) {}
 212     }
 213 
 214     // test default ctor
 215     public static class Ctors1 {
 216     }
 217 
 218     public static class GenericMethods1<E> {
 219         public E m1(E e, Object o) throws Error, RuntimeException { return null; }
 220         public E m2(List<? extends List> e, int i) throws Error, RuntimeException { return null; }
 221         public E m3(double d, List<E> e) throws Error, RuntimeException { return null; }
 222         public <E extends List> E m4(byte[] b, GenericMethods1<? extends E> e) { return null; }
 223         public <E extends List> E m5(GenericMethods1<? super Number> e) { return null; }
 224         public <E extends List & Cloneable> E m6(char c, E e) { return null; }
 225         public <E extends List & Cloneable> E m7(char c, E e, byte ... b) { return null; }
 226 
 227         public static <M> M n1(M e) { return null; }
 228         public static <M> M n2(List<? extends List> e) { return null; }
 229         public static <M extends RuntimeException> M n3(List<M> e) throws Error, M { return null; }
 230         public static <M extends Number> M n4(GenericMethods1<? extends M> e) throws Error, RuntimeException { return null; }
 231         public static <M extends Object> M n5(GenericMethods1<? super Number> e) { return null; }
 232         public static <M extends List & Cloneable> M n6(M e) { return null; }
 233 
 234         public <M> E o1(E e) { return null; }
 235         public <M> E o2(List<? extends List> e) { return null; }
 236         public <M extends Error, N extends RuntimeException> E o3(GenericMethods1<E> this, List<E> e) throws M, N { return null; }
 237         public <M extends Number> E o4(GenericMethods1<? extends E> e) throws Error, RuntimeException { return null; }
 238         public <M extends Object> E o5(GenericMethods1<? super Number> e) { return null; }
 239         public <M extends List & Cloneable> E o6(E e) { return null; }
 240 
 241 
 242         // with annotations
 243         public @TA E m10(E e, @TC Object o) throws @TA Error, @TB @TC RuntimeException { return null; }
 244         public @TB E m20(@TA List<@TA ? extends @TA List> e, @TC int i) throws @TA Error, @TB @TC RuntimeException { return null; }
 245         public @TB E m30(@TC double d, List<E> e) throws @TA Error, @TB @TC RuntimeException { return null; }
 246         public <@TA E extends @TA List> @TA E m40(@TA byte @TB [] b, GenericMethods1<@TA ? extends E> e) { return null; }
 247         public <@TB E extends @TB List> E m50(@TA GenericMethods1<? super Number> e) { return null; }
 248         public <@TB E extends @TA List & Cloneable> E m60(@TC char c, E e) { return null; }
 249         public <@TB E extends @TA List & Cloneable> E m70(@TC char c, E e, @TA @TB byte ... b) { return null; }
 250 
 251         public static <@TA M> @TA M n10(M e) { return null; }
 252         public static <@TA @TB @TC M> M n20(List<@TA ? extends List> e) { return null; }
 253         @TA @TB @TC public static <M extends RuntimeException> M n30(List<@TB M> e) throws @TA Error, @TB @TC M { return null; }
 254         public static <@TC M extends Number> M n40(GenericMethods1<? extends @TA M> e) throws @TA Error, @TB @TC RuntimeException { return null; }
 255         @TA public static <M extends @TB Object> M n50(GenericMethods1<? super Number> e) { return null; }
 256         public static <@TA M extends @TB List & @TC @TB Cloneable> M n60(M e) { return null; }
 257 
 258         public <@TC M> E o10(@TA E e) { return null; }
 259         public <M> @TA E o20(@TB List<@TB ? extends @TB List> e) { return null; }
 260         @TC public <M extends Error, N extends RuntimeException> @TB E o30(@TA @TB @TC GenericMethods1<E> this, List<E> e) throws @TA M, @TB @TC N { return null; }
 261         public <@TA M extends Number> E o40(GenericMethods1<? extends @TA E> e) throws @TA Error, @TB @TC RuntimeException { return null; }
 262         public <M extends @TA Object> E o50(GenericMethods1<@TA ? super Number> e) { return null; }
 263         public <@TA M extends @TB List & @TC Cloneable> E o60(@TA E e) { return null; }
 264 
 265 
 266         // ctors
 267         public GenericMethods1(List<? extends List> e, int i) throws Error, RuntimeException { }
 268         public <E extends List & Cloneable> GenericMethods1(char c, E e, byte ... b) { }
 269         @TC public <M extends Error, N extends RuntimeException> GenericMethods1(List<@TC E> e) throws @TA M, @TB @TC N { }
 270         public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m) throws @TA Exception { }
 271         public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m, @TC byte ... b) throws Exception { }
 272     }
 273 
 274     // test default ctor
 275     public static class GenericCtors1<T> {
 276     }
 277 }