1 /*
  2  * Copyright (c) 2024, 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 import org.testng.Assert;
 25 import org.testng.annotations.DataProvider;
 26 import org.testng.annotations.Test;
 27 
 28 import java.lang.constant.ClassDesc;
 29 import java.lang.constant.ConstantDescs;
 30 import java.lang.invoke.MethodHandles;
 31 import java.lang.reflect.Field;
 32 import java.lang.reflect.Type;
 33 import java.lang.reflect.code.type.ArrayType;
 34 import java.lang.reflect.code.type.ClassType;
 35 import java.lang.reflect.code.type.JavaType;
 36 import java.util.ArrayList;
 37 import java.util.List;
 38 import java.util.Map;
 39 import java.util.stream.Stream;
 40 
 41 
 42 /*
 43  * @test
 44  * @run testng TestJavaType
 45  */
 46 
 47 public class TestJavaType {
 48 
 49     @DataProvider
 50     public Object[][] JavaTypes() {
 51         return new Object[][]{
 52                 {"boolean", "Z"},
 53                 {"byte", "B"},
 54                 {"char", "C"},
 55                 {"short", "S"},
 56                 {"int", "I"},
 57                 {"long", "J"},
 58                 {"float", "F"},
 59                 {"double", "D"},
 60                 {"void", "V"},
 61                 {"int[]", "[I"},
 62                 {"int[][][][]", "[[[[I"},
 63                 {"java.lang.String", "Ljava/lang/String;"},
 64                 {"java.lang.String[][]", "[[Ljava/lang/String;"},
 65                 {"a.b.C$D", "La/b/C$D;"},
 66         };
 67     }
 68 
 69     @Test(dataProvider = "JavaTypes")
 70     public void testJavaType(String tds, String bcd) {
 71         JavaType jt = JavaType.ofString(tds);
 72         Assert.assertEquals(jt.toString(), tds);
 73         Assert.assertEquals(jt.toNominalDescriptor().descriptorString(), bcd);
 74         Assert.assertEquals(jt, JavaType.type(ClassDesc.ofDescriptor(bcd)));
 75     }
 76 
 77     @DataProvider
 78     public Object[][] classDescriptors() {
 79         return new Object[][]{
 80                 {"java.lang.String", "java.lang.String"},
 81         };
 82     }
 83 
 84     @Test(dataProvider = "classDescriptors")
 85     public void classDescriptor(String tds, String bcd) {
 86         ClassType jt = (ClassType)JavaType.ofString(tds);
 87         Assert.assertEquals(jt.toString(), tds);
 88         Assert.assertEquals(jt.toClassName(), bcd);
 89     }
 90 
 91 
 92     @DataProvider
 93     public Object[][] basicJavaTypes() {
 94         return new Object[][]{
 95                 {"boolean", "int"},
 96                 {"byte", "int"},
 97                 {"char", "int"},
 98                 {"short", "int"},
 99                 {"int", "int"},
100                 {"long", "long"},
101                 {"float", "float"},
102                 {"double", "double"},
103                 {"void", "void"},
104                 {"int[]", "java.lang.Object"},
105                 {"int[][][][]", "java.lang.Object"},
106                 {"java.lang.String", "java.lang.Object"},
107                 {"java.lang.String[][]", "java.lang.Object"},
108                 {"a.b.C$D", "java.lang.Object"},
109                 {"java.util.List<T>", "java.lang.Object"},
110                 {"java.util.List<T>[]", "java.lang.Object"},
111         };
112     }
113 
114     @Test(dataProvider = "basicJavaTypes")
115     public void testBasicJavaType(String tds, String btds) {
116         JavaType jt = JavaType.ofString(tds);
117         Assert.assertEquals(jt.toString(), tds);
118         Assert.assertEquals(jt.toBasicType().toString(), btds);
119     }
120 
121 
122     @DataProvider
123     public Object[][] argumentJavaTypes() {
124         return new Object[][]{
125                 {"java.util.List<T>", "T"},
126                 {"java.util.List<T>[]", "T"},
127                 {"java.util.List<java.util.function.Supplier<T>>", "java.util.function.Supplier<T>"},
128                 {"java.util.List<java.util.function.Supplier<T>>[][]", "java.util.function.Supplier<T>"},
129                 {"java.util.Map<K, V>", "K", "V"},
130                 {"ab<cd<S<T, V>, N>>", "cd<S<T, V>, N>"},
131                 {"java.util.Consumer<java.util.Function<String, Number>>", "java.util.Function<String, Number>"},
132         };
133     }
134 
135     @Test(dataProvider = "argumentJavaTypes")
136     public void testArgumentJavaType(String tds, String... argTypes) {
137         JavaType jt = JavaType.ofString(tds);
138         Assert.assertEquals(jt.toString(), tds);
139 
140         while (jt instanceof ArrayType) {
141             jt = ((ArrayType)jt).componentType();
142         }
143         ClassType ct = (ClassType)jt;
144 
145         Assert.assertEquals(argTypes.length, ct.typeArguments().size());
146 
147         Assert.assertEquals(ct.typeArguments(), Stream.of(argTypes).map(JavaType::ofString).toList());
148     }
149 
150     @Test(dataProvider = "classDescs")
151     public void testClassDescRoundTrip(ClassDesc classDesc) {
152         Assert.assertEquals(classDesc, JavaType.type(classDesc).toNominalDescriptor());
153     }
154 
155     @DataProvider
156     public Object[][] classDescs() throws ReflectiveOperationException {
157         List<Object[]> classDescs = new ArrayList<>();
158         for (Field f : ConstantDescs.class.getDeclaredFields()) {
159             if (f.getName().startsWith("CD_")) {
160                 ClassDesc cd = (ClassDesc)f.get(null);
161                 classDescs.add(new Object[] { cd });
162                 if (!cd.equals(ConstantDescs.CD_void)) {
163                     classDescs.add(new Object[]{cd.arrayType()});
164                     classDescs.add(new Object[]{cd.arrayType().arrayType()});
165                 }
166             }
167         }
168         return classDescs.stream().toArray(Object[][]::new);
169     }
170 
171     @Test(dataProvider = "types")
172     public void testTypeRoundTrip(Type type) throws ReflectiveOperationException {
173         Assert.assertEquals(type, JavaType.type(type).resolve(MethodHandles.lookup()));
174     }
175 
176     @DataProvider
177     public Object[][] types() throws ReflectiveOperationException {
178         List<Object[]> types = new ArrayList<>();
179         for (Field f : TypeHolder.class.getDeclaredFields()) {
180             types.add(new Object[] { f.getGenericType() });
181         }
182         return types.stream().toArray(Object[][]::new);
183     }
184 
185     static class TypeHolder<X extends Number> {
186         boolean p1;
187         char p2;
188         byte p3;
189         short p4;
190         int p5;
191         long p6;
192         float p7;
193         double p8;
194 
195         boolean[] ap1;
196         char[] ap2;
197         byte[] ap3;
198         short[] ap4;
199         int[] ap5;
200         long[] ap6;
201         float[] ap7;
202         double[] ap8;
203 
204         boolean[][] aap1;
205         char[][] aap2;
206         byte[][] aap3;
207         short[][] aap4;
208         int[][] aap5;
209         long[][] aap6;
210         float[][] aap7;
211         double[][] aap8;
212 
213         String r1;
214         Map<String, String> r2;
215         Map<String, ?  extends String> r3;
216         Map<? extends String, String> r4;
217         Map<? extends String, ?  extends String> r5;
218         Map<? extends List<? extends String>, ? super List<? extends String>> r6;
219         Map<? extends List<? extends String>[], ? super List<? extends String>[]> r7;
220         List<boolean[]> r8;
221         List<char[]> r9;
222         List<byte[]> r10;
223         List<short[]> r11;
224         List<int[]> r12;
225         List<long[]> r13;
226         List<float[]> r14;
227         List<double[]> r15;
228 
229         String[] ar1;
230         Map<String, String>[] ar2;
231         Map<String, ?  extends String>[] ar3;
232         Map<? extends String, String>[] ar4;
233         Map<? extends String, ?  extends String>[] ar5;
234         Map<? extends List<? extends String>, ? super List<? extends String>>[] ar6;
235         Map<? extends List<? extends String>[], ? super List<? extends String>[]>[] ar7;
236         List<boolean[]>[] ar8;
237         List<char[]>[] ar9;
238         List<byte[]>[] ar10;
239         List<short[]>[] ar11;
240         List<int[]>[] ar12;
241         List<long[]>[] ar13;
242         List<float[]>[] ar14;
243         List<double[]>[] ar15;
244 
245         String[][] aar1;
246         Map<String, String>[][] aar2;
247         Map<String, ?  extends String>[][] aar3;
248         Map<? extends String, String>[][] aar4;
249         Map<? extends String, ?  extends String>[][] aar5;
250         Map<? extends List<? extends String>, ? super List<? extends String>>[][] aar6;
251         Map<? extends List<? extends String>[], ? super List<? extends String>[]>[][] aar7;
252         List<boolean[]>[][] aar8;
253         List<char[]>[][] aar9;
254         List<byte[]>[][] aar10;
255         List<short[]>[][] aar11;
256         List<int[]>[][] aar12;
257         List<long[]>[][] aar13;
258         List<float[]>[][] aar14;
259         List<double[]>[][] aar15;
260 
261         X x1;
262         Map<X, X> x2;
263         Map<X, ?  extends X> x3;
264         Map<? extends X, X> x4;
265         Map<? extends X, ?  extends X> x5;
266         Map<? extends List<? extends X>, ? super List<? extends X>> x6;
267         Map<? extends List<? extends X>[], ? super List<? extends X>[]> x7;
268         List<X[]> x8;
269 
270         X[] ax1;
271         Map<X, X>[] ax2;
272         Map<X, ?  extends X>[] ax3;
273         Map<? extends X, X>[] ax4;
274         Map<? extends X, ?  extends X>[] ax5;
275         Map<? extends List<? extends X>, ? super List<? extends X>>[] ax6;
276         Map<? extends List<? extends X>[], ? super List<? extends X>[]>[] ax7;
277         List<X[]>[] ax8;
278 
279         X[][] aax1;
280         Map<X, X>[][] aax2;
281         Map<X, ?  extends X>[][] aax3;
282         Map<? extends X, X>[][] aax4;
283         Map<? extends X, ?  extends X>[][] aax5;
284         Map<? extends List<? extends X>, ? super List<? extends X>>[][] aax6;
285         Map<? extends List<? extends X>[], ? super List<? extends X>[]>[][] aax7;
286         List<X[]>[][] aax8;
287     }
288 }