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