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     @Test(dataProvider = "genericMethodData")
  77     public void testGenericReceiverType(Executable e) throws Exception {
  78         testReceiverType0(e);
  79     }
  80 
  81     @Test(dataProvider = "methodData")
  82     public void testReceiverType(Executable e) throws Exception {
  83         testReceiverType0(e);
  84     }
  85 
  86     @Test(dataProvider = "genericMethodData")
  87     public void testGenericMethodReturnType(Object o) throws Exception {
  88         // testng gets confused if the param to this method has type Method
  89         Method m = (Method)o;
  90         testReturnType(m);
  91     }
  92 
  93     @Test(dataProvider = "methodData")
  94     public void testMethodReturnType(Object o) throws Exception {
  95         // testng gets confused if the param to this method has type Method
  96         Method m = (Method)o;
  97         testReturnType(m);
  98     }
  99 
 100     private void testExceptions(Executable e) {
 101         Type[] ts = e.getGenericExceptionTypes();
 102         AnnotatedType[] ats = e.getAnnotatedExceptionTypes();
 103         assertEquals(ts.length, ats.length);
 104 
 105         for (int i = 0; i < ts.length; i++) {
 106             Type t = ts[i];
 107             AnnotatedType at = ats[i];
 108             assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
 109         }
 110     }
 111 
 112     private void testMethodParameters(Executable e) {
 113         Type[] ts = e.getGenericParameterTypes();
 114         AnnotatedType[] ats = e.getAnnotatedParameterTypes();
 115         assertEquals(ts.length, ats.length);
 116 
 117         for (int i = 0; i < ts.length; i++) {
 118             Type t = ts[i];
 119             AnnotatedType at = ats[i];
 120             assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
 121         }
 122     }
 123 
 124     private void testParameters(Parameter[] params) {
 125         for (Parameter p : params) {
 126             Type t = p.getParameterizedType();
 127             AnnotatedType at = p.getAnnotatedType();
 128             assertSame(at.getType(), t, p.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
 129         }
 130     }
 131 
 132     private void testReceiverType0(Executable e) {
 133         if (Modifier.isStatic(e.getModifiers()))
 134             assertNull(e.getAnnotatedReceiverType());
 135         else
 136             assertSame(e.getAnnotatedReceiverType().getType(), e.getDeclaringClass());
 137     }
 138 
 139     private void testReturnType(Method m) {
 140         Type t = m.getGenericReturnType();
 141         AnnotatedType at = m.getAnnotatedReturnType();
 142         assertSame(at.getType(), t, m.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n");
 143     }
 144 
 145     @DataProvider
 146     public Object[][] methodData() throws Exception {
 147         return filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class)
 148             .toArray(new Object[0][0]);
 149     }
 150 
 151     @DataProvider
 152     public Object[][] genericMethodData()  throws Exception {
 153         return filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class)
 154             .toArray(new Object[0][0]);
 155     }
 156 
 157     @DataProvider
 158     public Object[][] executableData() throws Exception {
 159     @SuppressWarnings("raw")
 160         List l = filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class);
 161         l.addAll(filterData(Arrays.stream(Methods1.class.getConstructors()), Methods1.class));
 162         l.addAll(filterData(Arrays.stream(Ctors1.class.getConstructors()), Ctors1.class));
 163         return ((List<Object[][]>)l).toArray(new Object[0][0]);
 164     }
 165 
 166     @DataProvider
 167     public Object[][] genericExecutableData() throws Exception {
 168     @SuppressWarnings("raw")
 169         List l = filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class);
 170         l.addAll(filterData(Arrays.stream(GenericMethods1.class.getConstructors()), GenericMethods1.class));
 171         l.addAll(filterData(Arrays.stream(GenericCtors1.class.getConstructors()), GenericCtors1.class));
 172         return ((List<Object[][]>)l).toArray(new Object[0][0]);
 173     }
 174 
 175     private List<?> filterData(Stream<? extends Executable> l, Class<?> c) {
 176         return l.filter(m -> (m.getDeclaringClass() == c)) // remove object methods
 177             .map(m -> { Object[] o = new Object[1]; o[0] = m; return o; })
 178             .collect(Collectors.toList());
 179     }
 180 
 181     @Retention(RetentionPolicy.RUNTIME)
 182     @Target(ElementType.TYPE_USE)
 183     public @interface TA {}
 184 
 185     @Retention(RetentionPolicy.RUNTIME)
 186     @Target(ElementType.TYPE_USE)
 187     public @interface TB {}
 188 
 189     @Retention(RetentionPolicy.RUNTIME)
 190     @Target(ElementType.TYPE_USE)
 191     public @interface TC {}
 192 
 193     public static class Methods1 {
 194         public static void m1() throws Error, RuntimeException {;}
 195         public static long m2(int a, double b) throws Error, RuntimeException { return 0L; }
 196         public static Object m3(String s, List l) throws Error, RuntimeException { return null; }
 197         public static Object m4(String s, List<String> l) { return null; }
 198         public static Object m4(String s, List<String> l, boolean ... b){ return null; }
 199 
 200         public static void m10() throws @TA Error, @TB @TC RuntimeException {;}
 201         public static @TB long m20(@TC int a, @TA double b) throws @TA Error, @TB @TC RuntimeException { return 0L; }
 202         public static @TC Object m30(@TA String s, @TB List l) throws @TA Error, @TB @TC RuntimeException { return null; }
 203         public static @TA Object m40(@TB String s, @TC List<@TA String> l) { return null; }
 204         public static @TA Object m40(@TB String s, @TC List<@TA String> l, @TB boolean ... b) { return null; }
 205 
 206         public Methods1(int a, double b) {}
 207         public Methods1(String s, List<String> l, boolean ... b) {}
 208         public Methods1(@TC long a, @TA float b) {}
 209         public Methods1(@TA int i, @TB String s, @TC List<@TA String> l, @TB boolean ... b) {}
 210     }
 211 
 212     // test default ctor
 213     public static class Ctors1 {
 214     }
 215 
 216     public static class GenericMethods1<E> {
 217         public E m1(E e, Object o) throws Error, RuntimeException { return null; }
 218         public E m2(List<? extends List> e, int i) throws Error, RuntimeException { return null; }
 219         public E m3(double d, List<E> e) throws Error, RuntimeException { return null; }
 220         public <E extends List> E m4(byte[] b, GenericMethods1<? extends E> e) { return null; }
 221         public <E extends List> E m5(GenericMethods1<? super Number> e) { return null; }
 222         public <E extends List & Cloneable> E m6(char c, E e) { return null; }
 223         public <E extends List & Cloneable> E m7(char c, E e, byte ... b) { return null; }
 224 
 225         public static <M> M n1(M e) { return null; }
 226         public static <M> M n2(List<? extends List> e) { return null; }
 227         public static <M extends RuntimeException> M n3(List<M> e) throws Error, M { return null; }
 228         public static <M extends Number> M n4(GenericMethods1<? extends M> e) throws Error, RuntimeException { return null; }
 229         public static <M extends Object> M n5(GenericMethods1<? super Number> e) { return null; }
 230         public static <M extends List & Cloneable> M n6(M e) { return null; }
 231 
 232         public <M> E o1(E e) { return null; }
 233         public <M> E o2(List<? extends List> e) { return null; }
 234         public <M extends Error, N extends RuntimeException> E o3(GenericMethods1<E> this, List<E> e) throws M, N { return null; }
 235         public <M extends Number> E o4(GenericMethods1<? extends E> e) throws Error, RuntimeException { return null; }
 236         public <M extends Object> E o5(GenericMethods1<? super Number> e) { return null; }
 237         public <M extends List & Cloneable> E o6(E e) { return null; }
 238 
 239 
 240         // with annotations
 241         public @TA E m10(E e, @TC Object o) throws @TA Error, @TB @TC RuntimeException { return null; }
 242         public @TB E m20(@TA List<@TA ? extends @TA List> e, @TC int i) throws @TA Error, @TB @TC RuntimeException { return null; }
 243         public @TB E m30(@TC double d, List<E> e) throws @TA Error, @TB @TC RuntimeException { return null; }
 244         public <@TA E extends @TA List> @TA E m40(@TA byte @TB [] b, GenericMethods1<@TA ? extends E> e) { return null; }
 245         public <@TB E extends @TB List> E m50(@TA GenericMethods1<? super Number> e) { return null; }
 246         public <@TB E extends @TA List & Cloneable> E m60(@TC char c, E e) { return null; }
 247         public <@TB E extends @TA List & Cloneable> E m70(@TC char c, E e, @TA @TB byte ... b) { return null; }
 248 
 249         public static <@TA M> @TA M n10(M e) { return null; }
 250         public static <@TA @TB @TC M> M n20(List<@TA ? extends List> e) { return null; }
 251         @TA @TB @TC public static <M extends RuntimeException> M n30(List<@TB M> e) throws @TA Error, @TB @TC M { return null; }
 252         public static <@TC M extends Number> M n40(GenericMethods1<? extends @TA M> e) throws @TA Error, @TB @TC RuntimeException { return null; }
 253         @TA public static <M extends @TB Object> M n50(GenericMethods1<? super Number> e) { return null; }
 254         public static <@TA M extends @TB List & @TC @TB Cloneable> M n60(M e) { return null; }
 255 
 256         public <@TC M> E o10(@TA E e) { return null; }
 257         public <M> @TA E o20(@TB List<@TB ? extends @TB List> e) { return null; }
 258         @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; }
 259         public <@TA M extends Number> E o40(GenericMethods1<? extends @TA E> e) throws @TA Error, @TB @TC RuntimeException { return null; }
 260         public <M extends @TA Object> E o50(GenericMethods1<@TA ? super Number> e) { return null; }
 261         public <@TA M extends @TB List & @TC Cloneable> E o60(@TA E e) { return null; }
 262 
 263 
 264         // ctors
 265         public GenericMethods1(List<? extends List> e, int i) throws Error, RuntimeException { }
 266         public <E extends List & Cloneable> GenericMethods1(char c, E e, byte ... b) { }
 267         @TC public <M extends Error, N extends RuntimeException> GenericMethods1(List<@TC E> e) throws @TA M, @TB @TC N { }
 268         public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m) throws @TA Exception { }
 269         public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m, @TC byte ... b) throws Exception { }
 270     }
 271 
 272     // test default ctor
 273     public static class GenericCtors1<T> {
 274     }
 275 }