View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.reflect;
18  
19  import static org.junit.jupiter.api.Assertions.assertArrayEquals;
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  import static org.junit.jupiter.api.Assumptions.assumeTrue;
26  
27  import java.awt.Insets;
28  import java.io.Serializable;
29  import java.lang.reflect.Constructor;
30  import java.lang.reflect.Field;
31  import java.lang.reflect.GenericArrayType;
32  import java.lang.reflect.Method;
33  import java.lang.reflect.ParameterizedType;
34  import java.lang.reflect.Type;
35  import java.lang.reflect.TypeVariable;
36  import java.lang.reflect.WildcardType;
37  import java.net.URI;
38  import java.util.ArrayList;
39  import java.util.Arrays;
40  import java.util.Collection;
41  import java.util.Collections;
42  import java.util.Comparator;
43  import java.util.HashMap;
44  import java.util.List;
45  import java.util.Map;
46  import java.util.Properties;
47  import java.util.TreeSet;
48  
49  import org.apache.commons.lang3.AbstractLangTest;
50  import org.apache.commons.lang3.JavaVersion;
51  import org.apache.commons.lang3.SystemUtils;
52  import org.apache.commons.lang3.reflect.testbed.Foo;
53  import org.apache.commons.lang3.reflect.testbed.GenericParent;
54  import org.apache.commons.lang3.reflect.testbed.GenericTypeHolder;
55  import org.apache.commons.lang3.reflect.testbed.StringParameterizedChild;
56  import org.junit.jupiter.api.Disabled;
57  import org.junit.jupiter.api.Test;
58  
59  class AAAClass extends AAClass<String> {
60      public class BBBClass extends BBClass<String> {
61          // empty
62      }
63  }
64  
65  @SuppressWarnings("unused") // Unused type parameter for test
66  class AAClass<T> {
67  
68      public class BBClass<S> {
69          // empty
70      }
71  }
72  
73  @SuppressWarnings("rawtypes")
74  //raw types, where used, are used purposely
75  class AClass extends AAClass<String>.BBClass<Number> {
76  
77      @SuppressWarnings("unused") // Unused type parameter for test
78      public interface AInterface<T> {
79          // empty
80      }
81  
82      @SuppressWarnings("unused") // Unused type parameter for test
83      public class BClass<T> {
84          // empty
85      }
86  
87      @SuppressWarnings("unused") // Unused type parameter for test
88      public class CClass<T> extends BClass {
89          // empty
90      }
91  
92      @SuppressWarnings("unused") // Unused type parameter for test
93      public class DClass<T> extends CClass<T> {
94          // empty
95      }
96  
97      @SuppressWarnings("unused") // Unused type parameter for test
98      public class EClass<T> extends DClass {
99          // empty
100     }
101 
102     public class FClass extends EClass<String> {
103         // empty
104     }
105 
106     public class GClass<T extends BClass<? extends T> & AInterface<AInterface<? super T>>> {
107         // empty
108     }
109 
110     public BClass<Number> bClass;
111 
112     public CClass<? extends String> cClass;
113 
114     public DClass<String> dClass;
115 
116     public EClass<String> eClass;
117 
118     public FClass fClass;
119 
120     public GClass gClass;
121 
122     AClass(final AAClass<String> enclosingInstance) {
123         enclosingInstance.super();
124     }
125 }
126 @SuppressWarnings("rawtypes")
127 abstract class Test1<G> {
128     public abstract Object m0();
129     public abstract String[] m1();
130     public abstract <K, V> Map<? extends K, V[]> m10();
131     public abstract <K, V> Map<? extends K, List<V[]>> m11();
132     public abstract List m12();
133     public abstract Map m13();
134     public abstract Properties m14();
135     public abstract G m15();
136     public abstract List<G> m16();
137     public abstract Enum m17();
138     public abstract <E> E[] m2();
139     public abstract <E> List<? extends E> m3();
140     public abstract <E extends Enum<E>> List<? extends Enum<E>> m4();
141     public abstract List<? extends Enum<?>> m5();
142     public abstract List<? super Enum<?>> m6();
143     public abstract List<?> m7();
144     public abstract Map<? extends Enum<?>, ? super Enum<?>> m8();
145     public abstract <K, V> Map<? extends K, ? super V[]> m9();
146 }
147 
148 /**
149  * Test TypeUtils
150  */
151 @SuppressWarnings({ "unchecked", "unused", "rawtypes" })
152 //raw types, where used, are used purposely
153 public class TypeUtilsTest<B> extends AbstractLangTest {
154 
155     public interface And<K, V> extends This<Number, Number> {
156     }
157 
158     public static class ClassWithSuperClassWithGenericType extends ArrayList<Object> {
159         private static final long serialVersionUID = 1L;
160 
161         public static <U> Iterable<U> methodWithGenericReturnType() {
162             return null;
163         }
164     }
165 
166     public class Other<T> implements This<String, T> {
167     }
168 
169     public class Tester implements This<String, B> {
170     }
171 
172     public class That<K, V> implements This<K, V> {
173     }
174 
175     public class The<K, V> extends That<Number, Number> implements And<String, String> {
176     }
177 
178     public class Thing<Q> extends Other<B> {
179     }
180 
181     public interface This<K, V> {
182     }
183 
184     public static Comparable<String> stringComparable;
185 
186     public static Comparable<URI> uriComparable;
187 
188     public static Comparable<Integer> intComparable;
189 
190     public static Comparable<Long> longComparable;
191 
192     public static Comparable<?> wildcardComparable;
193 
194     public static URI uri;
195 
196     public static List<String>[] stringListArray;
197 
198     public static <G extends Comparable<G>> G stub() {
199         return null;
200     }
201 
202     public static <G extends Comparable<? super G>> G stub2() {
203         return null;
204     }
205 
206     public static <T extends Comparable<? extends T>> T stub3() {
207         return null;
208     }
209 
210     public This<String, String> dis;
211 
212     public That<String, String> dat;
213 
214     public The<String, String> da;
215 
216     public Other<String> uhder;
217 
218     public Thing ding;
219 
220     public TypeUtilsTest<String>.Tester tester;
221 
222     public Tester tester2;
223 
224     public TypeUtilsTest<String>.That<String, String> dat2;
225 
226     public TypeUtilsTest<Number>.That<String, String> dat3;
227 
228     public Comparable<? extends Integer>[] intWildcardComparable;
229 
230     public Iterable<? extends Map<Integer, ? extends Collection<?>>> iterable;
231 
232     public void delegateBooleanAssertion(final Type[] types, final int i2, final int i1, final boolean expected) {
233         final Type type1 = types[i1];
234         final Type type2 = types[i2];
235         final boolean isAssignable = TypeUtils.isAssignable(type2, type1);
236 
237         if (expected) {
238             assertTrue(isAssignable,
239                     "[" + i1 + ", " + i2 + "]: From "
240                                 + String.valueOf(type2) + " to "
241                                 + String.valueOf(type1));
242         } else {
243             assertFalse(isAssignable,
244                     "[" + i1 + ", " + i2 + "]: From "
245                                 + String.valueOf(type2) + " to "
246                                 + String.valueOf(type1));
247         }
248     }
249 
250     public void dummyMethod(final List list0, final List<Object> list1, final List<?> list2,
251             final List<? super Object> list3, final List<String> list4, final List<? extends String> list5,
252             final List<? super String> list6, final List[] list7, final List<Object>[] list8, final List<?>[] list9,
253             final List<? super Object>[] list10, final List<String>[] list11, final List<? extends String>[] list12,
254             final List<? super String>[] list13) {
255     }
256 
257     @Test
258     public void test_LANG_1114() throws Exception {
259         final Type nonWildcardType = getClass().getDeclaredField("wildcardComparable").getGenericType();
260         final Type wildcardType = ((ParameterizedType) nonWildcardType).getActualTypeArguments()[0];
261 
262         assertFalse(TypeUtils.equals(wildcardType, nonWildcardType));
263         assertFalse(TypeUtils.equals(nonWildcardType, wildcardType));
264     }
265 
266     @Test
267     public void test_LANG_1190() throws Exception {
268         final Type fromType = ClassWithSuperClassWithGenericType.class.getDeclaredMethod("methodWithGenericReturnType").getGenericReturnType();
269         final Type failingToType = TypeUtils.wildcardType().withLowerBounds(ClassWithSuperClassWithGenericType.class).build();
270 
271         assertTrue(TypeUtils.isAssignable(fromType, failingToType));
272     }
273 
274     @Test
275     public void test_LANG_1348() throws Exception {
276         final Method method = Enum.class.getMethod("valueOf", Class.class, String.class);
277         assertEquals("T extends java.lang.Enum<T>", TypeUtils.toString(method.getGenericReturnType()));
278     }
279 
280     /**
281      * <pre>{@code
282      * java.lang.StackOverflowError
283     at org.apache.commons.lang3.reflect.TypeUtils.typeVariableToString(TypeUtils.java:1785)
284     at org.apache.commons.lang3.reflect.TypeUtils.toString(TypeUtils.java:1737)
285     at org.apache.commons.lang3.reflect.TypeUtils.toString(TypeUtils.java:1714)
286     at org.apache.commons.lang3.reflect.TypeUtils.appendAllTo(TypeUtils.java:302)
287     at org.apache.commons.lang3.reflect.TypeUtils.wildcardTypeToString(TypeUtils.java:1902)
288     at org.apache.commons.lang3.reflect.TypeUtils.toString(TypeUtils.java:1734)
289     at org.apache.commons.lang3.reflect.TypeUtils.toString(TypeUtils.java:1714)
290     at org.apache.commons.lang3.reflect.TypeUtils.appendAllTo(TypeUtils.java:302)
291     at org.apache.commons.lang3.reflect.TypeUtils.parameterizedTypeToString(TypeUtils.java:1604)
292     at org.apache.commons.lang3.reflect.TypeUtils.toString(TypeUtils.java:1731)
293     at org.apache.commons.lang3.reflect.TypeUtils.toString(TypeUtils.java:1714)
294     at org.apache.commons.lang3.reflect.TypeUtils.appendAllTo(TypeUtils.java:302)
295     at org.apache.commons.lang3.reflect.TypeUtils.typeVariableToString(TypeUtils.java:1789)
296      * }
297      * </pre>
298      */
299     @Test
300     public void test_LANG_1698() {
301         // SO on Java 17
302         assumeTrue(SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_16));
303         final ParameterizedType comparing = (ParameterizedType) Arrays.stream(Comparator.class.getDeclaredMethods())
304                 .filter(k -> k.getName().equals("comparing")).findFirst()
305                 .orElse(Comparator.class.getDeclaredMethods()[0]).getGenericParameterTypes()[0];
306         final String typeName = TypeUtils
307                 .parameterize((Class<?>) comparing.getRawType(), comparing.getActualTypeArguments()).getTypeName();
308         assertEquals("java.util.function.Function<? super T, ? extends U>", typeName);
309     }
310 
311     @Test
312     public void test_LANG_820() {
313         final Type[] typeArray = {String.class, String.class};
314         final Type[] expectedArray = {String.class};
315         assertArrayEquals(expectedArray, TypeUtils.normalizeUpperBounds(typeArray));
316     }
317 
318     @Test
319     public void testContainsTypeVariables() throws Exception {
320         assertFalse(TypeUtils.containsTypeVariables(Test1.class.getMethod("m0").getGenericReturnType()));
321         assertFalse(TypeUtils.containsTypeVariables(Test1.class.getMethod("m1").getGenericReturnType()));
322         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m2").getGenericReturnType()));
323         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m3").getGenericReturnType()));
324         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m4").getGenericReturnType()));
325         assertFalse(TypeUtils.containsTypeVariables(Test1.class.getMethod("m5").getGenericReturnType()));
326         assertFalse(TypeUtils.containsTypeVariables(Test1.class.getMethod("m6").getGenericReturnType()));
327         assertFalse(TypeUtils.containsTypeVariables(Test1.class.getMethod("m7").getGenericReturnType()));
328         assertFalse(TypeUtils.containsTypeVariables(Test1.class.getMethod("m8").getGenericReturnType()));
329         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m9").getGenericReturnType()));
330         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m10").getGenericReturnType()));
331         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m11").getGenericReturnType()));
332         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m12").getGenericReturnType()));
333         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m13").getGenericReturnType()));
334         assertFalse(TypeUtils.containsTypeVariables(Test1.class.getMethod("m14").getGenericReturnType()));
335         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m15").getGenericReturnType()));
336         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m16").getGenericReturnType()));
337         assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m17").getGenericReturnType()));
338     }
339 
340     @Test
341     public void testDetermineTypeVariableAssignments() throws SecurityException,
342             NoSuchFieldException {
343         final ParameterizedType iterableType = (ParameterizedType) getClass().getField("iterable")
344                 .getGenericType();
345         final Map<TypeVariable<?>, Type> typeVarAssigns = TypeUtils.determineTypeArguments(TreeSet.class,
346                 iterableType);
347         final TypeVariable<?> treeSetTypeVar = TreeSet.class.getTypeParameters()[0];
348         assertTrue(typeVarAssigns.containsKey(treeSetTypeVar));
349         assertEquals(iterableType.getActualTypeArguments()[0], typeVarAssigns
350                 .get(treeSetTypeVar));
351 
352         assertThrows(NullPointerException.class,
353                 () -> TypeUtils.determineTypeArguments(TreeSet.class, null));
354         assertThrows(NullPointerException.class,
355                 () -> TypeUtils.determineTypeArguments(null, iterableType));
356     }
357 
358     @Test
359     public void testGenericArrayType() throws Exception {
360         final Type expected = getClass().getField("intWildcardComparable").getGenericType();
361         final GenericArrayType actual =
362             TypeUtils.genericArrayType(TypeUtils.parameterize(Comparable.class, TypeUtils.wildcardType()
363                 .withUpperBounds(Integer.class).build()));
364         assertTrue(TypeUtils.equals(expected, actual));
365         assertEquals("java.lang.Comparable<? extends java.lang.Integer>[]", actual.toString());
366     }
367 
368     @Test
369     public void testGetArrayComponentType() throws Exception {
370         final Method method = getClass().getMethod("dummyMethod", List.class, List.class, List.class,
371                 List.class, List.class, List.class, List.class, List[].class, List[].class,
372                 List[].class, List[].class, List[].class, List[].class, List[].class);
373 
374         final Type[] types = method.getGenericParameterTypes();
375 
376         assertNull(TypeUtils.getArrayComponentType(types[0]));
377         assertNull(TypeUtils.getArrayComponentType(types[1]));
378         assertNull(TypeUtils.getArrayComponentType(types[2]));
379         assertNull(TypeUtils.getArrayComponentType(types[3]));
380         assertNull(TypeUtils.getArrayComponentType(types[4]));
381         assertNull(TypeUtils.getArrayComponentType(types[5]));
382         assertNull(TypeUtils.getArrayComponentType(types[6]));
383         assertEquals(types[0], TypeUtils.getArrayComponentType(types[7]));
384         assertEquals(types[1], TypeUtils.getArrayComponentType(types[8]));
385         assertEquals(types[2], TypeUtils.getArrayComponentType(types[9]));
386         assertEquals(types[3], TypeUtils.getArrayComponentType(types[10]));
387         assertEquals(types[4], TypeUtils.getArrayComponentType(types[11]));
388         assertEquals(types[5], TypeUtils.getArrayComponentType(types[12]));
389         assertEquals(types[6], TypeUtils.getArrayComponentType(types[13]));
390     }
391 
392     @Test
393     public void testGetPrimitiveArrayComponentType() {
394         assertEquals(boolean.class, TypeUtils.getArrayComponentType(boolean[].class));
395         assertEquals(byte.class, TypeUtils.getArrayComponentType(byte[].class));
396         assertEquals(short.class, TypeUtils.getArrayComponentType(short[].class));
397         assertEquals(int.class, TypeUtils.getArrayComponentType(int[].class));
398         assertEquals(char.class, TypeUtils.getArrayComponentType(char[].class));
399         assertEquals(long.class, TypeUtils.getArrayComponentType(long[].class));
400         assertEquals(float.class, TypeUtils.getArrayComponentType(float[].class));
401         assertEquals(double.class, TypeUtils.getArrayComponentType(double[].class));
402 
403         assertNull(TypeUtils.getArrayComponentType(boolean.class));
404         assertNull(TypeUtils.getArrayComponentType(byte.class));
405         assertNull(TypeUtils.getArrayComponentType(short.class));
406         assertNull(TypeUtils.getArrayComponentType(int.class));
407         assertNull(TypeUtils.getArrayComponentType(char.class));
408         assertNull(TypeUtils.getArrayComponentType(long.class));
409         assertNull(TypeUtils.getArrayComponentType(float.class));
410         assertNull(TypeUtils.getArrayComponentType(double.class));
411     }
412 
413     @Test
414     public void testGetRawType() throws SecurityException, NoSuchFieldException {
415         final Type stringParentFieldType = GenericTypeHolder.class.getDeclaredField("stringParent").getGenericType();
416         final Type integerParentFieldType = GenericTypeHolder.class.getDeclaredField("integerParent").getGenericType();
417         final Type foosFieldType = GenericTypeHolder.class.getDeclaredField("foos").getGenericType();
418         final Type genericParentT = GenericParent.class.getTypeParameters()[0];
419         assertEquals(GenericParent.class, TypeUtils.getRawType(stringParentFieldType, null));
420         assertEquals(GenericParent.class, TypeUtils.getRawType(integerParentFieldType, null));
421         assertEquals(List.class, TypeUtils.getRawType(foosFieldType, null));
422         assertEquals(String.class, TypeUtils.getRawType(genericParentT, StringParameterizedChild.class));
423         assertEquals(String.class, TypeUtils.getRawType(genericParentT, stringParentFieldType));
424         assertEquals(Foo.class, TypeUtils.getRawType(Iterable.class.getTypeParameters()[0], foosFieldType));
425         assertEquals(Foo.class, TypeUtils.getRawType(List.class.getTypeParameters()[0], foosFieldType));
426         assertNull(TypeUtils.getRawType(genericParentT, GenericParent.class));
427         assertEquals(GenericParent[].class, TypeUtils.getRawType(GenericTypeHolder.class.getDeclaredField("barParents").getGenericType(), null));
428     }
429 
430     /**
431      * Tests https://issues.apache.org/jira/browse/LANG-1697
432      */
433     @Test
434     public void testGetRawType_LANG_1697() throws NoSuchFieldException {
435         assertEquals(int[].class, TypeUtils.getRawType(TypeUtils.genericArrayType(Integer.TYPE), Integer.TYPE));
436         // LANG-1697:
437         assertNull(TypeUtils.getRawType(TypeUtils.genericArrayType(TypeUtils.WILDCARD_ALL), null));
438         // TODO: Is this correct?
439         assertNull(TypeUtils.getRawType(TypeUtils.genericArrayType(TypeUtils.WILDCARD_ALL), TypeUtils.WILDCARD_ALL));
440         // TODO: Is this correct?
441         assertNull(TypeUtils.getRawType(TypeUtils.genericArrayType(TypeUtils.WILDCARD_ALL), Integer.TYPE));
442     }
443 
444     @Test
445     public void testGetTypeArguments() {
446         Map<TypeVariable<?>, Type> typeVarAssigns;
447         TypeVariable<?> treeSetTypeVar;
448         Type typeArg;
449 
450         typeVarAssigns = TypeUtils.getTypeArguments(Integer.class, Comparable.class);
451         treeSetTypeVar = Comparable.class.getTypeParameters()[0];
452         assertTrue(typeVarAssigns.containsKey(treeSetTypeVar),
453                 "Type var assigns for Comparable from Integer: " + typeVarAssigns);
454         typeArg = typeVarAssigns.get(treeSetTypeVar);
455         assertEquals(Integer.class, typeVarAssigns.get(treeSetTypeVar),
456                 "Type argument of Comparable from Integer: " + typeArg);
457 
458         typeVarAssigns = TypeUtils.getTypeArguments(int.class, Comparable.class);
459         treeSetTypeVar = Comparable.class.getTypeParameters()[0];
460         assertTrue(typeVarAssigns.containsKey(treeSetTypeVar),
461                 "Type var assigns for Comparable from int: " + typeVarAssigns);
462         typeArg = typeVarAssigns.get(treeSetTypeVar);
463         assertEquals(Integer.class, typeVarAssigns.get(treeSetTypeVar),
464                 "Type argument of Comparable from int: " + typeArg);
465 
466         final Collection<Integer> col = Collections.emptyList();
467         typeVarAssigns = TypeUtils.getTypeArguments(List.class, Collection.class);
468         treeSetTypeVar = Comparable.class.getTypeParameters()[0];
469         assertFalse(typeVarAssigns.containsKey(treeSetTypeVar),
470                 "Type var assigns for Collection from List: " + typeVarAssigns);
471 
472         typeVarAssigns = TypeUtils.getTypeArguments(AAAClass.BBBClass.class, AAClass.BBClass.class);
473         assertEquals(2, typeVarAssigns.size());
474         assertEquals(String.class, typeVarAssigns.get(AAClass.class.getTypeParameters()[0]));
475         assertEquals(String.class, typeVarAssigns.get(AAClass.BBClass.class.getTypeParameters()[0]));
476 
477         typeVarAssigns = TypeUtils.getTypeArguments(Other.class, This.class);
478         assertEquals(2, typeVarAssigns.size());
479         assertEquals(String.class, typeVarAssigns.get(This.class.getTypeParameters()[0]));
480         assertEquals(Other.class.getTypeParameters()[0], typeVarAssigns.get(This.class.getTypeParameters()[1]));
481 
482         typeVarAssigns = TypeUtils.getTypeArguments(And.class, This.class);
483         assertEquals(2, typeVarAssigns.size());
484         assertEquals(Number.class, typeVarAssigns.get(This.class.getTypeParameters()[0]));
485         assertEquals(Number.class, typeVarAssigns.get(This.class.getTypeParameters()[1]));
486 
487         typeVarAssigns = TypeUtils.getTypeArguments(Thing.class, Other.class);
488         assertEquals(2, typeVarAssigns.size());
489         assertEquals(getClass().getTypeParameters()[0], typeVarAssigns.get(getClass().getTypeParameters()[0]));
490         assertEquals(getClass().getTypeParameters()[0], typeVarAssigns.get(Other.class.getTypeParameters()[0]));
491     }
492 
493     @Test
494     public void testIsArrayGenericTypes() throws Exception {
495         final Method method = getClass().getMethod("dummyMethod", List.class, List.class, List.class,
496                 List.class, List.class, List.class, List.class, List[].class, List[].class,
497                 List[].class, List[].class, List[].class, List[].class, List[].class);
498 
499         final Type[] types = method.getGenericParameterTypes();
500 
501         assertFalse(TypeUtils.isArrayType(types[0]));
502         assertFalse(TypeUtils.isArrayType(types[1]));
503         assertFalse(TypeUtils.isArrayType(types[2]));
504         assertFalse(TypeUtils.isArrayType(types[3]));
505         assertFalse(TypeUtils.isArrayType(types[4]));
506         assertFalse(TypeUtils.isArrayType(types[5]));
507         assertFalse(TypeUtils.isArrayType(types[6]));
508         assertTrue(TypeUtils.isArrayType(types[7]));
509         assertTrue(TypeUtils.isArrayType(types[8]));
510         assertTrue(TypeUtils.isArrayType(types[9]));
511         assertTrue(TypeUtils.isArrayType(types[10]));
512         assertTrue(TypeUtils.isArrayType(types[11]));
513         assertTrue(TypeUtils.isArrayType(types[12]));
514         assertTrue(TypeUtils.isArrayType(types[13]));
515     }
516 
517     @Test
518     public void testIsArrayTypeClasses() {
519         assertTrue(TypeUtils.isArrayType(boolean[].class));
520         assertTrue(TypeUtils.isArrayType(byte[].class));
521         assertTrue(TypeUtils.isArrayType(short[].class));
522         assertTrue(TypeUtils.isArrayType(int[].class));
523         assertTrue(TypeUtils.isArrayType(char[].class));
524         assertTrue(TypeUtils.isArrayType(long[].class));
525         assertTrue(TypeUtils.isArrayType(float[].class));
526         assertTrue(TypeUtils.isArrayType(double[].class));
527         assertTrue(TypeUtils.isArrayType(Object[].class));
528         assertTrue(TypeUtils.isArrayType(String[].class));
529 
530         assertFalse(TypeUtils.isArrayType(boolean.class));
531         assertFalse(TypeUtils.isArrayType(byte.class));
532         assertFalse(TypeUtils.isArrayType(short.class));
533         assertFalse(TypeUtils.isArrayType(int.class));
534         assertFalse(TypeUtils.isArrayType(char.class));
535         assertFalse(TypeUtils.isArrayType(long.class));
536         assertFalse(TypeUtils.isArrayType(float.class));
537         assertFalse(TypeUtils.isArrayType(double.class));
538         assertFalse(TypeUtils.isArrayType(Object.class));
539         assertFalse(TypeUtils.isArrayType(String.class));
540     }
541 
542     @SuppressWarnings("boxing") // deliberately used here
543     @Test
544     public void testIsAssignable() throws SecurityException, NoSuchMethodException,
545             NoSuchFieldException {
546         List list0 = null;
547         List<Object> list1;
548         List<?> list2;
549         List<? super Object> list3;
550         List<String> list4;
551         List<? extends String> list5;
552         List<? super String> list6;
553         List[] list7 = null;
554         List<Object>[] list8;
555         List<?>[] list9;
556         List<? super Object>[] list10;
557         List<String>[] list11;
558         List<? extends String>[] list12;
559         List<? super String>[] list13;
560         final Class<?> clazz = getClass();
561         final Method method = clazz.getMethod("dummyMethod", List.class, List.class, List.class,
562                 List.class, List.class, List.class, List.class, List[].class, List[].class,
563                 List[].class, List[].class, List[].class, List[].class, List[].class);
564         final Type[] types = method.getGenericParameterTypes();
565 //        list0 = list0;
566         delegateBooleanAssertion(types, 0, 0, true);
567         list1 = list0;
568         delegateBooleanAssertion(types, 0, 1, true);
569         list0 = list1;
570         delegateBooleanAssertion(types, 1, 0, true);
571         list2 = list0;
572         delegateBooleanAssertion(types, 0, 2, true);
573         list0 = list2;
574         delegateBooleanAssertion(types, 2, 0, true);
575         list3 = list0;
576         delegateBooleanAssertion(types, 0, 3, true);
577         list0 = list3;
578         delegateBooleanAssertion(types, 3, 0, true);
579         list4 = list0;
580         delegateBooleanAssertion(types, 0, 4, true);
581         list0 = list4;
582         delegateBooleanAssertion(types, 4, 0, true);
583         list5 = list0;
584         delegateBooleanAssertion(types, 0, 5, true);
585         list0 = list5;
586         delegateBooleanAssertion(types, 5, 0, true);
587         list6 = list0;
588         delegateBooleanAssertion(types, 0, 6, true);
589         list0 = list6;
590         delegateBooleanAssertion(types, 6, 0, true);
591 //        list1 = list1;
592         delegateBooleanAssertion(types, 1, 1, true);
593         list2 = list1;
594         delegateBooleanAssertion(types, 1, 2, true);
595         list1 = (List<Object>) list2;
596         delegateBooleanAssertion(types, 2, 1, false);
597         list3 = list1;
598         delegateBooleanAssertion(types, 1, 3, true);
599         list1 = (List<Object>) list3;
600         delegateBooleanAssertion(types, 3, 1, false);
601         // list4 = list1;
602         delegateBooleanAssertion(types, 1, 4, false);
603         // list1 = list4;
604         delegateBooleanAssertion(types, 4, 1, false);
605         // list5 = list1;
606         delegateBooleanAssertion(types, 1, 5, false);
607         // list1 = list5;
608         delegateBooleanAssertion(types, 5, 1, false);
609         list6 = list1;
610         delegateBooleanAssertion(types, 1, 6, true);
611         list1 = (List<Object>) list6;
612         delegateBooleanAssertion(types, 6, 1, false);
613 //        list2 = list2;
614         delegateBooleanAssertion(types, 2, 2, true);
615         list2 = list3;
616         delegateBooleanAssertion(types, 2, 3, false);
617         list2 = list4;
618         delegateBooleanAssertion(types, 3, 2, true);
619         list3 = (List<? super Object>) list2;
620         delegateBooleanAssertion(types, 2, 4, false);
621         list2 = list5;
622         delegateBooleanAssertion(types, 4, 2, true);
623         list4 = (List<String>) list2;
624         delegateBooleanAssertion(types, 2, 5, false);
625         list2 = list6;
626         delegateBooleanAssertion(types, 5, 2, true);
627         list5 = (List<? extends String>) list2;
628         delegateBooleanAssertion(types, 2, 6, false);
629 //        list3 = list3;
630         delegateBooleanAssertion(types, 6, 2, true);
631         list6 = (List<? super String>) list2;
632         delegateBooleanAssertion(types, 3, 3, true);
633         // list4 = list3;
634         delegateBooleanAssertion(types, 3, 4, false);
635         // list3 = list4;
636         delegateBooleanAssertion(types, 4, 3, false);
637         // list5 = list3;
638         delegateBooleanAssertion(types, 3, 5, false);
639         // list3 = list5;
640         delegateBooleanAssertion(types, 5, 3, false);
641         list6 = list3;
642         delegateBooleanAssertion(types, 3, 6, true);
643         list3 = (List<? super Object>) list6;
644         delegateBooleanAssertion(types, 6, 3, false);
645 //        list4 = list4;
646         delegateBooleanAssertion(types, 4, 4, true);
647         list5 = list4;
648         delegateBooleanAssertion(types, 4, 5, true);
649         list4 = (List<String>) list5;
650         delegateBooleanAssertion(types, 5, 4, false);
651         list6 = list4;
652         delegateBooleanAssertion(types, 4, 6, true);
653         list4 = (List<String>) list6;
654         delegateBooleanAssertion(types, 6, 4, false);
655 //        list5 = list5;
656         delegateBooleanAssertion(types, 5, 5, true);
657         list6 = (List<? super String>) list5;
658         delegateBooleanAssertion(types, 5, 6, false);
659         list5 = (List<? extends String>) list6;
660         delegateBooleanAssertion(types, 6, 5, false);
661 //        list6 = list6;
662         delegateBooleanAssertion(types, 6, 6, true);
663 
664 //        list7 = list7;
665         delegateBooleanAssertion(types, 7, 7, true);
666         list8 = list7;
667         delegateBooleanAssertion(types, 7, 8, true);
668         list7 = list8;
669         delegateBooleanAssertion(types, 8, 7, true);
670         list9 = list7;
671         delegateBooleanAssertion(types, 7, 9, true);
672         list7 = list9;
673         delegateBooleanAssertion(types, 9, 7, true);
674         list10 = list7;
675         delegateBooleanAssertion(types, 7, 10, true);
676         list7 = list10;
677         delegateBooleanAssertion(types, 10, 7, true);
678         list11 = list7;
679         delegateBooleanAssertion(types, 7, 11, true);
680         list7 = list11;
681         delegateBooleanAssertion(types, 11, 7, true);
682         list12 = list7;
683         delegateBooleanAssertion(types, 7, 12, true);
684         list7 = list12;
685         delegateBooleanAssertion(types, 12, 7, true);
686         list13 = list7;
687         delegateBooleanAssertion(types, 7, 13, true);
688         list7 = list13;
689         delegateBooleanAssertion(types, 13, 7, true);
690 //        list8 = list8;
691         delegateBooleanAssertion(types, 8, 8, true);
692         list9 = list8;
693         delegateBooleanAssertion(types, 8, 9, true);
694         list8 = (List<Object>[]) list9;
695         delegateBooleanAssertion(types, 9, 8, false);
696         list10 = list8;
697         delegateBooleanAssertion(types, 8, 10, true);
698         list8 = (List<Object>[]) list10; // NOTE cast is required by Sun Java, but not by Eclipse
699         delegateBooleanAssertion(types, 10, 8, false);
700         // list11 = list8;
701         delegateBooleanAssertion(types, 8, 11, false);
702         // list8 = list11;
703         delegateBooleanAssertion(types, 11, 8, false);
704         // list12 = list8;
705         delegateBooleanAssertion(types, 8, 12, false);
706         // list8 = list12;
707         delegateBooleanAssertion(types, 12, 8, false);
708         list13 = list8;
709         delegateBooleanAssertion(types, 8, 13, true);
710         list8 = (List<Object>[]) list13;
711         delegateBooleanAssertion(types, 13, 8, false);
712 //        list9 = list9;
713         delegateBooleanAssertion(types, 9, 9, true);
714         list10 = (List<? super Object>[]) list9;
715         delegateBooleanAssertion(types, 9, 10, false);
716         list9 = list10;
717         delegateBooleanAssertion(types, 10, 9, true);
718         list11 = (List<String>[]) list9;
719         delegateBooleanAssertion(types, 9, 11, false);
720         list9 = list11;
721         delegateBooleanAssertion(types, 11, 9, true);
722         list12 = (List<? extends String>[]) list9;
723         delegateBooleanAssertion(types, 9, 12, false);
724         list9 = list12;
725         delegateBooleanAssertion(types, 12, 9, true);
726         list13 = (List<? super String>[]) list9;
727         delegateBooleanAssertion(types, 9, 13, false);
728         list9 = list13;
729         delegateBooleanAssertion(types, 13, 9, true);
730 //        list10 = list10;
731         delegateBooleanAssertion(types, 10, 10, true);
732         // list11 = list10;
733         delegateBooleanAssertion(types, 10, 11, false);
734         // list10 = list11;
735         delegateBooleanAssertion(types, 11, 10, false);
736         // list12 = list10;
737         delegateBooleanAssertion(types, 10, 12, false);
738         // list10 = list12;
739         delegateBooleanAssertion(types, 12, 10, false);
740         list13 = list10;
741         delegateBooleanAssertion(types, 10, 13, true);
742         list10 = (List<? super Object>[]) list13;
743         delegateBooleanAssertion(types, 13, 10, false);
744 //        list11 = list11;
745         delegateBooleanAssertion(types, 11, 11, true);
746         list12 = list11;
747         delegateBooleanAssertion(types, 11, 12, true);
748         list11 = (List<String>[]) list12;
749         delegateBooleanAssertion(types, 12, 11, false);
750         list13 = list11;
751         delegateBooleanAssertion(types, 11, 13, true);
752         list11 = (List<String>[]) list13;
753         delegateBooleanAssertion(types, 13, 11, false);
754 //        list12 = list12;
755         delegateBooleanAssertion(types, 12, 12, true);
756         list13 = (List<? super String>[]) list12;
757         delegateBooleanAssertion(types, 12, 13, false);
758         list12 = (List<? extends String>[]) list13;
759         delegateBooleanAssertion(types, 13, 12, false);
760 //        list13 = list13;
761         delegateBooleanAssertion(types, 13, 13, true);
762         final Type disType = getClass().getField("dis").getGenericType();
763         // Reporter.log( ( ( ParameterizedType ) disType
764         // ).getOwnerType().getClass().toString() );
765         final Type datType = getClass().getField("dat").getGenericType();
766         final Type daType = getClass().getField("da").getGenericType();
767         final Type uhderType = getClass().getField("uhder").getGenericType();
768         final Type dingType = getClass().getField("ding").getGenericType();
769         final Type testerType = getClass().getField("tester").getGenericType();
770         final Type tester2Type = getClass().getField("tester2").getGenericType();
771         final Type dat2Type = getClass().getField("dat2").getGenericType();
772         final Type dat3Type = getClass().getField("dat3").getGenericType();
773         dis = dat;
774         assertTrue(TypeUtils.isAssignable(datType, disType));
775         // dis = da;
776         assertFalse(TypeUtils.isAssignable(daType, disType));
777         dis = uhder;
778         assertTrue(TypeUtils.isAssignable(uhderType, disType));
779         dis = ding;
780         assertFalse(TypeUtils.isAssignable(dingType, disType),
781                 String.format("type %s not assignable to %s!", dingType, disType));
782         dis = tester;
783         assertTrue(TypeUtils.isAssignable(testerType, disType));
784         // dis = tester2;
785         assertFalse(TypeUtils.isAssignable(tester2Type, disType));
786         // dat = dat2;
787         assertFalse(TypeUtils.isAssignable(dat2Type, datType));
788         // dat2 = dat;
789         assertFalse(TypeUtils.isAssignable(datType, dat2Type));
790         // dat = dat3;
791         assertFalse(TypeUtils.isAssignable(dat3Type, datType));
792         final char ch = 0;
793         final boolean bo = false;
794         final byte by = 0;
795         final short sh = 0;
796         int in = 0;
797         long lo = 0;
798         final float fl = 0;
799         double du;
800         du = ch;
801         assertTrue(TypeUtils.isAssignable(char.class, double.class));
802         du = by;
803         assertTrue(TypeUtils.isAssignable(byte.class, double.class));
804         du = sh;
805         assertTrue(TypeUtils.isAssignable(short.class, double.class));
806         du = in;
807         assertTrue(TypeUtils.isAssignable(int.class, double.class));
808         du = lo;
809         assertTrue(TypeUtils.isAssignable(long.class, double.class));
810         du = fl;
811         assertTrue(TypeUtils.isAssignable(float.class, double.class));
812         lo = in;
813         assertTrue(TypeUtils.isAssignable(int.class, long.class));
814         lo = Integer.valueOf(0);
815         assertTrue(TypeUtils.isAssignable(Integer.class, long.class));
816         // Long lngW = 1;
817         assertFalse(TypeUtils.isAssignable(int.class, Long.class));
818         // lngW = Integer.valueOf( 0 );
819         assertFalse(TypeUtils.isAssignable(Integer.class, Long.class));
820         in = Integer.valueOf(0);
821         assertTrue(TypeUtils.isAssignable(Integer.class, int.class));
822         final Integer inte = in;
823         assertTrue(TypeUtils.isAssignable(int.class, Integer.class));
824         assertTrue(TypeUtils.isAssignable(int.class, Number.class));
825         assertTrue(TypeUtils.isAssignable(int.class, Object.class));
826         final Type intComparableType = getClass().getField("intComparable").getGenericType();
827         intComparable = 1;
828         assertTrue(TypeUtils.isAssignable(int.class, intComparableType));
829         assertTrue(TypeUtils.isAssignable(int.class, Comparable.class));
830         final Serializable ser = 1;
831         assertTrue(TypeUtils.isAssignable(int.class, Serializable.class));
832         final Type longComparableType = getClass().getField("longComparable").getGenericType();
833         // longComparable = 1;
834         assertFalse(TypeUtils.isAssignable(int.class, longComparableType));
835         // longComparable = Integer.valueOf( 0 );
836         assertFalse(TypeUtils.isAssignable(Integer.class, longComparableType));
837         // int[] ia;
838         // long[] la = ia;
839         assertFalse(TypeUtils.isAssignable(int[].class, long[].class));
840         final Integer[] ia = null;
841         final Type caType = getClass().getField("intWildcardComparable").getGenericType();
842         intWildcardComparable = ia;
843         assertTrue(TypeUtils.isAssignable(Integer[].class, caType));
844         // int[] ina = ia;
845         assertFalse(TypeUtils.isAssignable(Integer[].class, int[].class));
846         final int[] ina = null;
847         final Object[] oa;
848         // oa = ina;
849         assertFalse(TypeUtils.isAssignable(int[].class, Object[].class));
850         oa = new Integer[0];
851         assertTrue(TypeUtils.isAssignable(Integer[].class, Object[].class));
852         final Type bClassType = AClass.class.getField("bClass").getGenericType();
853         final Type cClassType = AClass.class.getField("cClass").getGenericType();
854         final Type dClassType = AClass.class.getField("dClass").getGenericType();
855         final Type eClassType = AClass.class.getField("eClass").getGenericType();
856         final Type fClassType = AClass.class.getField("fClass").getGenericType();
857         final AClass aClass = new AClass(new AAClass<>());
858         aClass.bClass = aClass.cClass;
859         assertTrue(TypeUtils.isAssignable(cClassType, bClassType));
860         aClass.bClass = aClass.dClass;
861         assertTrue(TypeUtils.isAssignable(dClassType, bClassType));
862         aClass.bClass = aClass.eClass;
863         assertTrue(TypeUtils.isAssignable(eClassType, bClassType));
864         aClass.bClass = aClass.fClass;
865         assertTrue(TypeUtils.isAssignable(fClassType, bClassType));
866         aClass.cClass = aClass.dClass;
867         assertTrue(TypeUtils.isAssignable(dClassType, cClassType));
868         aClass.cClass = aClass.eClass;
869         assertTrue(TypeUtils.isAssignable(eClassType, cClassType));
870         aClass.cClass = aClass.fClass;
871         assertTrue(TypeUtils.isAssignable(fClassType, cClassType));
872         aClass.dClass = aClass.eClass;
873         assertTrue(TypeUtils.isAssignable(eClassType, dClassType));
874         aClass.dClass = aClass.fClass;
875         assertTrue(TypeUtils.isAssignable(fClassType, dClassType));
876         aClass.eClass = aClass.fClass;
877         assertTrue(TypeUtils.isAssignable(fClassType, eClassType));
878     }
879 
880     private void testIsAssignable(final Class testUnassignableClass) {
881         final Class<Constructor> rawClass = Constructor.class;
882         final Class<Insets> typeArgClass = Insets.class;
883         // Builds a ParameterizedType for Constructor<Insets>
884         final ParameterizedType paramType = TypeUtils.parameterize(rawClass, typeArgClass);
885         assertEquals(rawClass, paramType.getRawType());
886         assertEquals(typeArgClass, paramType.getActualTypeArguments()[0]);
887 
888         assertFalse(testUnassignableClass.isAssignableFrom(paramType.getClass()));
889         assertFalse(paramType.getClass().isAssignableFrom(testUnassignableClass));
890 
891         final GenericArrayType arrayType = TypeUtils.genericArrayType(paramType);
892         assertFalse(TypeUtils.isAssignable(arrayType, paramType),
893                 () -> String.format("TypeUtils.isAssignable(%s, %s)", arrayType, paramType));
894         assertFalse(TypeUtils.isAssignable(paramType, arrayType),
895                 () -> String.format("TypeUtils.isAssignable(%s, %s)", paramType, arrayType));
896     }
897 
898     @Test
899     public void testIsAssignableGenericArrayTypeToObject() {
900         final Class<Constructor> rawClass = Constructor.class;
901         final Class<Insets> typeArgClass = Insets.class;
902         // Builds a ParameterizedType for Constructor<Insets>
903         final ParameterizedType paramType = TypeUtils.parameterize(rawClass, typeArgClass);
904         assertEquals(rawClass, paramType.getRawType());
905         assertEquals(typeArgClass, paramType.getActualTypeArguments()[0]);
906 
907         assertTrue(Object.class.isAssignableFrom(paramType.getClass()));
908         assertFalse(paramType.getClass().isAssignableFrom(Object.class));
909 
910         final Type testType = Object.class;
911         assertTrue(TypeUtils.isAssignable(paramType, testType),
912                 () -> String.format("TypeUtils.isAssignable(%s, %s)", paramType, testType));
913         assertFalse(TypeUtils.isAssignable(testType, paramType),
914                 () -> String.format("TypeUtils.isAssignable(%s, %s)", testType, paramType));
915     }
916 
917     @Test
918     public void testIsAssignableGenericArrayTypeToParameterizedType() {
919         final Class<Constructor> rawClass = Constructor.class;
920         final Class<Insets> typeArgClass = Insets.class;
921         // Builds a ParameterizedType for Constructor<Insets>
922         final ParameterizedType paramType = TypeUtils.parameterize(rawClass, typeArgClass);
923         assertEquals(rawClass, paramType.getRawType());
924         assertEquals(typeArgClass, paramType.getActualTypeArguments()[0]);
925 
926         assertFalse(GenericArrayType.class.isAssignableFrom(paramType.getClass()));
927         assertFalse(paramType.getClass().isAssignableFrom(GenericArrayType.class));
928 
929         final GenericArrayType testType = TypeUtils.genericArrayType(paramType);
930         assertFalse(TypeUtils.isAssignable(paramType, testType),
931                 () -> String.format("TypeUtils.isAssignable(%s, %s)", paramType, testType));
932         assertFalse(TypeUtils.isAssignable(testType, paramType),
933                 () -> String.format("TypeUtils.isAssignable(%s, %s)", testType, paramType));
934     }
935 
936     @Test
937     @Disabled("TODO")
938     public void testIsAssignableGenericArrayTypeToWildercardType() {
939         final Class<Constructor> rawClass = Constructor.class;
940         final Class<Insets> typeArgClass = Insets.class;
941         // Builds a ParameterizedType for Constructor<Insets>
942         final ParameterizedType paramType = TypeUtils.parameterize(rawClass, typeArgClass);
943         assertEquals(rawClass, paramType.getRawType());
944         assertEquals(typeArgClass, paramType.getActualTypeArguments()[0]);
945 
946         assertFalse(WildcardType.class.isAssignableFrom(paramType.getClass()));
947         assertFalse(paramType.getClass().isAssignableFrom(WildcardType.class));
948 
949         final WildcardType testType = TypeUtils.WILDCARD_ALL;
950         // TODO This test returns true unlike the test above.
951         // Is this a bug in this test or in the main code?
952         assertFalse(TypeUtils.isAssignable(paramType, testType),
953                 () -> String.format("TypeUtils.isAssignable(%s, %s)", paramType, testType));
954         assertFalse(TypeUtils.isAssignable(testType, paramType),
955                 () -> String.format("TypeUtils.isAssignable(%s, %s)", testType, paramType));
956     }
957 
958     @SuppressWarnings("boxing") // boxing is deliberate here
959     @Test
960     public void testIsInstance() throws SecurityException, NoSuchFieldException {
961         final Type intComparableType = getClass().getField("intComparable").getGenericType();
962         final Type uriComparableType = getClass().getField("uriComparable").getGenericType();
963         intComparable = 1;
964         assertTrue(TypeUtils.isInstance(1, intComparableType));
965         // uriComparable = 1;
966         assertFalse(TypeUtils.isInstance(1, uriComparableType));
967     }
968 
969     @Test
970     public void testLowerBoundedWildcardType() {
971        final WildcardType lowerBounded = TypeUtils.wildcardType().withLowerBounds(java.sql.Date.class).build();
972        assertEquals(String.format("? super %s", java.sql.Date.class.getName()), TypeUtils.toString(lowerBounded));
973        assertEquals(String.format("? super %s", java.sql.Date.class.getName()), lowerBounded.toString());
974 
975        final TypeVariable<Class<Iterable>> iterableT0 = Iterable.class.getTypeParameters()[0];
976        final WildcardType lowerTypeVariable = TypeUtils.wildcardType().withLowerBounds(iterableT0).build();
977        assertEquals(String.format("? super %s", iterableT0.getName()), TypeUtils.toString(lowerTypeVariable));
978        assertEquals(String.format("? super %s", iterableT0.getName()), lowerTypeVariable.toString());
979     }
980 
981     @Test
982     public void testParameterize() throws Exception {
983         final ParameterizedType stringComparableType = TypeUtils.parameterize(Comparable.class, String.class);
984         assertTrue(TypeUtils.equals(getClass().getField("stringComparable").getGenericType(),
985             stringComparableType));
986         assertEquals("java.lang.Comparable<java.lang.String>", stringComparableType.toString());
987     }
988 
989     @Test
990     public void testParameterizeNarrowerTypeArray() {
991         final TypeVariable<?>[] variables = ArrayList.class.getTypeParameters();
992         final ParameterizedType parameterizedType = TypeUtils.parameterize(ArrayList.class, variables);
993         final Map<TypeVariable<?>, Type> mapping = Collections.<TypeVariable<?>, Type>singletonMap(variables[0], String.class);
994         final Type unrolled = TypeUtils.unrollVariables(mapping, parameterizedType);
995         assertEquals(TypeUtils.parameterize(ArrayList.class, String.class), unrolled);
996     }
997 
998     @Test
999     public void testParameterizeNullPointerException() {
1000         assertThrows(NullPointerException.class, () -> TypeUtils.parameterize(null, Collections.emptyMap()));
1001         final Map<TypeVariable<?>, Type> nullTypeVariableMap = null;
1002         assertThrows(NullPointerException.class, () -> TypeUtils.parameterize(String.class, nullTypeVariableMap));
1003     }
1004 
1005     @Test
1006     public void testParameterizeVarArgsNullPointerException() {
1007         assertThrows(NullPointerException.class, () -> TypeUtils.parameterize(null));
1008     }
1009 
1010     @Test
1011     public void testParameterizeWithOwner() throws Exception {
1012         final Type owner = TypeUtils.parameterize(TypeUtilsTest.class, String.class);
1013         final ParameterizedType dat2Type = TypeUtils.parameterizeWithOwner(owner, That.class, String.class, String.class);
1014         assertTrue(TypeUtils.equals(getClass().getField("dat2").getGenericType(), dat2Type));
1015     }
1016 
1017     @Test
1018     public void testParameterizeWithOwner3ArgsNullPointerException() {
1019         final Type owner = TypeUtils.parameterize(TypeUtilsTest.class, String.class);
1020         assertThrows(NullPointerException.class, () -> TypeUtils.parameterizeWithOwner(owner, null, String.class));
1021         final Map<TypeVariable<?>, Type> nullTypeVariableMap = null;
1022         assertThrows(NullPointerException.class, () -> TypeUtils.parameterizeWithOwner(owner, That.class, nullTypeVariableMap));
1023     }
1024 
1025     @Test
1026     public void testParameterizeWithOwnerVarArgsNullPointerException() {
1027         final Type owner = TypeUtils.parameterize(TypeUtilsTest.class, String.class);
1028         assertThrows(NullPointerException.class, () -> TypeUtils.parameterizeWithOwner(owner, null));
1029     }
1030 
1031     @Test
1032     public void testToLongString() {
1033         assertEquals(getClass().getName() + ":B", TypeUtils.toLongString(getClass().getTypeParameters()[0]));
1034 
1035         assertThrows(NullPointerException.class, () -> TypeUtils.toLongString(null));
1036     }
1037 
1038     @Test
1039     public void testToString_LANG_1311() {
1040         assertEquals("int[]", TypeUtils.toString(int[].class));
1041         assertEquals("java.lang.Integer[]", TypeUtils.toString(Integer[].class));
1042         final Field stringListField = FieldUtils.getDeclaredField(getClass(), "stringListArray");
1043         assertEquals("java.util.List<java.lang.String>[]", TypeUtils.toString(stringListField.getGenericType()));
1044     }
1045 
1046     @Test
1047     public void testTypesSatisfyVariables() throws SecurityException,
1048             NoSuchMethodException {
1049         final Map<TypeVariable<?>, Type> typeVarAssigns = new HashMap<>();
1050         final Integer max = TypeUtilsTest.<Integer>stub();
1051         typeVarAssigns.put(getClass().getMethod("stub").getTypeParameters()[0], Integer.class);
1052         assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
1053         typeVarAssigns.clear();
1054         typeVarAssigns.put(getClass().getMethod("stub2").getTypeParameters()[0], Integer.class);
1055         assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
1056         typeVarAssigns.clear();
1057         typeVarAssigns.put(getClass().getMethod("stub3").getTypeParameters()[0], Integer.class);
1058         assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
1059 
1060         assertThrows(NullPointerException.class, () -> TypeUtils.typesSatisfyVariables(null));
1061     }
1062 
1063     @Test
1064     public void testUnboundedWildcardType() {
1065         final WildcardType unbounded = TypeUtils.wildcardType().withLowerBounds((Type) null).withUpperBounds().build();
1066         assertTrue(TypeUtils.equals(TypeUtils.WILDCARD_ALL, unbounded));
1067         assertArrayEquals(new Type[] { Object.class }, TypeUtils.getImplicitUpperBounds(unbounded));
1068         assertArrayEquals(new Type[] { null }, TypeUtils.getImplicitLowerBounds(unbounded));
1069         assertEquals("?", TypeUtils.toString(unbounded));
1070         assertEquals("?", unbounded.toString());
1071 
1072         assertThrows(NullPointerException.class,
1073                 () -> TypeUtils.getImplicitLowerBounds(null));
1074         assertThrows(NullPointerException.class,
1075                 () -> TypeUtils.getImplicitUpperBounds(null));
1076     }
1077 
1078     @Test
1079     public void testWildcardType() throws Exception {
1080         final WildcardType simpleWildcard = TypeUtils.wildcardType().withUpperBounds(String.class).build();
1081         final Field cClass = AClass.class.getField("cClass");
1082         assertTrue(TypeUtils.equals(((ParameterizedType) cClass.getGenericType()).getActualTypeArguments()[0],
1083             simpleWildcard));
1084         assertEquals(String.format("? extends %s", String.class.getName()), TypeUtils.toString(simpleWildcard));
1085         assertEquals(String.format("? extends %s", String.class.getName()), simpleWildcard.toString());
1086     }
1087 
1088     @Test
1089     public void testWrap() {
1090         final Type t = getClass().getTypeParameters()[0];
1091         assertTrue(TypeUtils.equals(t, TypeUtils.wrap(t).getType()));
1092 
1093         assertEquals(String.class, TypeUtils.wrap(String.class).getType());
1094     }
1095 }