You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2020/11/15 16:49:16 UTC

[commons-lang] branch master updated: [LANG-1420] TypeUtils.isAssignable returns wrong result for GenericArrayType and ParameterizedType.

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git


The following commit(s) were added to refs/heads/master by this push:
     new 35799d0  [LANG-1420] TypeUtils.isAssignable returns wrong result for GenericArrayType and ParameterizedType.
35799d0 is described below

commit 35799d095886243ad32f46c81a77f85743d5fb05
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Nov 15 11:49:11 2020 -0500

    [LANG-1420] TypeUtils.isAssignable returns wrong result for
    GenericArrayType and ParameterizedType.
---
 src/changes/changes.xml                            |  13 +-
 .../apache/commons/lang3/reflect/TypeUtils.java    |  11 +-
 .../commons/lang3/reflect/TypeUtilsTest.java       | 863 +++++++++++----------
 3 files changed, 487 insertions(+), 400 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 300ee63..9d070a5 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -52,12 +52,13 @@ The <action> type attribute can be add,update,fix,remove.
     <action                   type="fix" dev="ggregory" due-to="iamchao1129">ContextedException Javadoc add missing semicolon #581.</action>
     <action issue="LANG-1608" type="fix" dev="aherbert" due-to="Edgar Asatryan">Resolve JUnit pioneer transitive dependencies using JUnit BOM.</action>
     <action                   type="fix" dev="aherbert" due-to="HubertWo, Gary Gregory">NumberUtilsTest - incorrect types in min/max tests #634.</action>
-    <action issue="LANG-1579" type="update" dev="aherbert" due-to="XenoAmess">Improve StringUtils.stripAccents conversion of remaining accents.</action>
-    <action issue="LANG-1606" type="update" dev="sebb" due-to="Rustem Galiev">StringUtils.countMatches - clarify Javadoc.</action>
-    <action issue="LANG-1591" type="update" dev="kinow" due-to="bhawna94">Remove redundant argument from substring call.</action>
-    <action issue="LANG-1613" type="update" dev="ggregory" due-to="Arturo Bernal, Gary Gregory">BigDecimal is created when you pass it the min and max values, #642.</action>
-    <action issue="LANG-1541" type="update" dev="ggregory" due-to="Arturo Bernal, Gary Gregory">ArrayUtils.contains() and indexOf() fails to handle Double.NaN #647.</action>
-    <action issue="LANG-1541" type="update" dev="ggregory" due-to="Gary Gregory">Fix potential NPE in TypeUtils.isAssignable(Type, ParameterizedType, Map, Type>).</action>
+    <action issue="LANG-1579" type="fix" dev="aherbert" due-to="XenoAmess">Improve StringUtils.stripAccents conversion of remaining accents.</action>
+    <action issue="LANG-1606" type="fix" dev="sebb" due-to="Rustem Galiev">StringUtils.countMatches - clarify Javadoc.</action>
+    <action issue="LANG-1591" type="fix" dev="kinow" due-to="bhawna94">Remove redundant argument from substring call.</action>
+    <action issue="LANG-1613" type="fix" dev="ggregory" due-to="Arturo Bernal, Gary Gregory">BigDecimal is created when you pass it the min and max values, #642.</action>
+    <action issue="LANG-1541" type="fix" dev="ggregory" due-to="Arturo Bernal, Gary Gregory">ArrayUtils.contains() and indexOf() fails to handle Double.NaN #647.</action>
+    <action                   type="fix" dev="ggregory" due-to="Gary Gregory">Fix potential NPE in TypeUtils.isAssignable(Type, ParameterizedType, Map, Type>).</action>
+    <action issue="LANG-1420" type="fix" dev="ggregory" due-to="Gordon Fraser, Rostislav Krasny, Arturo Bernal, Gary Gregory">TypeUtils.isAssignable returns wrong result for GenericArrayType and ParameterizedType, #643.</action>
     
     <!--  ADDS -->
     <action                   type="add" dev="ggregory" due-to="Gary Gregory">Add BooleanUtils.booleanValues().</action>
