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

garydgregory 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 45f08d9e3 Fix TypeUtils.toString() recursion and bound handling on 
recursive generic types (#1789).
45f08d9e3 is described below

commit 45f08d9e3b03177e12559878fc95cf3266b65052
Author: Gary Gregory <[email protected]>
AuthorDate: Sun Sep 13 15:26:35 2026 -0700

    Fix TypeUtils.toString() recursion and bound handling on recursive
    generic types (#1789).
    
    Sort members.
---
 src/changes/changes.xml                            |   1 +
 .../apache/commons/lang3/reflect/TypeUtils.java    |  66 +--
 .../commons/lang3/reflect/TypeUtilsTest.java       | 640 ++++++++++-----------
 3 files changed, 354 insertions(+), 353 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3801cfd96..22a98d042 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -284,6 +284,7 @@ java.lang.NullPointerException: Cannot invoke
     <action                   type="fix" dev="ggregory" due-to="Jeff Lenamon, 
Gary Gregory">Fix MethodUtils.invokeMethod on instances of non-public classes 
(#1783).</action>
     <action                   type="fix" dev="ggregory" due-to="Jeff Lenamon, 
Gary Gregory">Fraction.add and subtract return the reduced form when an operand 
is zero (#1787).</action>
     <action                   type="fix" dev="ggregory" due-to="alhuda, Gary 
Gregory">Return null for out-of-range offset in FastTimeZone.getGmtTimeZone 
(#1788).</action>
+    <action                   type="fix" dev="ggregory" due-to="gaurav kumar 
pandey, Gary Gregory">Fix TypeUtils.toString() recursion and bound handling on 
recursive generic types (#1789).</action>
     <!-- ADD -->
     <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">Add JavaVersion.JAVA_27.</action>
     <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">Add SystemUtils.IS_JAVA_27.</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 4c8491efd..f36a6ccf2 100644
--- a/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
+++ b/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
@@ -336,23 +336,12 @@ public String toString() {
      */
     public static final WildcardType WILDCARD_ALL = 
wildcardType().withUpperBounds(Object.class).build();
 
+    private static final ThreadLocal<Set<Type>> VISITING = 
ThreadLocal.withInitial(() -> Collections.newSetFromMap(new 
IdentityHashMap<>()));
+
     private static <T> String anyToString(final T object) {
         return object instanceof Type ? toString((Type) object) : 
object.toString();
     }
 
-    /**
-     * Formats a {@link Type} as a type reference string (type variables are 
formatted by name only without bounds).
-     *
-     * @param type The type to format.
-     * @return String.
-     */
-    private static String toReferenceString(final Type type) {
-        if (type instanceof TypeVariable<?>) {
-            return ((TypeVariable<?>) type).getName();
-        }
-        return toString(type);
-    }
-
 
     /**
      * Formats a {@link Class} as a {@link String}.
@@ -1531,6 +1520,28 @@ private static Type substituteTypeVariables(final Type 
type, final Map<TypeVaria
         return type;
     }
 
+    private static String toCyclicString(final Type type) {
+        if (type instanceof Class<?>) {
+            return ((Class<?>) type).getSimpleName() + "(cycle)";
+        }
+        if (type instanceof TypeVariable<?>) {
+            return ((TypeVariable<?>) type).getName() + "(cycle)";
+        }
+        if (type instanceof WildcardType) {
+            return "? (cycle)";
+        }
+        if (type instanceof ParameterizedType) {
+            final ParameterizedType pt = (ParameterizedType) type;
+            final Type raw = pt.getRawType();
+            final String rawName = raw instanceof Class<?> ? ((Class<?>) 
raw).getSimpleName() : raw.getTypeName();
+            return rawName + "(cycle)";
+        }
+        if (type instanceof GenericArrayType) {
+            return "(cycle)";
+        }
+        return ObjectUtils.identityToString(type) + "(cycle)";
+    }
+
     /**
      * Formats a {@link TypeVariable} including its {@link GenericDeclaration}.
      *
@@ -1561,28 +1572,17 @@ public static String toLongString(final TypeVariable<?> 
typeVariable) {
         return buf.append(':').append(toString(typeVariable)).toString();
     }
 
-    private static final ThreadLocal<Set<Type>> VISITING = 
ThreadLocal.withInitial(() -> Collections.newSetFromMap(new 
IdentityHashMap<>()));
-
-    private static String toCyclicString(final Type type) {
-        if (type instanceof Class<?>) {
-            return ((Class<?>) type).getSimpleName() + "(cycle)";
-        }
+    /**
+     * Formats a {@link Type} as a type reference string (type variables are 
formatted by name only without bounds).
+     *
+     * @param type The type to format.
+     * @return String.
+     */
+    private static String toReferenceString(final Type type) {
         if (type instanceof TypeVariable<?>) {
-            return ((TypeVariable<?>) type).getName() + "(cycle)";
-        }
-        if (type instanceof WildcardType) {
-            return "? (cycle)";
-        }
-        if (type instanceof ParameterizedType) {
-            final ParameterizedType pt = (ParameterizedType) type;
-            final Type raw = pt.getRawType();
-            final String rawName = raw instanceof Class<?> ? ((Class<?>) 
raw).getSimpleName() : raw.getTypeName();
-            return rawName + "(cycle)";
-        }
-        if (type instanceof GenericArrayType) {
-            return "(cycle)";
+            return ((TypeVariable<?>) type).getName();
         }
-        return ObjectUtils.identityToString(type) + "(cycle)";
+        return toString(type);
     }
 
     /**
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 6c00f8204..291cfd45d 100644
--- a/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
@@ -153,33 +153,11 @@ public class GClass<T extends BClass<? extends T> & 
AInterface<AInterface<? supe
         enclosingInstance.super();
     }
 }
-@SuppressWarnings("rawtypes")
-abstract class Test1<G> {
-    public abstract Object m0();
-    public abstract String[] m1();
-    public abstract <K, V> Map<? extends K, V[]> m10();
-    public abstract <K, V> Map<? extends K, List<V[]>> m11();
-    public abstract List m12();
-    public abstract Map m13();
-    public abstract Properties m14();
-    public abstract G m15();
-    public abstract List<G> m16();
-    public abstract Enum m17();
-    public abstract <E> E[] m2();
-    public abstract <E> List<? extends E> m3();
-    public abstract <E extends Enum<E>> List<? extends Enum<E>> m4();
-    public abstract List<? extends Enum<?>> m5();
-    public abstract List<? super Enum<?>> m6();
-    public abstract List<?> m7();
-    public abstract Map<? extends Enum<?>, ? super Enum<?>> m8();
-    public abstract <K, V> Map<? extends K, ? super V[]> m9();
-}
-
-class MySuperClass<T> {
+class DependentBounds<T extends Number, S extends T> {
     // empty
 }
 
-class MyClass<U extends MySuperClass<? super U>> {
+class InterfaceBound<T extends List<String>> {
     // empty
 }
 
@@ -187,15 +165,11 @@ class MultiBoundClass<U extends Number & Comparable<? 
super U>> {
     // empty
 }
 
-class TwoParams<T extends TwoParams<T, U>, U> {
-    // empty
-}
-
-class InterfaceBound<T extends List<String>> {
+class MyClass<U extends MySuperClass<? super U>> {
     // empty
 }
 
-class DependentBounds<T extends Number, S extends T> {
+class MySuperClass<T> {
     // empty
 }
 
@@ -209,6 +183,32 @@ public NonGenericInner getInner() {
     }
 }
 
+@SuppressWarnings("rawtypes")
+abstract class Test1<G> {
+    public abstract Object m0();
+    public abstract String[] m1();
+    public abstract <K, V> Map<? extends K, V[]> m10();
+    public abstract <K, V> Map<? extends K, List<V[]>> m11();
+    public abstract List m12();
+    public abstract Map m13();
+    public abstract Properties m14();
+    public abstract G m15();
+    public abstract List<G> m16();
+    public abstract Enum m17();
+    public abstract <E> E[] m2();
+    public abstract <E> List<? extends E> m3();
+    public abstract <E extends Enum<E>> List<? extends Enum<E>> m4();
+    public abstract List<? extends Enum<?>> m5();
+    public abstract List<? super Enum<?>> m6();
+    public abstract List<?> m7();
+    public abstract Map<? extends Enum<?>, ? super Enum<?>> m8();
+    public abstract <K, V> Map<? extends K, ? super V[]> m9();
+}
+
+class TwoParams<T extends TwoParams<T, U>, U> {
+    // empty
+}
+
 /**
  * Tests {@link TypeUtils}.
  *
@@ -450,6 +450,20 @@ void test_LANG_1702() throws NoSuchMethodException, 
SecurityException {
         final Type unrolledType = TypeUtils.unrollVariables(typeArguments, 
type);
     }
 
+    @Test
+    void testBoundedGenericArrayTypeToString() {
+        final TypeVariable<?> t = DependentBounds.class.getTypeParameters()[0];
+        final GenericArrayType gat = TypeUtils.genericArrayType(t);
+        assertEquals("T[]", TypeUtils.toString(gat));
+    }
+
+    @Test
+    void testBoundedParameterizedTypeArgumentToString() {
+        final TypeVariable<?> t = DependentBounds.class.getTypeParameters()[0];
+        final ParameterizedType pt = TypeUtils.parameterize(List.class, t);
+        assertEquals("java.util.List<T>", TypeUtils.toString(pt));
+    }
+
     @Test
     void testContainsTypeVariables() throws NoSuchMethodException {
         
assertFalse(TypeUtils.containsTypeVariables(Test1.class.getMethod("m0").getGenericReturnType()));
@@ -472,6 +486,17 @@ void testContainsTypeVariables() throws 
NoSuchMethodException {
         
assertTrue(TypeUtils.containsTypeVariables(Test1.class.getMethod("m17").getGenericReturnType()));
     }
 
+    @Test
+    void testContainsTypeVariablesMultiBoundWildcard() {
+        final TypeVariable<?> t = getClass().getTypeParameters()[0];
+        final WildcardType wtUpper = 
TypeUtils.wildcardType().withUpperBounds(Integer.class, t).build();
+        assertTrue(TypeUtils.containsTypeVariables(wtUpper));
+        final WildcardType wtLower = 
TypeUtils.wildcardType().withLowerBounds(Integer.class, t).build();
+        assertTrue(TypeUtils.containsTypeVariables(wtLower));
+        final WildcardType wtNone = 
TypeUtils.wildcardType().withUpperBounds(Integer.class, String.class).build();
+        assertFalse(TypeUtils.containsTypeVariables(wtNone));
+    }
+
     @Test
     void testContainsTypeVariablesPr437() throws Exception {
         abstract class Test2<G> {
@@ -515,6 +540,126 @@ abstract class Test2<G> {
         
assertTrue(TypeUtils.containsTypeVariables(Test2.class.getMethod("m17").getGenericReturnType()));
     }
 
+    @Test
+    void testCyclicGenericArrayTypeToString() {
+        final GenericArrayType[] holder = new GenericArrayType[1];
+        final GenericArrayType cyclicType = () -> holder[0];
+        holder[0] = cyclicType;
+        assertEquals("(cycle)[]", TypeUtils.toString(cyclicType));
+    }
+
+    @Test
+    void testCyclicOwnerParameterizedTypeToString() {
+        final ParameterizedType[] holder = new ParameterizedType[1];
+        final ParameterizedType cyclicOwnerType = new ParameterizedType() {
+            @Override
+            public Type[] getActualTypeArguments() {
+                return ArrayUtils.EMPTY_TYPE_ARRAY;
+            }
+
+            @Override
+            public Type getOwnerType() {
+                return holder[0];
+            }
+
+            @Override
+            public Type getRawType() {
+                return List.class;
+            }
+        };
+        holder[0] = cyclicOwnerType;
+        assertEquals("List(cycle).List", TypeUtils.toString(cyclicOwnerType));
+
+        final ParameterizedType[] holderA = new ParameterizedType[1];
+        final ParameterizedType[] holderB = new ParameterizedType[1];
+        final ParameterizedType typeA = new ParameterizedType() {
+            @Override
+            public Type[] getActualTypeArguments() {
+                return ArrayUtils.EMPTY_TYPE_ARRAY;
+            }
+
+            @Override
+            public Type getOwnerType() {
+                return holderB[0];
+            }
+
+            @Override
+            public Type getRawType() {
+                return Map.class;
+            }
+        };
+        final ParameterizedType typeB = new ParameterizedType() {
+            @Override
+            public Type[] getActualTypeArguments() {
+                return ArrayUtils.EMPTY_TYPE_ARRAY;
+            }
+
+            @Override
+            public Type getOwnerType() {
+                return holderA[0];
+            }
+
+            @Override
+            public Type getRawType() {
+                return Set.class;
+            }
+        };
+        holderA[0] = typeA;
+        holderB[0] = typeB;
+        assertEquals("Map(cycle).Set.Map", TypeUtils.toString(typeA));
+    }
+
+    @Test
+    void testCyclicParameterizedTypeToString() {
+        final ParameterizedType[] holder = new ParameterizedType[1];
+        final ParameterizedType cyclicType = new ParameterizedType() {
+            @Override
+            public Type[] getActualTypeArguments() {
+                return new Type[] { holder[0] };
+            }
+
+            @Override
+            public Type getOwnerType() {
+                return null;
+            }
+
+            @Override
+            public Type getRawType() {
+                return List.class;
+            }
+        };
+        holder[0] = cyclicType;
+        assertEquals("java.util.List<List(cycle)>", 
TypeUtils.toString(cyclicType));
+    }
+
+    @Test
+    void testCyclicWildcardTypeToString() {
+        final WildcardType[] holder = new WildcardType[1];
+        final WildcardType cyclicWildcard = new WildcardType() {
+            @Override
+            public Type[] getLowerBounds() {
+                return ArrayUtils.EMPTY_TYPE_ARRAY;
+            }
+
+            @Override
+            public Type[] getUpperBounds() {
+                return new Type[] { holder[0] };
+            }
+        };
+        holder[0] = cyclicWildcard;
+        assertEquals("? extends ? (cycle)", 
TypeUtils.toString(cyclicWildcard));
+    }
+
+    @Test
+    void testDependentBoundsClassAndTypeParametersToString() {
+        assertEquals("org.apache.commons.lang3.reflect.DependentBounds<T 
extends java.lang.Number, S extends T>",
+                TypeUtils.toString(DependentBounds.class));
+        assertEquals("T extends java.lang.Number",
+                
TypeUtils.toString(DependentBounds.class.getTypeParameters()[0]));
+        assertEquals("S extends T",
+                
TypeUtils.toString(DependentBounds.class.getTypeParameters()[1]));
+    }
+
     @Test
     void testDeprecatedConstructor() {
         assertNotNull(new TypeUtils().toString());
@@ -545,6 +690,13 @@ void testEquals() throws NoSuchFieldException {
         assertFalse(TypeUtils.equals(null, gat1));
     }
 
+    @Test
+    void testGClassToString() {
+        assertEquals("org.apache.commons.lang3.reflect.AClass.GClass<T extends 
org.apache.commons.lang3.reflect.AClass.BClass<? extends T> "
+                + "& 
org.apache.commons.lang3.reflect.AClass.AInterface<org.apache.commons.lang3.reflect.AClass.AInterface<?
 super T>>>",
+                TypeUtils.toString(AClass.GClass.class));
+    }
+
     @SuppressWarnings("unlikely-arg-type")
     @Test
     void testGenericArrayType() throws NoSuchFieldException {
@@ -695,6 +847,12 @@ void testGetTypeArguments() {
         assertEquals(getClass().getTypeParameters()[0], 
typeVarAssigns.get(Other.class.getTypeParameters()[0]));
     }
 
+    @Test
+    void testInterfaceBoundPreserved() {
+        assertEquals("T extends java.util.List<java.lang.String>",
+                
TypeUtils.toString(InterfaceBound.class.getTypeParameters()[0]));
+    }
+
     @Test
     void testIsArrayGenericTypes() throws NoSuchFieldException {
         final Type rawListType = 
GenericTypeHolder.class.getDeclaredField("rawList").getGenericType();
@@ -1155,6 +1313,21 @@ void testLowerBoundedWildcardType() {
        assertEquals(String.format("? super %s", iterableT0.getName()), 
lowerTypeVariable.toString());
     }
 
+    @Test
+    void testMultiBoundRecursiveType() {
+        assertEquals("org.apache.commons.lang3.reflect.MultiBoundClass<U 
extends java.lang.Number & java.lang.Comparable<? super U>>",
+                TypeUtils.toString(MultiBoundClass.class));
+        assertEquals("U extends java.lang.Number & java.lang.Comparable<? 
super U>",
+                
TypeUtils.toString(MultiBoundClass.class.getTypeParameters()[0]));
+    }
+
+    @Test
+    void testMultiParamRecursiveType() {
+        final ParameterizedType parameterizedType = 
TypeUtils.parameterize(TwoParams.class, TwoParams.class.getTypeParameters());
+        assertEquals("org.apache.commons.lang3.reflect.TwoParams<T, U>",
+                TypeUtils.toString(parameterizedType));
+    }
+
     @Test
     void testNormalizeUpperBounds() {
         final Type[] typeArray = { Collection.class, List.class };
@@ -1169,6 +1342,18 @@ void testNormalizeUpperBounds_LANG_820() {
         assertArrayEquals(expectedArray, 
TypeUtils.normalizeUpperBounds(typeArray));
     }
 
+    @Test
+    void testParameterizedOwnerWithNonGenericInnerClassToString() throws 
NoSuchMethodException {
+        final ParameterizedType owner = 
TypeUtils.parameterize(ParameterizedOwner.class, String.class);
+        final ParameterizedType nonGenericInner = 
TypeUtils.parameterizeWithOwner(owner, 
ParameterizedOwner.NonGenericInner.class);
+        
assertEquals("org.apache.commons.lang3.reflect.ParameterizedOwner<java.lang.String>.NonGenericInner",
+                TypeUtils.toString(nonGenericInner));
+
+        final Type methodReturnType = 
ParameterizedOwner.class.getMethod("getInner").getGenericReturnType();
+        
assertEquals("org.apache.commons.lang3.reflect.ParameterizedOwner<T>.NonGenericInner",
+                TypeUtils.toString(methodReturnType));
+    }
+
     @Test
     void testParameterizeMapArg() throws NoSuchFieldException {
         final Map<TypeVariable<?>, Type> typeVariableMap = new HashMap<>();
@@ -1245,17 +1430,107 @@ void 
testParameterizeWithOwnerVarArgsNullPointerException() {
     }
 
     @Test
-    void testToLongString() {
-        assertNullPointerException(() -> TypeUtils.toLongString(null));
-        assertEquals(getClass().getName() + ":B", 
TypeUtils.toLongString(getClass().getTypeParameters()[0]));
-        assertEquals(getClass().getName() + ".MyInnerClass:T", 
TypeUtils.toLongString(MyInnerClass.class.getTypeParameters()[0]));
-        assertEquals(getClass().getName() + ".That:K", 
TypeUtils.toLongString(That.class.getTypeParameters()[0]));
-        assertEquals(getClass().getName() + ".The:K", 
TypeUtils.toLongString(The.class.getTypeParameters()[0]));
-        assertEquals(getClass().getName() + ".MyInnerClass.MyInnerClass2:X", 
TypeUtils.toLongString(MyInnerClass.MyInnerClass2.class.getTypeParameters()[0]));
-    }
-
-    @Test
-    void testToString() {
+    void testRecursiveTypeWildcardBoundClass() {
+        assertEquals("org.apache.commons.lang3.reflect.MyClass<U extends 
org.apache.commons.lang3.reflect.MySuperClass<? super U>>",
+                TypeUtils.toString(MyClass.class));
+        assertEquals("U extends 
org.apache.commons.lang3.reflect.MySuperClass<? super U>",
+                TypeUtils.toString(MyClass.class.getTypeParameters()[0]));
+    }
+
+    @Test
+    void testRepeatedSiblingReferencesToString() {
+        final ParameterizedType listString = 
TypeUtils.parameterize(List.class, String.class);
+        final ParameterizedType mapType = TypeUtils.parameterize(Map.class, 
listString, listString);
+        assertEquals("java.util.Map<java.util.List<java.lang.String>, 
java.util.List<java.lang.String>>",
+                TypeUtils.toString(mapType));
+
+        final TypeVariable<?> t = DependentBounds.class.getTypeParameters()[0];
+        final ParameterizedType biFunctionType = 
TypeUtils.parameterize(BiFunction.class, t, t, t);
+        assertEquals("java.util.function.BiFunction<T, T, T>", 
TypeUtils.toString(biFunctionType));
+
+        final WildcardType wildcard = 
TypeUtils.wildcardType().withUpperBounds(listString).build();
+        final ParameterizedType mapWildcards = 
TypeUtils.parameterize(Map.class, wildcard, wildcard);
+        assertEquals("java.util.Map<? extends 
java.util.List<java.lang.String>, ? extends java.util.List<java.lang.String>>",
+                TypeUtils.toString(mapWildcards));
+    }
+
+    @Test
+    void testThreadLocalCleanupAfterException() {
+        final Type unsupportedType = new Type() {
+            @Override
+            public String getTypeName() {
+                return "Unsupported";
+            }
+        };
+        assertThrows(IllegalArgumentException.class, () -> 
TypeUtils.toString(unsupportedType));
+        assertEquals("java.lang.String", TypeUtils.toString(String.class));
+
+        final Type faultyType = new ParameterizedType() {
+            @Override
+            public Type[] getActualTypeArguments() {
+                throw new IllegalStateException("Simulated failure in 
getActualTypeArguments");
+            }
+
+            @Override
+            public Type getOwnerType() {
+                return null;
+            }
+
+            @Override
+            public Type getRawType() {
+                return List.class;
+            }
+        };
+        assertThrows(IllegalStateException.class, () -> 
TypeUtils.toString(faultyType));
+        assertEquals("java.lang.String", TypeUtils.toString(String.class));
+
+        final ParameterizedType wrapper = new ParameterizedType() {
+            @Override
+            public Type[] getActualTypeArguments() {
+                return new Type[] { faultyType };
+            }
+
+            @Override
+            public Type getOwnerType() {
+                return null;
+            }
+
+            @Override
+            public Type getRawType() {
+                return Set.class;
+            }
+        };
+        assertThrows(IllegalStateException.class, () -> 
TypeUtils.toString(wrapper));
+        assertEquals("java.util.List<java.lang.String>",
+                TypeUtils.toString(TypeUtils.parameterize(List.class, 
String.class)));
+    }
+
+    @Test
+    void testToLongString() {
+        assertNullPointerException(() -> TypeUtils.toLongString(null));
+        assertEquals(getClass().getName() + ":B", 
TypeUtils.toLongString(getClass().getTypeParameters()[0]));
+        assertEquals(getClass().getName() + ".MyInnerClass:T", 
TypeUtils.toLongString(MyInnerClass.class.getTypeParameters()[0]));
+        assertEquals(getClass().getName() + ".That:K", 
TypeUtils.toLongString(That.class.getTypeParameters()[0]));
+        assertEquals(getClass().getName() + ".The:K", 
TypeUtils.toLongString(The.class.getTypeParameters()[0]));
+        assertEquals(getClass().getName() + ".MyInnerClass.MyInnerClass2:X", 
TypeUtils.toLongString(MyInnerClass.MyInnerClass2.class.getTypeParameters()[0]));
+    }
+
+    @Test
+    void testToLongStringBoundedTypeVariable() {
+        assertEquals("org.apache.commons.lang3.reflect.DependentBounds:T 
extends java.lang.Number",
+                
TypeUtils.toLongString(DependentBounds.class.getTypeParameters()[0]));
+        assertEquals("org.apache.commons.lang3.reflect.DependentBounds:S 
extends T",
+                
TypeUtils.toLongString(DependentBounds.class.getTypeParameters()[1]));
+        assertEquals("org.apache.commons.lang3.reflect.MultiBoundClass:U 
extends java.lang.Number & java.lang.Comparable<? super U>",
+                
TypeUtils.toLongString(MultiBoundClass.class.getTypeParameters()[0]));
+        assertEquals("org.apache.commons.lang3.reflect.InterfaceBound:T 
extends java.util.List<java.lang.String>",
+                
TypeUtils.toLongString(InterfaceBound.class.getTypeParameters()[0]));
+        assertEquals("org.apache.commons.lang3.reflect.MyClass:U extends 
org.apache.commons.lang3.reflect.MySuperClass<? super U>",
+                TypeUtils.toLongString(MyClass.class.getTypeParameters()[0]));
+    }
+
+    @Test
+    void testToString() {
         assertNullPointerException(() -> TypeUtils.toString(null));
         assertIllegalArgumentException(() -> TypeUtils.toString(new Type() {
             // empty
@@ -1327,60 +1602,6 @@ void testWildcardType() throws NoSuchFieldException {
         
assertFalse(simpleWildcard.equals(TypeUtils.genericArrayType(String.class)));
     }
 
-    @Test
-    void testWrap() {
-        final Type t = getClass().getTypeParameters()[0];
-        assertTrue(TypeUtils.equals(t, TypeUtils.wrap(t).getType()));
-        assertEquals(String.class, TypeUtils.wrap(String.class).getType());
-    }
-
-    @Test
-    void testRecursiveTypeWildcardBoundClass() {
-        assertEquals("org.apache.commons.lang3.reflect.MyClass<U extends 
org.apache.commons.lang3.reflect.MySuperClass<? super U>>",
-                TypeUtils.toString(MyClass.class));
-        assertEquals("U extends 
org.apache.commons.lang3.reflect.MySuperClass<? super U>",
-                TypeUtils.toString(MyClass.class.getTypeParameters()[0]));
-    }
-
-    @Test
-    void testMultiBoundRecursiveType() {
-        assertEquals("org.apache.commons.lang3.reflect.MultiBoundClass<U 
extends java.lang.Number & java.lang.Comparable<? super U>>",
-                TypeUtils.toString(MultiBoundClass.class));
-        assertEquals("U extends java.lang.Number & java.lang.Comparable<? 
super U>",
-                
TypeUtils.toString(MultiBoundClass.class.getTypeParameters()[0]));
-    }
-
-    @Test
-    void testInterfaceBoundPreserved() {
-        assertEquals("T extends java.util.List<java.lang.String>",
-                
TypeUtils.toString(InterfaceBound.class.getTypeParameters()[0]));
-    }
-
-    @Test
-    void testMultiParamRecursiveType() {
-        final ParameterizedType parameterizedType = 
TypeUtils.parameterize(TwoParams.class, TwoParams.class.getTypeParameters());
-        assertEquals("org.apache.commons.lang3.reflect.TwoParams<T, U>",
-                TypeUtils.toString(parameterizedType));
-    }
-
-    @Test
-    void testGClassToString() {
-        assertEquals("org.apache.commons.lang3.reflect.AClass.GClass<T extends 
org.apache.commons.lang3.reflect.AClass.BClass<? extends T> "
-                + "& 
org.apache.commons.lang3.reflect.AClass.AInterface<org.apache.commons.lang3.reflect.AClass.AInterface<?
 super T>>>",
-                TypeUtils.toString(AClass.GClass.class));
-    }
-
-    @Test
-    void testContainsTypeVariablesMultiBoundWildcard() {
-        final TypeVariable<?> t = getClass().getTypeParameters()[0];
-        final WildcardType wtUpper = 
TypeUtils.wildcardType().withUpperBounds(Integer.class, t).build();
-        assertTrue(TypeUtils.containsTypeVariables(wtUpper));
-        final WildcardType wtLower = 
TypeUtils.wildcardType().withLowerBounds(Integer.class, t).build();
-        assertTrue(TypeUtils.containsTypeVariables(wtLower));
-        final WildcardType wtNone = 
TypeUtils.wildcardType().withUpperBounds(Integer.class, String.class).build();
-        assertFalse(TypeUtils.containsTypeVariables(wtNone));
-    }
-
     @Test
     void testWildcardTypeBuilderDefensiveCopy() {
         // Upper bounds defensive copying on input array and getter
@@ -1401,231 +1622,10 @@ void testWildcardTypeBuilderDefensiveCopy() {
     }
 
     @Test
-    void testBoundedGenericArrayTypeToString() {
-        final TypeVariable<?> t = DependentBounds.class.getTypeParameters()[0];
-        final GenericArrayType gat = TypeUtils.genericArrayType(t);
-        assertEquals("T[]", TypeUtils.toString(gat));
-    }
-
-    @Test
-    void testBoundedParameterizedTypeArgumentToString() {
-        final TypeVariable<?> t = DependentBounds.class.getTypeParameters()[0];
-        final ParameterizedType pt = TypeUtils.parameterize(List.class, t);
-        assertEquals("java.util.List<T>", TypeUtils.toString(pt));
-    }
-
-    @Test
-    void testDependentBoundsClassAndTypeParametersToString() {
-        assertEquals("org.apache.commons.lang3.reflect.DependentBounds<T 
extends java.lang.Number, S extends T>",
-                TypeUtils.toString(DependentBounds.class));
-        assertEquals("T extends java.lang.Number",
-                
TypeUtils.toString(DependentBounds.class.getTypeParameters()[0]));
-        assertEquals("S extends T",
-                
TypeUtils.toString(DependentBounds.class.getTypeParameters()[1]));
-    }
-
-    @Test
-    void testToLongStringBoundedTypeVariable() {
-        assertEquals("org.apache.commons.lang3.reflect.DependentBounds:T 
extends java.lang.Number",
-                
TypeUtils.toLongString(DependentBounds.class.getTypeParameters()[0]));
-        assertEquals("org.apache.commons.lang3.reflect.DependentBounds:S 
extends T",
-                
TypeUtils.toLongString(DependentBounds.class.getTypeParameters()[1]));
-        assertEquals("org.apache.commons.lang3.reflect.MultiBoundClass:U 
extends java.lang.Number & java.lang.Comparable<? super U>",
-                
TypeUtils.toLongString(MultiBoundClass.class.getTypeParameters()[0]));
-        assertEquals("org.apache.commons.lang3.reflect.InterfaceBound:T 
extends java.util.List<java.lang.String>",
-                
TypeUtils.toLongString(InterfaceBound.class.getTypeParameters()[0]));
-        assertEquals("org.apache.commons.lang3.reflect.MyClass:U extends 
org.apache.commons.lang3.reflect.MySuperClass<? super U>",
-                TypeUtils.toLongString(MyClass.class.getTypeParameters()[0]));
-    }
-
-    @Test
-    void testParameterizedOwnerWithNonGenericInnerClassToString() throws 
NoSuchMethodException {
-        final ParameterizedType owner = 
TypeUtils.parameterize(ParameterizedOwner.class, String.class);
-        final ParameterizedType nonGenericInner = 
TypeUtils.parameterizeWithOwner(owner, 
ParameterizedOwner.NonGenericInner.class);
-        
assertEquals("org.apache.commons.lang3.reflect.ParameterizedOwner<java.lang.String>.NonGenericInner",
-                TypeUtils.toString(nonGenericInner));
-
-        final Type methodReturnType = 
ParameterizedOwner.class.getMethod("getInner").getGenericReturnType();
-        
assertEquals("org.apache.commons.lang3.reflect.ParameterizedOwner<T>.NonGenericInner",
-                TypeUtils.toString(methodReturnType));
-    }
-
-    @Test
-    void testCyclicOwnerParameterizedTypeToString() {
-        final ParameterizedType[] holder = new ParameterizedType[1];
-        final ParameterizedType cyclicOwnerType = new ParameterizedType() {
-            @Override
-            public Type[] getActualTypeArguments() {
-                return ArrayUtils.EMPTY_TYPE_ARRAY;
-            }
-
-            @Override
-            public Type getRawType() {
-                return List.class;
-            }
-
-            @Override
-            public Type getOwnerType() {
-                return holder[0];
-            }
-        };
-        holder[0] = cyclicOwnerType;
-        assertEquals("List(cycle).List", TypeUtils.toString(cyclicOwnerType));
-
-        final ParameterizedType[] holderA = new ParameterizedType[1];
-        final ParameterizedType[] holderB = new ParameterizedType[1];
-        final ParameterizedType typeA = new ParameterizedType() {
-            @Override
-            public Type[] getActualTypeArguments() {
-                return ArrayUtils.EMPTY_TYPE_ARRAY;
-            }
-
-            @Override
-            public Type getRawType() {
-                return Map.class;
-            }
-
-            @Override
-            public Type getOwnerType() {
-                return holderB[0];
-            }
-        };
-        final ParameterizedType typeB = new ParameterizedType() {
-            @Override
-            public Type[] getActualTypeArguments() {
-                return ArrayUtils.EMPTY_TYPE_ARRAY;
-            }
-
-            @Override
-            public Type getRawType() {
-                return Set.class;
-            }
-
-            @Override
-            public Type getOwnerType() {
-                return holderA[0];
-            }
-        };
-        holderA[0] = typeA;
-        holderB[0] = typeB;
-        assertEquals("Map(cycle).Set.Map", TypeUtils.toString(typeA));
-    }
-
-    @Test
-    void testRepeatedSiblingReferencesToString() {
-        final ParameterizedType listString = 
TypeUtils.parameterize(List.class, String.class);
-        final ParameterizedType mapType = TypeUtils.parameterize(Map.class, 
listString, listString);
-        assertEquals("java.util.Map<java.util.List<java.lang.String>, 
java.util.List<java.lang.String>>",
-                TypeUtils.toString(mapType));
-
-        final TypeVariable<?> t = DependentBounds.class.getTypeParameters()[0];
-        final ParameterizedType biFunctionType = 
TypeUtils.parameterize(BiFunction.class, t, t, t);
-        assertEquals("java.util.function.BiFunction<T, T, T>", 
TypeUtils.toString(biFunctionType));
-
-        final WildcardType wildcard = 
TypeUtils.wildcardType().withUpperBounds(listString).build();
-        final ParameterizedType mapWildcards = 
TypeUtils.parameterize(Map.class, wildcard, wildcard);
-        assertEquals("java.util.Map<? extends 
java.util.List<java.lang.String>, ? extends java.util.List<java.lang.String>>",
-                TypeUtils.toString(mapWildcards));
-    }
-
-    @Test
-    void testThreadLocalCleanupAfterException() {
-        final Type unsupportedType = new Type() {
-            @Override
-            public String getTypeName() {
-                return "Unsupported";
-            }
-        };
-        assertThrows(IllegalArgumentException.class, () -> 
TypeUtils.toString(unsupportedType));
-        assertEquals("java.lang.String", TypeUtils.toString(String.class));
-
-        final Type faultyType = new ParameterizedType() {
-            @Override
-            public Type[] getActualTypeArguments() {
-                throw new IllegalStateException("Simulated failure in 
getActualTypeArguments");
-            }
-
-            @Override
-            public Type getRawType() {
-                return List.class;
-            }
-
-            @Override
-            public Type getOwnerType() {
-                return null;
-            }
-        };
-        assertThrows(IllegalStateException.class, () -> 
TypeUtils.toString(faultyType));
-        assertEquals("java.lang.String", TypeUtils.toString(String.class));
-
-        final ParameterizedType wrapper = new ParameterizedType() {
-            @Override
-            public Type[] getActualTypeArguments() {
-                return new Type[] { faultyType };
-            }
-
-            @Override
-            public Type getRawType() {
-                return Set.class;
-            }
-
-            @Override
-            public Type getOwnerType() {
-                return null;
-            }
-        };
-        assertThrows(IllegalStateException.class, () -> 
TypeUtils.toString(wrapper));
-        assertEquals("java.util.List<java.lang.String>",
-                TypeUtils.toString(TypeUtils.parameterize(List.class, 
String.class)));
-    }
-
-    @Test
-    void testCyclicWildcardTypeToString() {
-        final WildcardType[] holder = new WildcardType[1];
-        final WildcardType cyclicWildcard = new WildcardType() {
-            @Override
-            public Type[] getUpperBounds() {
-                return new Type[] { holder[0] };
-            }
-
-            @Override
-            public Type[] getLowerBounds() {
-                return ArrayUtils.EMPTY_TYPE_ARRAY;
-            }
-        };
-        holder[0] = cyclicWildcard;
-        assertEquals("? extends ? (cycle)", 
TypeUtils.toString(cyclicWildcard));
-    }
-
-    @Test
-    void testCyclicParameterizedTypeToString() {
-        final ParameterizedType[] holder = new ParameterizedType[1];
-        final ParameterizedType cyclicType = new ParameterizedType() {
-            @Override
-            public Type[] getActualTypeArguments() {
-                return new Type[] { holder[0] };
-            }
-
-            @Override
-            public Type getRawType() {
-                return List.class;
-            }
-
-            @Override
-            public Type getOwnerType() {
-                return null;
-            }
-        };
-        holder[0] = cyclicType;
-        assertEquals("java.util.List<List(cycle)>", 
TypeUtils.toString(cyclicType));
-    }
-
-    @Test
-    void testCyclicGenericArrayTypeToString() {
-        final GenericArrayType[] holder = new GenericArrayType[1];
-        final GenericArrayType cyclicType = () -> holder[0];
-        holder[0] = cyclicType;
-        assertEquals("(cycle)[]", TypeUtils.toString(cyclicType));
+    void testWrap() {
+        final Type t = getClass().getTypeParameters()[0];
+        assertTrue(TypeUtils.equals(t, TypeUtils.wrap(t).getType()));
+        assertEquals(String.class, TypeUtils.wrap(String.class).getType());
     }
 
 }

Reply via email to