diff --git a/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java b/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
index c28d3bd..d9659fe 100644
--- a/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
+++ b/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
@@ -388,7 +388,7 @@ public class TypeUtils {
      * the type arguments for the subject class's type variables in that it can
      * only determine those parameters that map from the subject {@link Class}
      * object to the supertype.
-     * 
+     *
      * <p>
      * Example: {@link java.util.TreeSet
      * TreeSet} sets its parameter as the parameter for
@@ -924,7 +924,7 @@ public class TypeUtils {
      * interface {@link Map} are {@link Object} for the subtype
      * {@link java.util.Properties Properties} even though the subtype does not
      * directly implement the {@code Map} interface.
-     * 
+     *
      * <p>
      * This method returns {@code null} if {@code type} is not assignable to
      * {@code toClass}. It returns an empty map if none of the classes or
@@ -1182,6 +1182,11 @@ public class TypeUtils {
             return false;
         }
 
+        // cannot cast an array type to a parameterized type.
+        if (type instanceof GenericArrayType) {
+            return false;
+        }
+
         // all types are assignable to themselves
         if (toParameterizedType.equals(type)) {
             return true;
@@ -1482,7 +1487,7 @@ public class TypeUtils {
      * Strips out the redundant upper bound types in type
      * variable types and wildcard types (or it would with wildcard types if
      * multiple upper bounds were allowed).
-     * 
+     *
      * <p>
      * Example, with the variable type declaration:
      * </p>
diff --git a/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java b/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
index d029c08..8cdce0b 100644
--- a/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
@@ -22,7 +22,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.awt.Insets;
 import java.io.Serializable;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.Method;
@@ -43,8 +45,62 @@ import org.apache.commons.lang3.reflect.testbed.Foo;
 import org.apache.commons.lang3.reflect.testbed.GenericParent;
 import org.apache.commons.lang3.reflect.testbed.GenericTypeHolder;
 import org.apache.commons.lang3.reflect.testbed.StringParameterizedChild;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
+class AAAClass extends AAClass<String> {
+    public class BBBClass extends BBClass<String> {
+    }
+}
+
+class AAClass<T> {
+
+    public class BBClass<S> {
+    }
+}
+
+@SuppressWarnings("rawtypes")
+//raw types, where used, are used purposely
+class AClass extends AAClass<String>.BBClass<Number> {
+
+    public interface AInterface<T> {
+    }
+
+    public class BClass<T> {
+    }
+
+    public class CClass<T> extends BClass {
+    }
+
+    public class DClass<T> extends CClass<T> {
+    }
+
+    public class EClass<T> extends DClass {
+    }
+
+    public class FClass extends EClass<String> {
+    }
+
+    public class GClass<T extends BClass<? extends T> & AInterface<AInterface<? super T>>> {
+    }
+
+    public BClass<Number> bClass;
+
+    public CClass<? extends String> cClass;
+
+    public DClass<String> dClass;
+
+    public EClass<String> eClass;
+
+    public FClass fClass;
+
+    public GClass gClass;
+
+    AClass(final AAClass<String> enclosingInstance) {
+        enclosingInstance.super();
+    }
+}
+
 /**
  * Test TypeUtils
  */
@@ -52,25 +108,59 @@ import org.junit.jupiter.api.Test;
 //raw types, where used, are used purposely
 public class TypeUtilsTest<B> {
 
-    public interface This<K, V> {
+    public interface And<K, V> extends This<Number, Number> {
     }
 
-    public class That<K, V> implements This<K, V> {
+    public static class ClassWithSuperClassWithGenericType extends ArrayList<Object> {
+        private static final long serialVersionUID = 1L;
+
+        public static <U> Iterable<U> methodWithGenericReturnType() {
+            return null;
+        }
     }
 
-    public interface And<K, V> extends This<Number, Number> {
+    public class Other<T> implements This<String, T> {
     }
 
-    public class The<K, V> extends That<Number, Number> implements And<String, String> {
+    public class Tester implements This<String, B> {
     }
 
-    public class Other<T> implements This<String, T> {
+    public class That<K, V> implements This<K, V> {
+    }
+
+    public class The<K, V> extends That<Number, Number> implements And<String, String> {
     }
 
     public class Thing<Q> extends Other<B> {
     }
 
-    public class Tester implements This<String, B> {
+    public interface This<K, V> {
+    }
+
+    public static Comparable<String> stringComparable;
+
+    public static Comparable<URI> uriComparable;
+
+    public static Comparable<Integer> intComparable;
+
+    public static Comparable<Long> longComparable;
+
+    public static Comparable<?> wildcardComparable;
+
+    public static URI uri;
+
+    public static List<String>[] stringListArray;
+
+    public static <G extends Comparable<G>> G stub() {
+        return null;
+    }
+
+    public static <G extends Comparable<? super G>> G stub2() {
+        return null;
+    }
+
+    public static <T extends Comparable<? extends T>> T stub3() {
+        return null;
     }
 
     public This<String, String> dis;
@@ -93,25 +183,222 @@ public class TypeUtilsTest<B> {
 
     public Comparable<? extends Integer>[] intWildcardComparable;
 
-    public static Comparable<String> stringComparable;
+    public Iterable<? extends Map<Integer, ? extends Collection<?>>> iterable;
 
-    public static Comparable<URI> uriComparable;
+    public void delegateBooleanAssertion(final Type[] types, final int i2, final int i1, final boolean expected) {
+        final Type type1 = types[i1];
+        final Type type2 = types[i2];
+        final boolean isAssignable = TypeUtils.isAssignable(type2, type1);
 
-    public static Comparable<Integer> intComparable;
+        if (expected) {
+            assertTrue(isAssignable,
+                    "[" + i1 + ", " + i2 + "]: From "
+                                + String.valueOf(type2) + " to "
+                                + String.valueOf(type1));
+        } else {
+            assertFalse(isAssignable,
+                    "[" + i1 + ", " + i2 + "]: From "
+                                + String.valueOf(type2) + " to "
+                                + String.valueOf(type1));
+        }
+    }
 
-    public static Comparable<Long> longComparable;
+    public void dummyMethod(final List list0, final List<Object> list1, final List<?> list2,
+            final List<? super Object> list3, final List<String> list4, final List<? extends String> list5,
+            final List<? super String> list6, final List[] list7, final List<Object>[] list8, final List<?>[] list9,
+            final List<? super Object>[] list10, final List<String>[] list11, final List<? extends String>[] list12,
+            final List<? super String>[] list13) {
+    }
 
-    public static Comparable<?> wildcardComparable;
+    @Test
+    public void testDetermineTypeVariableAssignments() throws SecurityException,
+            NoSuchFieldException {
+        final ParameterizedType iterableType = (ParameterizedType) getClass().getField("iterable")
+                .getGenericType();
+        final Map<TypeVariable<?>, Type> typeVarAssigns = TypeUtils.determineTypeArguments(TreeSet.class,
+                iterableType);
+        final TypeVariable<?> treeSetTypeVar = TreeSet.class.getTypeParameters()[0];
+        assertTrue(typeVarAssigns.containsKey(treeSetTypeVar));
+        assertEquals(iterableType.getActualTypeArguments()[0], typeVarAssigns
+                .get(treeSetTypeVar));
+    }
 
-    public static URI uri;
+    @Test
+    public void testGenericArrayType() throws Exception {
+        final Type expected = getClass().getField("intWildcardComparable").getGenericType();
+        final GenericArrayType actual =
+            TypeUtils.genericArrayType(TypeUtils.parameterize(Comparable.class, TypeUtils.wildcardType()
+                .withUpperBounds(Integer.class).build()));
+        assertTrue(TypeUtils.equals(expected, actual));
+        assertEquals("java.lang.Comparable<? extends java.lang.Integer>[]", actual.toString());
+    }
+
+    @Test
+    public void testGetArrayComponentType() throws Exception {
+        final Method method = getClass().getMethod("dummyMethod", List.class, List.class, List.class,
+                List.class, List.class, List.class, List.class, List[].class, List[].class,
+                List[].class, List[].class, List[].class, List[].class, List[].class);
+
+        final Type[] types = method.getGenericParameterTypes();
+
+        assertNull(TypeUtils.getArrayComponentType(types[0]));
+        assertNull(TypeUtils.getArrayComponentType(types[1]));
+        assertNull(TypeUtils.getArrayComponentType(types[2]));
+        assertNull(TypeUtils.getArrayComponentType(types[3]));
+        assertNull(TypeUtils.getArrayComponentType(types[4]));
+        assertNull(TypeUtils.getArrayComponentType(types[5]));
+        assertNull(TypeUtils.getArrayComponentType(types[6]));
+        assertEquals(types[0], TypeUtils.getArrayComponentType(types[7]));
+        assertEquals(types[1], TypeUtils.getArrayComponentType(types[8]));
+        assertEquals(types[2], TypeUtils.getArrayComponentType(types[9]));
+        assertEquals(types[3], TypeUtils.getArrayComponentType(types[10]));
+        assertEquals(types[4], TypeUtils.getArrayComponentType(types[11]));
+        assertEquals(types[5], TypeUtils.getArrayComponentType(types[12]));
+        assertEquals(types[6], TypeUtils.getArrayComponentType(types[13]));
+    }
+
+    @Test
+    public void testGetPrimitiveArrayComponentType() {
+        assertEquals(boolean.class, TypeUtils.getArrayComponentType(boolean[].class));
+        assertEquals(byte.class, TypeUtils.getArrayComponentType(byte[].class));
+        assertEquals(short.class, TypeUtils.getArrayComponentType(short[].class));
+        assertEquals(int.class, TypeUtils.getArrayComponentType(int[].class));
+        assertEquals(char.class, TypeUtils.getArrayComponentType(char[].class));
+        assertEquals(long.class, TypeUtils.getArrayComponentType(long[].class));
+        assertEquals(float.class, TypeUtils.getArrayComponentType(float[].class));
+        assertEquals(double.class, TypeUtils.getArrayComponentType(double[].class));
+
+        assertNull(TypeUtils.getArrayComponentType(boolean.class));
+        assertNull(TypeUtils.getArrayComponentType(byte.class));
+        assertNull(TypeUtils.getArrayComponentType(short.class));
+        assertNull(TypeUtils.getArrayComponentType(int.class));
+        assertNull(TypeUtils.getArrayComponentType(char.class));
+        assertNull(TypeUtils.getArrayComponentType(long.class));
+        assertNull(TypeUtils.getArrayComponentType(float.class));
+        assertNull(TypeUtils.getArrayComponentType(double.class));
+    }
+
+    @Test
+    public void testGetRawType() throws SecurityException, NoSuchFieldException {
+        final Type stringParentFieldType = GenericTypeHolder.class.getDeclaredField("stringParent")
+                .getGenericType();
+        final Type integerParentFieldType = GenericTypeHolder.class.getDeclaredField("integerParent")
+                .getGenericType();
+        final Type foosFieldType = GenericTypeHolder.class.getDeclaredField("foos").getGenericType();
+        final Type genericParentT = GenericParent.class.getTypeParameters()[0];
+        assertEquals(GenericParent.class, TypeUtils.getRawType(stringParentFieldType, null));
+        assertEquals(GenericParent.class, TypeUtils.getRawType(integerParentFieldType,
+                        null));
+        assertEquals(List.class, TypeUtils.getRawType(foosFieldType, null));
+        assertEquals(String.class, TypeUtils.getRawType(genericParentT,
+                StringParameterizedChild.class));
+        assertEquals(String.class, TypeUtils.getRawType(genericParentT,
+                stringParentFieldType));
+        assertEquals(Foo.class, TypeUtils.getRawType(Iterable.class.getTypeParameters()[0],
+                foosFieldType));
+        assertEquals(Foo.class, TypeUtils.getRawType(List.class.getTypeParameters()[0],
+                foosFieldType));
+        assertNull(TypeUtils.getRawType(genericParentT, GenericParent.class));
+        assertEquals(GenericParent[].class, TypeUtils.getRawType(GenericTypeHolder.class
+                .getDeclaredField("barParents").getGenericType(), null));
+    }
+
+    @Test
+    public void testGetTypeArguments() {
+        Map<TypeVariable<?>, Type> typeVarAssigns;
+        TypeVariable<?> treeSetTypeVar;
+        Type typeArg;
+
+        typeVarAssigns = TypeUtils.getTypeArguments(Integer.class, Comparable.class);
+        treeSetTypeVar = Comparable.class.getTypeParameters()[0];
+        assertTrue(typeVarAssigns.containsKey(treeSetTypeVar),
+                "Type var assigns for Comparable from Integer: " + typeVarAssigns);
+        typeArg = typeVarAssigns.get(treeSetTypeVar);
+        assertEquals(Integer.class, typeVarAssigns.get(treeSetTypeVar),
+                "Type argument of Comparable from Integer: " + typeArg);
+
+        typeVarAssigns = TypeUtils.getTypeArguments(int.class, Comparable.class);
+        treeSetTypeVar = Comparable.class.getTypeParameters()[0];
+        assertTrue(typeVarAssigns.containsKey(treeSetTypeVar),
+                "Type var assigns for Comparable from int: " + typeVarAssigns);
+        typeArg = typeVarAssigns.get(treeSetTypeVar);
+        assertEquals(Integer.class, typeVarAssigns.get(treeSetTypeVar),
+                "Type argument of Comparable from int: " + typeArg);
+
+        final Collection<Integer> col = Collections.emptyList();
+        typeVarAssigns = TypeUtils.getTypeArguments(List.class, Collection.class);
+        treeSetTypeVar = Comparable.class.getTypeParameters()[0];
+        assertFalse(typeVarAssigns.containsKey(treeSetTypeVar),
+                "Type var assigns for Collection from List: " + typeVarAssigns);
+
+        typeVarAssigns = TypeUtils.getTypeArguments(AAAClass.BBBClass.class, AAClass.BBClass.class);
+        assertEquals(2, typeVarAssigns.size());
+        assertEquals(String.class, typeVarAssigns.get(AAClass.class.getTypeParameters()[0]));
+        assertEquals(String.class, typeVarAssigns.get(AAClass.BBClass.class.getTypeParameters()[0]));
+
+        typeVarAssigns = TypeUtils.getTypeArguments(Other.class, This.class);
+        assertEquals(2, typeVarAssigns.size());
+        assertEquals(String.class, typeVarAssigns.get(This.class.getTypeParameters()[0]));
+        assertEquals(Other.class.getTypeParameters()[0], typeVarAssigns.get(This.class.getTypeParameters()[1]));
+
+        typeVarAssigns = TypeUtils.getTypeArguments(And.class, This.class);
+        assertEquals(2, typeVarAssigns.size());
+        assertEquals(Number.class, typeVarAssigns.get(This.class.getTypeParameters()[0]));
+        assertEquals(Number.class, typeVarAssigns.get(This.class.getTypeParameters()[1]));
+
+        typeVarAssigns = TypeUtils.getTypeArguments(Thing.class, Other.class);
+        assertEquals(2, typeVarAssigns.size());
+        assertEquals(getClass().getTypeParameters()[0], typeVarAssigns.get(getClass().getTypeParameters()[0]));
+        assertEquals(getClass().getTypeParameters()[0], typeVarAssigns.get(Other.class.getTypeParameters()[0]));
+    }
+
+    @Test
+    public void testIsArrayGenericTypes() throws Exception {
+        final Method method = getClass().getMethod("dummyMethod", List.class, List.class, List.class,
+                List.class, List.class, List.class, List.class, List[].class, List[].class,
+                List[].class, List[].class, List[].class, List[].class, List[].class);
+
+        final Type[] types = method.getGenericParameterTypes();
+
+        assertFalse(TypeUtils.isArrayType(types[0]));
+        assertFalse(TypeUtils.isArrayType(types[1]));
+        assertFalse(TypeUtils.isArrayType(types[2]));
+        assertFalse(TypeUtils.isArrayType(types[3]));
+        assertFalse(TypeUtils.isArrayType(types[4]));
+        assertFalse(TypeUtils.isArrayType(types[5]));
+        assertFalse(TypeUtils.isArrayType(types[6]));
+        assertTrue(TypeUtils.isArrayType(types[7]));
+        assertTrue(TypeUtils.isArrayType(types[8]));
+        assertTrue(TypeUtils.isArrayType(types[9]));
+        assertTrue(TypeUtils.isArrayType(types[10]));
+        assertTrue(TypeUtils.isArrayType(types[11]));
+        assertTrue(TypeUtils.isArrayType(types[12]));
+        assertTrue(TypeUtils.isArrayType(types[13]));
+    }
 
-    public static List<String>[] stringListArray;
+    @Test
+    public void testIsArrayTypeClasses() {
+        assertTrue(TypeUtils.isArrayType(boolean[].class));
+        assertTrue(TypeUtils.isArrayType(byte[].class));
+        assertTrue(TypeUtils.isArrayType(short[].class));
+        assertTrue(TypeUtils.isArrayType(int[].class));
+        assertTrue(TypeUtils.isArrayType(char[].class));
+        assertTrue(TypeUtils.isArrayType(long[].class));
+        assertTrue(TypeUtils.isArrayType(float[].class));
+        assertTrue(TypeUtils.isArrayType(double[].class));
+        assertTrue(TypeUtils.isArrayType(Object[].class));
+        assertTrue(TypeUtils.isArrayType(String[].class));
 
-    public void dummyMethod(final List list0, final List<Object> list1, final List<?> list2,
-            final List<? super Object> list3, final List<String> list4, final List<? extends String> list5,
-            final List<? super String> list6, final List[] list7, final List<Object>[] list8, final List<?>[] list9,
-            final List<? super Object>[] list10, final List<String>[] list11, final List<? extends String>[] list12,
-            final List<? super String>[] list13) {
+        assertFalse(TypeUtils.isArrayType(boolean.class));
+        assertFalse(TypeUtils.isArrayType(byte.class));
+        assertFalse(TypeUtils.isArrayType(short.class));
+        assertFalse(TypeUtils.isArrayType(int.class));
+        assertFalse(TypeUtils.isArrayType(char.class));
+        assertFalse(TypeUtils.isArrayType(long.class));
+        assertFalse(TypeUtils.isArrayType(float.class));
+        assertFalse(TypeUtils.isArrayType(double.class));
+        assertFalse(TypeUtils.isArrayType(Object.class));
+        assertFalse(TypeUtils.isArrayType(String.class));
     }
 
     @SuppressWarnings("boxing") // deliberately used here
@@ -428,316 +715,117 @@ public class TypeUtilsTest<B> {
         final Type cClassType = AClass.class.getField("cClass").getGenericType();
         final Type dClassType = AClass.class.getField("dClass").getGenericType();
         final Type eClassType = AClass.class.getField("eClass").getGenericType();
-        final Type fClassType = AClass.class.getField("fClass").getGenericType();
-        final AClass aClass = new AClass(new AAClass<>());
-        aClass.bClass = aClass.cClass;
-        assertTrue(TypeUtils.isAssignable(cClassType, bClassType));
-        aClass.bClass = aClass.dClass;
-        assertTrue(TypeUtils.isAssignable(dClassType, bClassType));
-        aClass.bClass = aClass.eClass;
-        assertTrue(TypeUtils.isAssignable(eClassType, bClassType));
-        aClass.bClass = aClass.fClass;
-        assertTrue(TypeUtils.isAssignable(fClassType, bClassType));
-        aClass.cClass = aClass.dClass;
-        assertTrue(TypeUtils.isAssignable(dClassType, cClassType));
-        aClass.cClass = aClass.eClass;
-        assertTrue(TypeUtils.isAssignable(eClassType, cClassType));
-        aClass.cClass = aClass.fClass;
-        assertTrue(TypeUtils.isAssignable(fClassType, cClassType));
-        aClass.dClass = aClass.eClass;
-        assertTrue(TypeUtils.isAssignable(eClassType, dClassType));
-        aClass.dClass = aClass.fClass;
-        assertTrue(TypeUtils.isAssignable(fClassType, dClassType));
-        aClass.eClass = aClass.fClass;
-        assertTrue(TypeUtils.isAssignable(fClassType, eClassType));
-    }
-
-    public void delegateBooleanAssertion(final Type[] types, final int i2, final int i1, final boolean expected) {
-        final Type type1 = types[i1];
-        final Type type2 = types[i2];
-        final boolean isAssignable = TypeUtils.isAssignable(type2, type1);
-
-        if (expected) {
-            assertTrue(isAssignable,
-                    "[" + i1 + ", " + i2 + "]: From "
-                                + String.valueOf(type2) + " to "
-                                + String.valueOf(type1));
-        } else {
-            assertFalse(isAssignable,
-                    "[" + i1 + ", " + i2 + "]: From "
-                                + String.valueOf(type2) + " to "
-                                + String.valueOf(type1));
-        }
-    }
-
-    @SuppressWarnings("boxing") // boxing is deliberate here
-    @Test
-    public void testIsInstance() throws SecurityException, NoSuchFieldException {
-        final Type intComparableType = getClass().getField("intComparable").getGenericType();
-        final Type uriComparableType = getClass().getField("uriComparable").getGenericType();
-        intComparable = 1;
-        assertTrue(TypeUtils.isInstance(1, intComparableType));
-        // uriComparable = 1;
-        assertFalse(TypeUtils.isInstance(1, uriComparableType));
-    }
-
-    @Test
-    public void testGetTypeArguments() {
-        Map<TypeVariable<?>, Type> typeVarAssigns;
-        TypeVariable<?> treeSetTypeVar;
-        Type typeArg;
-
-        typeVarAssigns = TypeUtils.getTypeArguments(Integer.class, Comparable.class);
-        treeSetTypeVar = Comparable.class.getTypeParameters()[0];
-        assertTrue(typeVarAssigns.containsKey(treeSetTypeVar),
-                "Type var assigns for Comparable from Integer: " + typeVarAssigns);
-        typeArg = typeVarAssigns.get(treeSetTypeVar);
-        assertEquals(Integer.class, typeVarAssigns.get(treeSetTypeVar),
-                "Type argument of Comparable from Integer: " + typeArg);
-
-        typeVarAssigns = TypeUtils.getTypeArguments(int.class, Comparable.class);
-        treeSetTypeVar = Comparable.class.getTypeParameters()[0];
-        assertTrue(typeVarAssigns.containsKey(treeSetTypeVar),
-                "Type var assigns for Comparable from int: " + typeVarAssigns);
-        typeArg = typeVarAssigns.get(treeSetTypeVar);
-        assertEquals(Integer.class, typeVarAssigns.get(treeSetTypeVar),
-                "Type argument of Comparable from int: " + typeArg);
-
-        final Collection<Integer> col = Collections.emptyList();
-        typeVarAssigns = TypeUtils.getTypeArguments(List.class, Collection.class);
-        treeSetTypeVar = Comparable.class.getTypeParameters()[0];
-        assertFalse(typeVarAssigns.containsKey(treeSetTypeVar),
-                "Type var assigns for Collection from List: " + typeVarAssigns);
-
-        typeVarAssigns = TypeUtils.getTypeArguments(AAAClass.BBBClass.class, AAClass.BBClass.class);
-        assertEquals(2, typeVarAssigns.size());
-        assertEquals(String.class, typeVarAssigns.get(AAClass.class.getTypeParameters()[0]));
-        assertEquals(String.class, typeVarAssigns.get(AAClass.BBClass.class.getTypeParameters()[0]));
-
-        typeVarAssigns = TypeUtils.getTypeArguments(Other.class, This.class);
-        assertEquals(2, typeVarAssigns.size());
-        assertEquals(String.class, typeVarAssigns.get(This.class.getTypeParameters()[0]));
-        assertEquals(Other.class.getTypeParameters()[0], typeVarAssigns.get(This.class.getTypeParameters()[1]));
-
-        typeVarAssigns = TypeUtils.getTypeArguments(And.class, This.class);
-        assertEquals(2, typeVarAssigns.size());
-        assertEquals(Number.class, typeVarAssigns.get(This.class.getTypeParameters()[0]));
-        assertEquals(Number.class, typeVarAssigns.get(This.class.getTypeParameters()[1]));
-
-        typeVarAssigns = TypeUtils.getTypeArguments(Thing.class, Other.class);
-        assertEquals(2, typeVarAssigns.size());
-        assertEquals(getClass().getTypeParameters()[0], typeVarAssigns.get(getClass().getTypeParameters()[0]));
-        assertEquals(getClass().getTypeParameters()[0], typeVarAssigns.get(Other.class.getTypeParameters()[0]));
-    }
-
-    @Test
-    public void testTypesSatisfyVariables() throws SecurityException,
-            NoSuchMethodException {
-        final Map<TypeVariable<?>, Type> typeVarAssigns = new HashMap<>();
-        final Integer max = TypeUtilsTest.<Integer>stub();
-        typeVarAssigns.put(getClass().getMethod("stub").getTypeParameters()[0], Integer.class);
-        assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
-        typeVarAssigns.clear();
-        typeVarAssigns.put(getClass().getMethod("stub2").getTypeParameters()[0], Integer.class);
-        assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
-        typeVarAssigns.clear();
-        typeVarAssigns.put(getClass().getMethod("stub3").getTypeParameters()[0], Integer.class);
-        assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
-    }
-
-    @Test
-    public void testDetermineTypeVariableAssignments() throws SecurityException,
-            NoSuchFieldException {
-        final ParameterizedType iterableType = (ParameterizedType) getClass().getField("iterable")
-                .getGenericType();
-        final Map<TypeVariable<?>, Type> typeVarAssigns = TypeUtils.determineTypeArguments(TreeSet.class,
-                iterableType);
-        final TypeVariable<?> treeSetTypeVar = TreeSet.class.getTypeParameters()[0];
-        assertTrue(typeVarAssigns.containsKey(treeSetTypeVar));
-        assertEquals(iterableType.getActualTypeArguments()[0], typeVarAssigns
-                .get(treeSetTypeVar));
-    }
-
-    @Test
-    public void testGetRawType() throws SecurityException, NoSuchFieldException {
-        final Type stringParentFieldType = GenericTypeHolder.class.getDeclaredField("stringParent")
-                .getGenericType();
-        final Type integerParentFieldType = GenericTypeHolder.class.getDeclaredField("integerParent")
-                .getGenericType();
-        final Type foosFieldType = GenericTypeHolder.class.getDeclaredField("foos").getGenericType();
-        final Type genericParentT = GenericParent.class.getTypeParameters()[0];
-        assertEquals(GenericParent.class, TypeUtils.getRawType(stringParentFieldType, null));
-        assertEquals(GenericParent.class, TypeUtils.getRawType(integerParentFieldType,
-                        null));
-        assertEquals(List.class, TypeUtils.getRawType(foosFieldType, null));
-        assertEquals(String.class, TypeUtils.getRawType(genericParentT,
-                StringParameterizedChild.class));
-        assertEquals(String.class, TypeUtils.getRawType(genericParentT,
-                stringParentFieldType));
-        assertEquals(Foo.class, TypeUtils.getRawType(Iterable.class.getTypeParameters()[0],
-                foosFieldType));
-        assertEquals(Foo.class, TypeUtils.getRawType(List.class.getTypeParameters()[0],
-                foosFieldType));
-        assertNull(TypeUtils.getRawType(genericParentT, GenericParent.class));
-        assertEquals(GenericParent[].class, TypeUtils.getRawType(GenericTypeHolder.class
-                .getDeclaredField("barParents").getGenericType(), null));
-    }
-
-    @Test
-    public void testIsArrayTypeClasses() {
-        assertTrue(TypeUtils.isArrayType(boolean[].class));
-        assertTrue(TypeUtils.isArrayType(byte[].class));
-        assertTrue(TypeUtils.isArrayType(short[].class));
-        assertTrue(TypeUtils.isArrayType(int[].class));
-        assertTrue(TypeUtils.isArrayType(char[].class));
-        assertTrue(TypeUtils.isArrayType(long[].class));
-        assertTrue(TypeUtils.isArrayType(float[].class));
-        assertTrue(TypeUtils.isArrayType(double[].class));
-        assertTrue(TypeUtils.isArrayType(Object[].class));
-        assertTrue(TypeUtils.isArrayType(String[].class));
-
-        assertFalse(TypeUtils.isArrayType(boolean.class));
-        assertFalse(TypeUtils.isArrayType(byte.class));
-        assertFalse(TypeUtils.isArrayType(short.class));
-        assertFalse(TypeUtils.isArrayType(int.class));
-        assertFalse(TypeUtils.isArrayType(char.class));
-        assertFalse(TypeUtils.isArrayType(long.class));
-        assertFalse(TypeUtils.isArrayType(float.class));
-        assertFalse(TypeUtils.isArrayType(double.class));
-        assertFalse(TypeUtils.isArrayType(Object.class));
-        assertFalse(TypeUtils.isArrayType(String.class));
-    }
-
-    @Test
-    public void testIsArrayGenericTypes() throws Exception {
-        final Method method = getClass().getMethod("dummyMethod", List.class, List.class, List.class,
-                List.class, List.class, List.class, List.class, List[].class, List[].class,
-                List[].class, List[].class, List[].class, List[].class, List[].class);
-
-        final Type[] types = method.getGenericParameterTypes();
-
-        assertFalse(TypeUtils.isArrayType(types[0]));
-        assertFalse(TypeUtils.isArrayType(types[1]));
-        assertFalse(TypeUtils.isArrayType(types[2]));
-        assertFalse(TypeUtils.isArrayType(types[3]));
-        assertFalse(TypeUtils.isArrayType(types[4]));
-        assertFalse(TypeUtils.isArrayType(types[5]));
-        assertFalse(TypeUtils.isArrayType(types[6]));
-        assertTrue(TypeUtils.isArrayType(types[7]));
-        assertTrue(TypeUtils.isArrayType(types[8]));
-        assertTrue(TypeUtils.isArrayType(types[9]));
-        assertTrue(TypeUtils.isArrayType(types[10]));
-        assertTrue(TypeUtils.isArrayType(types[11]));
-        assertTrue(TypeUtils.isArrayType(types[12]));
-        assertTrue(TypeUtils.isArrayType(types[13]));
-    }
-
-    @Test
-    public void testGetPrimitiveArrayComponentType() {
-        assertEquals(boolean.class, TypeUtils.getArrayComponentType(boolean[].class));
-        assertEquals(byte.class, TypeUtils.getArrayComponentType(byte[].class));
-        assertEquals(short.class, TypeUtils.getArrayComponentType(short[].class));
-        assertEquals(int.class, TypeUtils.getArrayComponentType(int[].class));
-        assertEquals(char.class, TypeUtils.getArrayComponentType(char[].class));
-        assertEquals(long.class, TypeUtils.getArrayComponentType(long[].class));
-        assertEquals(float.class, TypeUtils.getArrayComponentType(float[].class));
-        assertEquals(double.class, TypeUtils.getArrayComponentType(double[].class));
-
-        assertNull(TypeUtils.getArrayComponentType(boolean.class));
-        assertNull(TypeUtils.getArrayComponentType(byte.class));
-        assertNull(TypeUtils.getArrayComponentType(short.class));
-        assertNull(TypeUtils.getArrayComponentType(int.class));
-        assertNull(TypeUtils.getArrayComponentType(char.class));
-        assertNull(TypeUtils.getArrayComponentType(long.class));
-        assertNull(TypeUtils.getArrayComponentType(float.class));
-        assertNull(TypeUtils.getArrayComponentType(double.class));
+        final Type fClassType = AClass.class.getField("fClass").getGenericType();
+        final AClass aClass = new AClass(new AAClass<>());
+        aClass.bClass = aClass.cClass;
+        assertTrue(TypeUtils.isAssignable(cClassType, bClassType));
+        aClass.bClass = aClass.dClass;
+        assertTrue(TypeUtils.isAssignable(dClassType, bClassType));
+        aClass.bClass = aClass.eClass;
+        assertTrue(TypeUtils.isAssignable(eClassType, bClassType));
+        aClass.bClass = aClass.fClass;
+        assertTrue(TypeUtils.isAssignable(fClassType, bClassType));
+        aClass.cClass = aClass.dClass;
+        assertTrue(TypeUtils.isAssignable(dClassType, cClassType));
+        aClass.cClass = aClass.eClass;
+        assertTrue(TypeUtils.isAssignable(eClassType, cClassType));
+        aClass.cClass = aClass.fClass;
+        assertTrue(TypeUtils.isAssignable(fClassType, cClassType));
+        aClass.dClass = aClass.eClass;
+        assertTrue(TypeUtils.isAssignable(eClassType, dClassType));
+        aClass.dClass = aClass.fClass;
+        assertTrue(TypeUtils.isAssignable(fClassType, dClassType));
+        aClass.eClass = aClass.fClass;
+        assertTrue(TypeUtils.isAssignable(fClassType, eClassType));
     }
 
-    @Test
-    public void testGetArrayComponentType() throws Exception {
-        final Method method = getClass().getMethod("dummyMethod", List.class, List.class, List.class,
-                List.class, List.class, List.class, List.class, List[].class, List[].class,
-                List[].class, List[].class, List[].class, List[].class, List[].class);
+    private void testIsAssignable(Class testUnassignableClass) {
+        final Class<Constructor> rawClass = Constructor.class;
+        final Class<Insets> typeArgClass = Insets.class;
+        // Builds a ParameterizedType for Constructor<Insets>
+        ParameterizedType paramType = TypeUtils.parameterize(rawClass, typeArgClass);
+        assertEquals(rawClass, paramType.getRawType());
+        assertEquals(typeArgClass, paramType.getActualTypeArguments()[0]);
 
-        final Type[] types = method.getGenericParameterTypes();
+        assertFalse(testUnassignableClass.isAssignableFrom(paramType.getClass()));
+        assertFalse(paramType.getClass().isAssignableFrom(testUnassignableClass));
 
-        assertNull(TypeUtils.getArrayComponentType(types[0]));
-        assertNull(TypeUtils.getArrayComponentType(types[1]));
-        assertNull(TypeUtils.getArrayComponentType(types[2]));
-        assertNull(TypeUtils.getArrayComponentType(types[3]));
-        assertNull(TypeUtils.getArrayComponentType(types[4]));
-        assertNull(TypeUtils.getArrayComponentType(types[5]));
-        assertNull(TypeUtils.getArrayComponentType(types[6]));
-        assertEquals(types[0], TypeUtils.getArrayComponentType(types[7]));
-        assertEquals(types[1], TypeUtils.getArrayComponentType(types[8]));
-        assertEquals(types[2], TypeUtils.getArrayComponentType(types[9]));
-        assertEquals(types[3], TypeUtils.getArrayComponentType(types[10]));
-        assertEquals(types[4], TypeUtils.getArrayComponentType(types[11]));
-        assertEquals(types[5], TypeUtils.getArrayComponentType(types[12]));
-        assertEquals(types[6], TypeUtils.getArrayComponentType(types[13]));
+        GenericArrayType arrayType = TypeUtils.genericArrayType(paramType);
+        assertFalse(TypeUtils.isAssignable(arrayType, paramType),
+                () -> String.format("TypeUtils.isAssignable(%s, %s)", arrayType, paramType));
+        assertFalse(TypeUtils.isAssignable(paramType, arrayType),
+                () -> String.format("TypeUtils.isAssignable(%s, %s)", paramType, arrayType));
     }
 
     @Test
-    public void testLang820() {
-        final Type[] typeArray = {String.class, String.class};
-        final Type[] expectedArray = {String.class};
-        assertArrayEquals(expectedArray, TypeUtils.normalizeUpperBounds(typeArray));
-    }
+    public void testIsAssignableGenericArrayTypeToParameterizedType() {
+        final Class<Constructor> rawClass = Constructor.class;
+        final Class<Insets> typeArgClass = Insets.class;
+        // Builds a ParameterizedType for Constructor<Insets>
+        ParameterizedType paramType = TypeUtils.parameterize(rawClass, typeArgClass);
+        assertEquals(rawClass, paramType.getRawType());
+        assertEquals(typeArgClass, paramType.getActualTypeArguments()[0]);
 
-    @Test
-    public void testParameterize() throws Exception {
-        final ParameterizedType stringComparableType = TypeUtils.parameterize(Comparable.class, String.class);
-        assertTrue(TypeUtils.equals(getClass().getField("stringComparable").getGenericType(),
-            stringComparableType));
-        assertEquals("java.lang.Comparable<java.lang.String>", stringComparableType.toString());
-    }
+        assertFalse(GenericArrayType.class.isAssignableFrom(paramType.getClass()));
+        assertFalse(paramType.getClass().isAssignableFrom(GenericArrayType.class));
 
-    @Test
-    public void testParameterizeNarrowerTypeArray() {
-        final TypeVariable<?>[] variables = ArrayList.class.getTypeParameters();
-        final ParameterizedType parameterizedType = TypeUtils.parameterize(ArrayList.class, variables);
-        final Map<TypeVariable<?>, Type> mapping = Collections.<TypeVariable<?>, Type>singletonMap(variables[0], String.class);
-        final Type unrolled = TypeUtils.unrollVariables(mapping, parameterizedType);
-        assertEquals(TypeUtils.parameterize(ArrayList.class, String.class), unrolled);
+        GenericArrayType testType = TypeUtils.genericArrayType(paramType);
+        assertFalse(TypeUtils.isAssignable(paramType, testType),
+                () -> String.format("TypeUtils.isAssignable(%s, %s)", paramType, testType));
+        assertFalse(TypeUtils.isAssignable(testType, paramType),
+                () -> String.format("TypeUtils.isAssignable(%s, %s)", testType, paramType));
     }
 
     @Test
-    public void testParameterizeWithOwner() throws Exception {
-        final Type owner = TypeUtils.parameterize(TypeUtilsTest.class, String.class);
-        final ParameterizedType dat2Type = TypeUtils.parameterizeWithOwner(owner, That.class, String.class, String.class);
-        assertTrue(TypeUtils.equals(getClass().getField("dat2").getGenericType(), dat2Type));
+    @Disabled("TODO")
+    public void testIsAssignableGenericArrayTypeToWildercardType() {
+        final Class<Constructor> rawClass = Constructor.class;
+        final Class<Insets> typeArgClass = Insets.class;
+        // Builds a ParameterizedType for Constructor<Insets>
+        ParameterizedType paramType = TypeUtils.parameterize(rawClass, typeArgClass);
+        assertEquals(rawClass, paramType.getRawType());
+        assertEquals(typeArgClass, paramType.getActualTypeArguments()[0]);
+
+        assertFalse(WildcardType.class.isAssignableFrom(paramType.getClass()));
+        assertFalse(paramType.getClass().isAssignableFrom(WildcardType.class));
+
+        WildcardType testType = TypeUtils.WILDCARD_ALL;
+        // TODO This test returns true unlike the test above.
+        // Is this a bug in this test or in the main code?
+        assertFalse(TypeUtils.isAssignable(paramType, testType),
+                () -> String.format("TypeUtils.isAssignable(%s, %s)", paramType, testType));
+        assertFalse(TypeUtils.isAssignable(testType, paramType),
+                () -> String.format("TypeUtils.isAssignable(%s, %s)", testType, paramType));
     }
 
     @Test
-    public void testWildcardType() throws Exception {
-        final WildcardType simpleWildcard = TypeUtils.wildcardType().withUpperBounds(String.class).build();
-        final Field cClass = AClass.class.getField("cClass");
-        assertTrue(TypeUtils.equals(((ParameterizedType) cClass.getGenericType()).getActualTypeArguments()[0],
-            simpleWildcard));
-        assertEquals(String.format("? extends %s", String.class.getName()), TypeUtils.toString(simpleWildcard));
-        assertEquals(String.format("? extends %s", String.class.getName()), simpleWildcard.toString());
-    }
+    public void testIsAssignableGenericArrayTypeToObject() {
+        final Class<Constructor> rawClass = Constructor.class;
+        final Class<Insets> typeArgClass = Insets.class;
+        // Builds a ParameterizedType for Constructor<Insets>
+        ParameterizedType paramType = TypeUtils.parameterize(rawClass, typeArgClass);
+        assertEquals(rawClass, paramType.getRawType());
+        assertEquals(typeArgClass, paramType.getActualTypeArguments()[0]);
 
-    @Test
-    public void testUnboundedWildcardType() {
-        final WildcardType unbounded = TypeUtils.wildcardType().withLowerBounds((Type) null).withUpperBounds().build();
-        assertTrue(TypeUtils.equals(TypeUtils.WILDCARD_ALL, unbounded));
-        assertArrayEquals(new Type[] { Object.class }, TypeUtils.getImplicitUpperBounds(unbounded));
-        assertArrayEquals(new Type[] { null }, TypeUtils.getImplicitLowerBounds(unbounded));
-        assertEquals("?", TypeUtils.toString(unbounded));
-        assertEquals("?", unbounded.toString());
+        assertTrue(Object.class.isAssignableFrom(paramType.getClass()));
+        assertFalse(paramType.getClass().isAssignableFrom(Object.class));
+
+        Type testType = Object.class;
+        assertTrue(TypeUtils.isAssignable(paramType, testType),
+                () -> String.format("TypeUtils.isAssignable(%s, %s)", paramType, testType));
+        assertFalse(TypeUtils.isAssignable(testType, paramType),
+                () -> String.format("TypeUtils.isAssignable(%s, %s)", testType, paramType));
     }
 
+    @SuppressWarnings("boxing") // boxing is deliberate here
     @Test
-    public void testLowerBoundedWildcardType() {
-       final WildcardType lowerBounded = TypeUtils.wildcardType().withLowerBounds(java.sql.Date.class).build();
-       assertEquals(String.format("? super %s", java.sql.Date.class.getName()), TypeUtils.toString(lowerBounded));
-       assertEquals(String.format("? super %s", java.sql.Date.class.getName()), lowerBounded.toString());
-
-       final TypeVariable<Class<Iterable>> iterableT0 = Iterable.class.getTypeParameters()[0];
-       final WildcardType lowerTypeVariable = TypeUtils.wildcardType().withLowerBounds(iterableT0).build();
-       assertEquals(String.format("? super %s", iterableT0.getName()), TypeUtils.toString(lowerTypeVariable));
-       assertEquals(String.format("? super %s", iterableT0.getName()), lowerTypeVariable.toString());
+    public void testIsInstance() throws SecurityException, NoSuchFieldException {
+        final Type intComparableType = getClass().getField("intComparable").getGenericType();
+        final Type uriComparableType = getClass().getField("uriComparable").getGenericType();
+        intComparable = 1;
+        assertTrue(TypeUtils.isInstance(1, intComparableType));
+        // uriComparable = 1;
+        assertFalse(TypeUtils.isInstance(1, uriComparableType));
     }
 
     @Test
@@ -750,45 +838,6 @@ public class TypeUtilsTest<B> {
     }
 
     @Test
-    public void testGenericArrayType() throws Exception {
-        final Type expected = getClass().getField("intWildcardComparable").getGenericType();
-        final GenericArrayType actual =
-            TypeUtils.genericArrayType(TypeUtils.parameterize(Comparable.class, TypeUtils.wildcardType()
-                .withUpperBounds(Integer.class).build()));
-        assertTrue(TypeUtils.equals(expected, actual));
-        assertEquals("java.lang.Comparable<? extends java.lang.Integer>[]", actual.toString());
-    }
-
-    @Test
-    public void testToStringLang1311() {
-        assertEquals("int[]", TypeUtils.toString(int[].class));
-        assertEquals("java.lang.Integer[]", TypeUtils.toString(Integer[].class));
-        final Field stringListField = FieldUtils.getDeclaredField(getClass(), "stringListArray");
-        assertEquals("java.util.List<java.lang.String>[]", TypeUtils.toString(stringListField.getGenericType()));
-    }
-
-    @Test
-    public void testToLongString() {
-        assertEquals(getClass().getName() + ":B", TypeUtils.toLongString(getClass().getTypeParameters()[0]));
-    }
-
-    @Test
-    public void testWrap() {
-        final Type t = getClass().getTypeParameters()[0];
-        assertTrue(TypeUtils.equals(t, TypeUtils.wrap(t).getType()));
-
-        assertEquals(String.class, TypeUtils.wrap(String.class).getType());
-    }
-
-    public static class ClassWithSuperClassWithGenericType extends ArrayList<Object> {
-        private static final long serialVersionUID = 1L;
-
-        public static <U> Iterable<U> methodWithGenericReturnType() {
-            return null;
-        }
-    }
-
-    @Test
     public void testLANG1190() throws Exception {
         final Type fromType = ClassWithSuperClassWithGenericType.class.getDeclaredMethod("methodWithGenericReturnType").getGenericReturnType();
         final Type failingToType = TypeUtils.wildcardType().withLowerBounds(ClassWithSuperClassWithGenericType.class).build();
@@ -802,70 +851,102 @@ public class TypeUtilsTest<B> {
         assertEquals("T extends java.lang.Enum<T>", TypeUtils.toString(method.getGenericReturnType()));
     }
 
-    public Iterable<? extends Map<Integer, ? extends Collection<?>>> iterable;
-
-    public static <G extends Comparable<G>> G stub() {
-        return null;
-    }
-
-    public static <G extends Comparable<? super G>> G stub2() {
-        return null;
-    }
-
-    public static <T extends Comparable<? extends T>> T stub3() {
-        return null;
+    @Test
+    public void testLang820() {
+        final Type[] typeArray = {String.class, String.class};
+        final Type[] expectedArray = {String.class};
+        assertArrayEquals(expectedArray, TypeUtils.normalizeUpperBounds(typeArray));
     }
-}
 
-class AAClass<T> {
+    @Test
+    public void testLowerBoundedWildcardType() {
+       final WildcardType lowerBounded = TypeUtils.wildcardType().withLowerBounds(java.sql.Date.class).build();
+       assertEquals(String.format("? super %s", java.sql.Date.class.getName()), TypeUtils.toString(lowerBounded));
+       assertEquals(String.format("? super %s", java.sql.Date.class.getName()), lowerBounded.toString());
 
-    public class BBClass<S> {
+       final TypeVariable<Class<Iterable>> iterableT0 = Iterable.class.getTypeParameters()[0];
+       final WildcardType lowerTypeVariable = TypeUtils.wildcardType().withLowerBounds(iterableT0).build();
+       assertEquals(String.format("? super %s", iterableT0.getName()), TypeUtils.toString(lowerTypeVariable));
+       assertEquals(String.format("? super %s", iterableT0.getName()), lowerTypeVariable.toString());
     }
-}
 
-class AAAClass extends AAClass<String> {
-    public class BBBClass extends BBClass<String> {
+    @Test
+    public void testParameterize() throws Exception {
+        final ParameterizedType stringComparableType = TypeUtils.parameterize(Comparable.class, String.class);
+        assertTrue(TypeUtils.equals(getClass().getField("stringComparable").getGenericType(),
+            stringComparableType));
+        assertEquals("java.lang.Comparable<java.lang.String>", stringComparableType.toString());
     }
-}
-
-@SuppressWarnings("rawtypes")
-//raw types, where used, are used purposely
-class AClass extends AAClass<String>.BBClass<Number> {
 
-    AClass(final AAClass<String> enclosingInstance) {
-        enclosingInstance.super();
+    @Test
+    public void testParameterizeNarrowerTypeArray() {
+        final TypeVariable<?>[] variables = ArrayList.class.getTypeParameters();
+        final ParameterizedType parameterizedType = TypeUtils.parameterize(ArrayList.class, variables);
+        final Map<TypeVariable<?>, Type> mapping = Collections.<TypeVariable<?>, Type>singletonMap(variables[0], String.class);
+        final Type unrolled = TypeUtils.unrollVariables(mapping, parameterizedType);
+        assertEquals(TypeUtils.parameterize(ArrayList.class, String.class), unrolled);
     }
 
-    public class BClass<T> {
+    @Test
+    public void testParameterizeWithOwner() throws Exception {
+        final Type owner = TypeUtils.parameterize(TypeUtilsTest.class, String.class);
+        final ParameterizedType dat2Type = TypeUtils.parameterizeWithOwner(owner, That.class, String.class, String.class);
+        assertTrue(TypeUtils.equals(getClass().getField("dat2").getGenericType(), dat2Type));
     }
 
-    public class CClass<T> extends BClass {
+    @Test
+    public void testToLongString() {
+        assertEquals(getClass().getName() + ":B", TypeUtils.toLongString(getClass().getTypeParameters()[0]));
     }
 
-    public class DClass<T> extends CClass<T> {
+    @Test
+    public void testToStringLang1311() {
+        assertEquals("int[]", TypeUtils.toString(int[].class));
+        assertEquals("java.lang.Integer[]", TypeUtils.toString(Integer[].class));
+        final Field stringListField = FieldUtils.getDeclaredField(getClass(), "stringListArray");
+        assertEquals("java.util.List<java.lang.String>[]", TypeUtils.toString(stringListField.getGenericType()));
     }
 
-    public class EClass<T> extends DClass {
+    @Test
+    public void testTypesSatisfyVariables() throws SecurityException,
+            NoSuchMethodException {
+        final Map<TypeVariable<?>, Type> typeVarAssigns = new HashMap<>();
+        final Integer max = TypeUtilsTest.<Integer>stub();
+        typeVarAssigns.put(getClass().getMethod("stub").getTypeParameters()[0], Integer.class);
+        assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
+        typeVarAssigns.clear();
+        typeVarAssigns.put(getClass().getMethod("stub2").getTypeParameters()[0], Integer.class);
+        assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
+        typeVarAssigns.clear();
+        typeVarAssigns.put(getClass().getMethod("stub3").getTypeParameters()[0], Integer.class);
+        assertTrue(TypeUtils.typesSatisfyVariables(typeVarAssigns));
     }
 
-    public class FClass extends EClass<String> {
+    @Test
+    public void testUnboundedWildcardType() {
+        final WildcardType unbounded = TypeUtils.wildcardType().withLowerBounds((Type) null).withUpperBounds().build();
+        assertTrue(TypeUtils.equals(TypeUtils.WILDCARD_ALL, unbounded));
+        assertArrayEquals(new Type[] { Object.class }, TypeUtils.getImplicitUpperBounds(unbounded));
+        assertArrayEquals(new Type[] { null }, TypeUtils.getImplicitLowerBounds(unbounded));
+        assertEquals("?", TypeUtils.toString(unbounded));
+        assertEquals("?", unbounded.toString());
     }
 
-    public class GClass<T extends BClass<? extends T> & AInterface<AInterface<? super T>>> {
+    @Test
+    public void testWildcardType() throws Exception {
+        final WildcardType simpleWildcard = TypeUtils.wildcardType().withUpperBounds(String.class).build();
+        final Field cClass = AClass.class.getField("cClass");
+        assertTrue(TypeUtils.equals(((ParameterizedType) cClass.getGenericType()).getActualTypeArguments()[0],
+            simpleWildcard));
+        assertEquals(String.format("? extends %s", String.class.getName()), TypeUtils.toString(simpleWildcard));
+        assertEquals(String.format("? extends %s", String.class.getName()), simpleWildcard.toString());
     }
 
-    public BClass<Number> bClass;
-
-    public CClass<? extends String> cClass;
-
-    public DClass<String> dClass;
-
-    public EClass<String> eClass;
-
-    public FClass fClass;
-
-    public GClass gClass;
+    @Test
+    public void testWrap() {
+        final Type t = getClass().getTypeParameters()[0];
+        assertTrue(TypeUtils.equals(t, TypeUtils.wrap(t).getType()));
 
-    public interface AInterface<T> {
+        assertEquals(String.class, TypeUtils.wrap(String.class).getType());
     }
 }