/***************************************************************************
* Copyright 2009-2012 by Christian Ihle *
* kontakt@usikkert.net *
* *
* This file is part of KouInject. *
* *
* KouInject is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version. *
* *
* KouInject is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with KouInject. *
* If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
package net.usikkert.kouinject.generics;
import static org.junit.Assert.*;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Provider;
import net.usikkert.kouinject.testbeans.notscanned.generics.typevariable.TypeVariableChild;
import net.usikkert.kouinject.testbeans.notscanned.generics.typevariable.TypeVariableParent;
import net.usikkert.kouinject.testbeans.notscanned.generics.typevariable.TypeVariableWithNestedWildcard;
import net.usikkert.kouinject.testbeans.notscanned.generics.typevariable.TypeVariableWithNestedWildcardImpl;
import net.usikkert.kouinject.testbeans.scanned.HelloBean;
import net.usikkert.kouinject.testbeans.scanned.generics.Container;
import net.usikkert.kouinject.testbeans.scanned.generics.circular.Square;
import net.usikkert.kouinject.testbeans.scanned.generics.qualifier.factory.Comedy;
import net.usikkert.kouinject.testbeans.scanned.generics.qualifier.factory.Horror;
import net.usikkert.kouinject.testbeans.scanned.generics.qualifier.factory.Movie;
import net.usikkert.kouinject.testbeans.scanned.generics.thing.FirstStartThingListenerBean;
import net.usikkert.kouinject.testbeans.scanned.generics.thing.MiddleThing;
import net.usikkert.kouinject.testbeans.scanned.generics.thing.MiddleThingListenerBean;
import net.usikkert.kouinject.testbeans.scanned.generics.thing.StartThing;
import net.usikkert.kouinject.testbeans.scanned.generics.thing.StopThing;
import net.usikkert.kouinject.testbeans.scanned.generics.thing.StopThingListenerBean;
import net.usikkert.kouinject.testbeans.scanned.generics.thing.ThingListenerBean;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.AbstractDualVariableBean;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.Box;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.ConcreteDualVariableBean;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.DualVariableInterfaceBean;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.Fanta;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.Liquid;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.Pepsi;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.Pizza;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.Shoe;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.ShoeBoxBean;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.VariableOne;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.VariableOnePointTwo;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.VariableTwo;
import net.usikkert.kouinject.testbeans.scanned.generics.typevariable.VariableTwoPointTwo;
import net.usikkert.kouinject.testbeans.scanned.hierarchy.ChildBean;
import net.usikkert.kouinject.testbeans.scanned.hierarchy.MiddleBean;
import net.usikkert.kouinject.testbeans.scanned.hierarchy.SuperBean;
import org.junit.Test;
/**
* Test of {@link GenericsHelper}.
*
* @author Christian Ihle
*/
public class GenericsHelperTest {
@Test
public void getGenericArgumentAsTypeShouldGetFirstArgument() {
final TypeLiteral<Set<List<String>>> inputType = new TypeLiteral<Set<List<String>>>() {};
final TypeLiteral<List<String>> expectedType = new TypeLiteral<List<String>>() {};
final Type argumentAsType = GenericsHelper.getGenericArgumentAsType(inputType.getGenericType());
assertEquals(expectedType.getGenericType(), argumentAsType);
}
@Test(expected = IllegalArgumentException.class)
public void getGenericArgumentAsTypeShouldFailIfWrongNumberOfArguments() {
final TypeLiteral<Map<String, Integer>> inputType = new TypeLiteral<Map<String, Integer>>() {};
GenericsHelper.getGenericArgumentAsType(inputType.getGenericType());
}
@Test(expected = IllegalArgumentException.class)
public void getGenericArgumentAsTypeShouldFailIfWrongType() {
final TypeLiteral<String[]> inputType = new TypeLiteral<String[]>() {};
GenericsHelper.getGenericArgumentAsType(inputType.getGenericType());
}
@Test(expected = IllegalArgumentException.class)
public void getGenericArgumentAsTypeShouldFailIfClass() {
GenericsHelper.getGenericArgumentAsType(String.class);
}
@Test
public void getGenericArgumentAsClassShouldReturnRawType() {
final TypeLiteral<Set<List<String>>> inputType = new TypeLiteral<Set<List<String>>>() {};
final Class<?> argumentAsClass = GenericsHelper.getGenericArgumentAsClass(inputType.getGenericType());
assertEquals(List.class, argumentAsClass);
}
@Test
public void getGenericArgumentAsClassShouldReturnClass() {
final TypeLiteral<List<String>> inputType = new TypeLiteral<List<String>>() {};
final Class<?> argumentAsClass = GenericsHelper.getGenericArgumentAsClass(inputType.getGenericType());
assertEquals(String.class, argumentAsClass);
}
@Test
public void getAsClassShouldReturnRawType() {
final TypeLiteral<List<String>> inputType = new TypeLiteral<List<String>>() {};
final Class<?> asClass = GenericsHelper.getAsClass(inputType.getGenericType());
assertEquals(List.class, asClass);
}
@Test
public void getAsClassShouldReturnClass() {
final TypeLiteral<String> stringType = new TypeLiteral<String>() {};
final Class<?> asStringClass = GenericsHelper.getAsClass(stringType.getGenericType());
assertEquals(String.class, asStringClass);
final Class<?> asHelloBeanClass = GenericsHelper.getAsClass(HelloBean.class);
assertEquals(HelloBean.class, asHelloBeanClass);
}
@Test(expected = IllegalArgumentException.class)
public void getAsClassShouldFailIfArrayIsGeneric() {
// Creating generic arrays are forbidden by the jvm, so wont bother adding support for getting the class
// final Container<String>[] anArrayContainer = new Container<String>[0]; // does not compile
final TypeLiteral<Container<String>[]> arrayContainer = new TypeLiteral<Container<String>[]>() {};
final Type arrayType = GenericsHelper.getGenericArgumentAsType(arrayContainer.getGenericType());
GenericsHelper.getAsClass(arrayType);
}
@Test
public void getAsClassShouldGetCorrectOneDimensionalArrayClass() {
final TypeLiteral<Provider<String[]>> providerWithArray = new TypeLiteral<Provider<String[]>>() {};
final Type array = GenericsHelper.getGenericArgumentAsType(providerWithArray.getGenericType());
final Class<?> asClass = GenericsHelper.getAsClass(array);
assertEquals(String[].class, asClass);
}
@Test
public void getAsClassShouldGetCorrectTwoDimensionalArrayClass() {
final TypeLiteral<Provider<String[][]>> providerWithArray = new TypeLiteral<Provider<String[][]>>() {};
final Type array = GenericsHelper.getGenericArgumentAsType(providerWithArray.getGenericType());
final Class<?> asClass = GenericsHelper.getAsClass(array);
assertEquals(String[][].class, asClass);
}
@Test
public void getAsClassShouldGetCorrectThreeDimensionalArrayClass() {
final TypeLiteral<Provider<String[][][]>> providerWithArray = new TypeLiteral<Provider<String[][][]>>() {};
final Type array = GenericsHelper.getGenericArgumentAsType(providerWithArray.getGenericType());
final Class<?> asClass = GenericsHelper.getAsClass(array);
assertEquals(String[][][].class, asClass);
}
@Test(expected = IllegalArgumentException.class)
public void getAsClassShouldFailIfWildcard() {
final TypeLiteral<Container<?>> wildcardContainer = new TypeLiteral<Container<?>>() {};
final Type wildcardType = GenericsHelper.getGenericArgumentAsType(wildcardContainer.getGenericType());
GenericsHelper.getAsClass(wildcardType);
}
@Test
public void getAsClassOrNullShouldReturnClass() {
final TypeLiteral<String> stringType = new TypeLiteral<String>() {};
final Class<?> asStringClass = GenericsHelper.getAsClassOrNull(stringType.getGenericType());
assertEquals(String.class, asStringClass);
final Class<?> asHelloBeanClass = GenericsHelper.getAsClassOrNull(HelloBean.class);
assertEquals(HelloBean.class, asHelloBeanClass);
}
@Test
public void getAsClassOrNullShouldReturnNullForWildcards() {
final TypeLiteral<Container<?>> wildcardContainer = new TypeLiteral<Container<?>>() {};
final Type wildcardType = GenericsHelper.getGenericArgumentAsType(wildcardContainer.getGenericType());
final Class<?> classOrNull = GenericsHelper.getAsClassOrNull(wildcardType);
assertNull(classOrNull);
}
@Test
public void getClassFromGenericArrayShouldHandleOneDimension() {
final Type genericType = new TypeLiteral<String[]>() {}.getGenericType();
assertTrue(GenericsHelper.isGenericArrayType(genericType));
assertEquals(String[].class, GenericsHelper.getArrayClassFromGenericArray((GenericArrayType) genericType));
}
@Test
public void getClassFromGenericArrayShouldHandleTwoDimensions() {
final Type genericType = new TypeLiteral<String[][]>() {}.getGenericType();
assertTrue(GenericsHelper.isGenericArrayType(genericType));
assertEquals(String[][].class, GenericsHelper.getArrayClassFromGenericArray((GenericArrayType) genericType));
}
@Test
public void getClassFromGenericArrayShouldHandleThreeDimensions() {
final Type genericType = new TypeLiteral<String[][][]>() {}.getGenericType();
assertTrue(GenericsHelper.isGenericArrayType(genericType));
assertEquals(String[][][].class, GenericsHelper.getArrayClassFromGenericArray((GenericArrayType) genericType));
}
@Test
public void isClass() {
assertTrue(GenericsHelper.isClass(HelloBean.class));
final TypeLiteral<String> stringType = new TypeLiteral<String>() {};
assertTrue(GenericsHelper.isClass(stringType.getGenericType()));
assertTrue(GenericsHelper.isClass(stringType.getGenericClass()));
final TypeLiteral<List<String>> listOfStringType = new TypeLiteral<List<String>>() {};
assertFalse(GenericsHelper.isClass(listOfStringType.getGenericType()));
assertTrue(GenericsHelper.isClass(listOfStringType.getGenericClass()));
}
@Test
public void isParameterizedType() {
assertFalse(GenericsHelper.isParameterizedType(HelloBean.class));
final TypeLiteral<String> stringType = new TypeLiteral<String>() {};
assertFalse(GenericsHelper.isParameterizedType(stringType.getGenericType()));
assertFalse(GenericsHelper.isParameterizedType(stringType.getGenericClass()));
final TypeLiteral<List<String>> listOfStringType = new TypeLiteral<List<String>>() {};
assertTrue(GenericsHelper.isParameterizedType(listOfStringType.getGenericType()));
assertFalse(GenericsHelper.isParameterizedType(listOfStringType.getGenericClass()));
}
@Test
public void isWildcard() {
assertFalse(GenericsHelper.isWildcard(HelloBean.class));
final TypeLiteral<Container<?>> wildcardContainer = new TypeLiteral<Container<?>>() {};
assertFalse(GenericsHelper.isWildcard(wildcardContainer.getGenericType()));
assertFalse(GenericsHelper.isWildcard(wildcardContainer.getGenericClass()));
final Type wildcardType = GenericsHelper.getGenericArgumentAsType(wildcardContainer.getGenericType());
assertTrue(GenericsHelper.isWildcard(wildcardType));
}
@Test
public void isGenericArrayType() {
assertFalse(GenericsHelper.isGenericArrayType(HelloBean.class));
final TypeLiteral<Container<String[]>> arrayContainer = new TypeLiteral<Container<String[]>>() {};
assertFalse(GenericsHelper.isGenericArrayType(arrayContainer.getGenericType()));
assertFalse(GenericsHelper.isGenericArrayType(arrayContainer.getGenericClass()));
final Type arrayType = GenericsHelper.getGenericArgumentAsType(arrayContainer.getGenericType());
assertTrue(GenericsHelper.isGenericArrayType(arrayType));
}
@Test
public void isAssignableFromShouldBeTrueForTheSameClass() {
// final String thatString = null;
// final String thisString = thatString; // ok
assertTrue(GenericsHelper.isAssignableFrom(String.class, String.class));
assertTrue(String.class.isAssignableFrom(String.class));
}
@Test
public void isAssignableFromShouldBeTrueForTheSameGenericClassWithoutTypeArguments() {
// final List thatBean = null;
// final List thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(List.class, List.class));
assertTrue(List.class.isAssignableFrom(List.class));
}
@Test
public void isAssignableFromShouldBeTrueForSubTypeClass() {
// final String thatString = null;
// final Object thisObject = thatString; // ok
assertTrue(GenericsHelper.isAssignableFrom(Object.class, String.class));
assertTrue(Object.class.isAssignableFrom(String.class));
// final Object thatObject = null;
// final String thisString = thatObject; // compile error
assertFalse(GenericsHelper.isAssignableFrom(String.class, Object.class));
assertFalse(String.class.isAssignableFrom(Object.class));
}
@Test
public void isAssignableFromShouldBeTrueForSubTypeGenericClassWhenUsedRaw() {
// final List thatList = null;
// final Object thisObject = thatList; // ok
assertTrue(GenericsHelper.isAssignableFrom(Object.class, List.class));
assertTrue(Object.class.isAssignableFrom(List.class));
// final Object thatObject = null;
// final List thisList = thatObject; // compile error
assertFalse(GenericsHelper.isAssignableFrom(List.class, Object.class));
assertFalse(List.class.isAssignableFrom(Object.class));
}
@Test
public void isAssignableFromShouldBeTrueForSubTypeGenericClassesWhenBothUsedRaw() {
// final ArrayList thatList = null;
// final List thisList = thatList; // ok
assertTrue(GenericsHelper.isAssignableFrom(List.class, ArrayList.class));
assertTrue(List.class.isAssignableFrom(ArrayList.class));
// final List thatList = null;
// final ArrayList thisList = thatList; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(ArrayList.class, List.class));
assertFalse(ArrayList.class.isAssignableFrom(List.class));
}
@Test
public void isAssignableFromShouldBeTrueForTheSameType() {
final Type thisType = new TypeLiteral<List<String>>() {}.getGenericType();
final Type thatType = new TypeLiteral<List<String>>() {}.getGenericType();
// final List<String> thatList = null;
// final List<String> thisList = thatList; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
assertTrue(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueForSubType() {
final Type thisType = new TypeLiteral<List<String>>() {}.getGenericType();
final Type thatType = new TypeLiteral<ArrayList<String>>() {}.getGenericType();
// final ArrayList<String> thatList = null;
// final List<String> thisList = thatList; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
// final List<String> thatList = null;
// final ArrayList<String> thisList = thatList; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseForTheDifferentSubType() {
final Type thisType = new TypeLiteral<List<Integer>>() {}.getGenericType();
final Type thatType = new TypeLiteral<List<String>>() {}.getGenericType();
// final List<String> thatList = null;
// final List<Integer> thisList = thatList; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final List<Integer> thatList = null;
// final List<String> thisList = thatList; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseForSubTypeWithInheritance() {
final Type thisType = new TypeLiteral<List<Object>>() {}.getGenericType();
final Type thatType = new TypeLiteral<List<String>>() {}.getGenericType();
// final List<String> thatList = null;
// final List<Object> thisList = thatList; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final List<Object> thatList = null;
// final List<String> thisList = thatList; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseForTheDifferentTypeAndSameSubType() {
final Type thisType = new TypeLiteral<List<String>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<String>>() {}.getGenericType();
// final Set<String> thatSet = null;
// final List<String> thisList = thatSet; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final List<String> thatList = null;
// final Set<String> thisSet = thatList; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueForAssigningSameGenericTypeToRawType() {
final Type type = new TypeLiteral<List<String>>() {}.getGenericType();
// final List<String> thatList = null;
// final List thisList = thatList; // ok
assertTrue(GenericsHelper.isAssignableFrom(List.class, type));
}
@Test
public void isAssignableFromShouldBeTrueForAssigningGenericTypeToRawSubType() {
final Type type = new TypeLiteral<ArrayList<String>>() {}.getGenericType();
// final ArrayList<String> thatList = null;
// final List thisList = thatList; // ok
assertTrue(GenericsHelper.isAssignableFrom(List.class, type));
// final List thatList = null;
// final ArrayList<String> thisList = thatList; // compile error
assertFalse(GenericsHelper.isAssignableFrom(type, List.class));
}
@Test
public void isAssignableFromShouldBeFalseForUncheckedCastFromRawTypeToSameGenericType() {
final Type type = new TypeLiteral<List<String>>() {}.getGenericType();
// final List thatList = null;
// final List<String> thisList = thatList; // ok, but unchecked assignment
// Valid, but not type safe. Not allowed.
assertFalse(GenericsHelper.isAssignableFrom(type, List.class));
}
@Test
public void isAssignableFromShouldBeFalseForCastFromRawTypeToUnboundedGenericType() {
final Type thisType = new TypeLiteral<List<?>>() {}.getGenericType();
// final List thatBean = null;
// final List<?> thisBean = thatBean; // ok
// Type safe and valid, but not allowed because of the limitations added for the above test
assertFalse(GenericsHelper.isAssignableFrom(thisType, List.class));
// final List<?> thatBean = null;
// final List thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(List.class, thisType));
}
@Test
public void isAssignableFromShouldBeFalseForUncheckedCastFromRawTypeToGenericSubType() {
final Type type = new TypeLiteral<List<String>>() {}.getGenericType();
// final ArrayList thatList = null;
// final List<String> thisList = thatList; // ok, but unchecked assignment
assertFalse(GenericsHelper.isAssignableFrom(type, ArrayList.class));
// final List<String> thatList = null;
// final ArrayList thisList = thatList; // compile error
assertFalse(GenericsHelper.isAssignableFrom(ArrayList.class, type));
}
@Test
public void isAssignableFromShouldBeTrueForWildcardWithExtendsAndCorrectInheritance() {
final Type thisType = new TypeLiteral<Set<? extends SuperBean>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<MiddleBean>>() {}.getGenericType();
// final Set<MiddleBean> thatSet = null;
// final Set<? extends SuperBean> thisSet = thatSet; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Set<? extends SuperBean> thatSet = null;
// final Set<MiddleBean> thisSet = thatSet; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueForDirectWildcardWithExtendsAndCorrectInheritance() {
final Type thisType = new TypeLiteral<Set<? extends SuperBean>>() {}.getGenericType();
final Type thisWildcard = GenericsHelper.getGenericArgumentAsType(thisType);
final Type thatType = new TypeLiteral<MiddleBean>() {}.getGenericType();
assertTrue(GenericsHelper.isAssignableFrom(thisWildcard, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisWildcard));
}
@Test
public void isAssignableFromShouldBeFalseForWildcardWithExtendsAndInvertedInheritance() {
final Type thisType = new TypeLiteral<Set<? extends ChildBean>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<MiddleBean>>() {}.getGenericType();
// final Set<MiddleBean> thatSet = null;
// final Set<? extends ChildBean> thisSet = thatSet; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Set<? extends ChildBean> thatSet = null;
// final Set<MiddleBean> thisSet = thatSet; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueForWildcardWithSuperAndCorrectInheritance() {
final Type thisType = new TypeLiteral<Set<? super ChildBean>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<MiddleBean>>() {}.getGenericType();
// final Set<MiddleBean> thatSet = null;
// final Set<? super ChildBean> thisSet = thatSet; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Set<? super ChildBean> thatSet = null;
// final Set<MiddleBean> thisSet = thatSet; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueForDirectWildcardWithSuperAndCorrectInheritance() {
final Type thisType = new TypeLiteral<Set<? super ChildBean>>() {}.getGenericType();
final Type thisWildcard = GenericsHelper.getGenericArgumentAsType(thisType);
final Type thatType = new TypeLiteral<MiddleBean>() {}.getGenericType();
assertTrue(GenericsHelper.isAssignableFrom(thisWildcard, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisWildcard));
}
@Test
public void isAssignableFromShouldBeFalseForWildcardWithSuperAndInvertedInheritance() {
final Type thisType = new TypeLiteral<Set<? super SuperBean>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<MiddleBean>>() {}.getGenericType();
// final Set<MiddleBean> thatSet = null;
// final Set<? super SuperBean> thisSet = thatSet; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Set<? super SuperBean> thatSet = null;
// final Set<MiddleBean> thisSet = thatSet; // compile error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningWildcardWithSuperToTheSameWildcard() {
final Type thisType = new TypeLiteral<Set<? super SuperBean>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<? super SuperBean>>() {}.getGenericType();
// final Set<? super SuperBean> thatBean = null;
// final Set<? super SuperBean> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningWildcardWithExtendsToTheSameWildcard() {
final Type thisType = new TypeLiteral<Set<? extends SuperBean>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<? extends SuperBean>>() {}.getGenericType();
// final Set<? extends SuperBean> thatBean = null;
// final Set<? extends SuperBean> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningUnboundWildcardToTheSameWildcard() {
final Type thisType = new TypeLiteral<Set<?>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<?>>() {}.getGenericType();
// final Set<?> thatBean = null;
// final Set<?> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
}
@Test
public void isAssignableFromShouldBeFalseWhenAssigningWildcardWithSuperToWildcardWithExtends() {
final Type thisType1 = new TypeLiteral<Set<? super SuperBean>>() {}.getGenericType();
final Type thisType2 = new TypeLiteral<Set<? super MiddleBean>>() {}.getGenericType();
final Type thisType3 = new TypeLiteral<Set<? super ChildBean>>() {}.getGenericType();
final Type thatType1 = new TypeLiteral<Set<? extends SuperBean>>() {}.getGenericType();
final Type thatType2 = new TypeLiteral<Set<? extends MiddleBean>>() {}.getGenericType();
final Type thatType3 = new TypeLiteral<Set<? extends ChildBean>>() {}.getGenericType();
// compiler error on all of them
assertFalse(GenericsHelper.isAssignableFrom(thisType1, thatType1));
assertFalse(GenericsHelper.isAssignableFrom(thisType1, thatType2));
assertFalse(GenericsHelper.isAssignableFrom(thisType1, thatType3));
assertFalse(GenericsHelper.isAssignableFrom(thisType2, thatType1));
assertFalse(GenericsHelper.isAssignableFrom(thisType2, thatType2));
assertFalse(GenericsHelper.isAssignableFrom(thisType2, thatType3));
assertFalse(GenericsHelper.isAssignableFrom(thisType3, thatType1));
assertFalse(GenericsHelper.isAssignableFrom(thisType3, thatType2));
assertFalse(GenericsHelper.isAssignableFrom(thisType3, thatType3));
assertFalse(GenericsHelper.isAssignableFrom(thatType1, thisType1));
assertFalse(GenericsHelper.isAssignableFrom(thatType1, thisType2));
assertFalse(GenericsHelper.isAssignableFrom(thatType1, thisType3));
assertFalse(GenericsHelper.isAssignableFrom(thatType2, thisType1));
assertFalse(GenericsHelper.isAssignableFrom(thatType2, thisType2));
assertFalse(GenericsHelper.isAssignableFrom(thatType2, thisType3));
assertFalse(GenericsHelper.isAssignableFrom(thatType3, thisType1));
assertFalse(GenericsHelper.isAssignableFrom(thatType3, thisType2));
assertFalse(GenericsHelper.isAssignableFrom(thatType3, thisType3));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningWildcardWithExtendsWithCorrectInheritance() {
final Type thisType = new TypeLiteral<Set<? extends MiddleBean>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<? extends SuperBean>>() {}.getGenericType();
// final Set<? extends SuperBean> thatBean = null;
// final Set<? extends MiddleBean> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Set<? extends MiddleBean> thatBean = null;
// final Set<? extends SuperBean> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningWildcardWithSuperWithCorrectInheritance() {
final Type thisType = new TypeLiteral<Set<? super MiddleBean>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Set<? super ChildBean>>() {}.getGenericType();
// final Set<? super ChildBean> thatBean = null;
// final Set<? super MiddleBean> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Set<? super MiddleBean> thatBean = null;
// final Set<? super ChildBean> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenAssigningWildcardWithSuperToGenericParameter() {
final Type thatType = new TypeLiteral<Set<? super MiddleBean>>() {}.getGenericType();
final Type thisType1 = new TypeLiteral<Set<ChildBean>>() {}.getGenericType();
final Type thisType2 = new TypeLiteral<Set<MiddleBean>>() {}.getGenericType();
final Type thisType3 = new TypeLiteral<Set<SuperBean>>() {}.getGenericType();
// final Set<? super MiddleBean> thatBean = null;
// final Set<ChildBean> thisBean1 = thatBean; // compiler error
// final Set<MiddleBean> thisBean2 = thatBean; // compiler error
// final Set<SuperBean> thisBean3 = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType1, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thisType2, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thisType3, thatType));
// final Set<ChildBean> thisBean1 = null;
// final Set<MiddleBean> thisBean2 = null;
// final Set<SuperBean> thisBean3 = null;
// final Set<? super MiddleBean> thatBean = thisBean1; // compiler error
// final Set<? super MiddleBean> thatBean = thisBean2; // ok
// final Set<? super MiddleBean> thatBean = thisBean3; // ok
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType1));
assertTrue(GenericsHelper.isAssignableFrom(thatType, thisType2));
assertTrue(GenericsHelper.isAssignableFrom(thatType, thisType3));
}
@Test
public void isAssignableFromShouldBeFalseWhenAssigningWildcardWithExtendsToGenericParameter() {
final Type thatType = new TypeLiteral<Set<? extends MiddleBean>>() {}.getGenericType();
final Type thisType1 = new TypeLiteral<Set<ChildBean>>() {}.getGenericType();
final Type thisType2 = new TypeLiteral<Set<MiddleBean>>() {}.getGenericType();
final Type thisType3 = new TypeLiteral<Set<SuperBean>>() {}.getGenericType();
// final Set<? extends MiddleBean> thatBean = null;
// final Set<ChildBean> thisBean1 = thatBean; // compiler error
// final Set<MiddleBean> thisBean2 = thatBean; // compiler error
// final Set<SuperBean> thisBean3 = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType1, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thisType2, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thisType3, thatType));
// final Set<ChildBean> thisBean1 = null;
// final Set<MiddleBean> thisBean2 = null;
// final Set<SuperBean> thisBean3 = null;
// final Set<? extends MiddleBean> thatBean = thisBean1; // ok
// final Set<? extends MiddleBean> thatBean = thisBean2; // ok
// final Set<? extends MiddleBean> thatBean = thisBean3; // compiler error
assertTrue(GenericsHelper.isAssignableFrom(thatType, thisType1));
assertTrue(GenericsHelper.isAssignableFrom(thatType, thisType2));
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType3));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningABoundWildcardToAnUnboundWildcard() {
final Type thatType = new TypeLiteral<Set<? extends MiddleBean>>() {}.getGenericType();
final Type thisType = new TypeLiteral<Set<?>>() {}.getGenericType();
// final Set<? extends MiddleBean> thatBean = null;
// final Set<?> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Set<?> thatBean = null;
// final Set<? extends MiddleBean> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningGenericParameterToAnUnboundWildcard() {
final Type thatType = new TypeLiteral<Set<MiddleBean>>() {}.getGenericType();
final Type thisType = new TypeLiteral<Set<?>>() {}.getGenericType();
// final Set<MiddleBean> thatBean = null;
// final Set<?> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Set<?> thatBean = null;
// final Set<MiddleBean> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenCompatibleWildcardsAreUsedALevelTooDeep() {
final Type thatType = new TypeLiteral<Collection<Container<? extends MiddleBean>>>() {}.getGenericType();
final Type thisType = new TypeLiteral<Collection<Container<?>>>() {}.getGenericType();
// final Collection<Container<? extends MiddleBean>> thatBean = null;
// final Collection<Container<?>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Collection<Container<?>> thatBean = null;
// final Collection<Container<? extends MiddleBean>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningAParameterWithAWildcardToAWildcard() {
final Type thatType = new TypeLiteral<Collection<Container<? extends MiddleBean>>>() {}.getGenericType();
final Type thisType = new TypeLiteral<Collection<?>>() {}.getGenericType();
// final Collection<Container<? extends MiddleBean>> thatBean = null;
// final Collection<?> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Collection<?> thatBean = null;
// final Collection<Container<? extends MiddleBean>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenAllParametersAreEqual() {
final Type thisType = new TypeLiteral<Map<String, Integer>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Map<String, Integer>>() {}.getGenericType();
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
assertTrue(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenOneOfTheParametersAreDifferent1() {
final Type thisType = new TypeLiteral<Map<String, Long>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Map<String, Integer>>() {}.getGenericType();
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenOneOfTheParametersAreDifferent2() {
final Type thisType = new TypeLiteral<Map<Long, String>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Map<Integer, String>>() {}.getGenericType();
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenOneOfTheParametersAreDifferent3() {
final Type thisType = new TypeLiteral<Map<Long, String>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Map<String, Long>>() {}.getGenericType();
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenSeveralLayersOfNestingAreTheSame() {
final Type thisType = new TypeLiteral<Map<Map<String, Integer>, Map<Long, Set<HelloBean>>>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Map<Map<String, Integer>, Map<Long, Set<HelloBean>>>>() {}.getGenericType();
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
assertTrue(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenOneOfSeveralLayersOfNestingAreDifferent() {
final Type thisType = new TypeLiteral<Map<Map<String, Integer>, Map<Long, Set<ChildBean>>>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Map<Map<String, Integer>, Map<Long, Set<MiddleBean>>>>() {}.getGenericType();
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenClassImplementsCorrectGenericInterface() {
final Type thisType = new TypeLiteral<ThingListenerBean<StopThing>>() {}.getGenericType();
// final StopThingListenerBean thatBean = null;
// final ThingListenerBean<StopThing> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, StopThingListenerBean.class));
// final ThingListenerBean<StopThing> thatBean = null;
// final StopThingListenerBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(StopThingListenerBean.class, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenClassExtendsAbstractClassImplementingCorrectGenericInterface() {
final Type thisType = new TypeLiteral<ThingListenerBean<StartThing>>() {}.getGenericType();
// final FirstStartThingListenerBean thatBean = null;
// final ThingListenerBean<StartThing> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, FirstStartThingListenerBean.class));
// final ThingListenerBean<StartThing> thatBean = null;
// final FirstStartThingListenerBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(FirstStartThingListenerBean.class, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenClassExtendsAbstractClassWithCorrectGenericParameter() {
final Type thisType = new TypeLiteral<ThingListenerBean<MiddleThing>>() {}.getGenericType();
// final MiddleThingListenerBean thatBean = null;
// final ThingListenerBean<MiddleThing> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, MiddleThingListenerBean.class));
// final ThingListenerBean<MiddleThing> thatBean = null;
// final MiddleThingListenerBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(MiddleThingListenerBean.class, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenTypeVariablesAreInheritedAndMatch() {
final Type thisType = new TypeLiteral<DualVariableInterfaceBean<VariableOnePointTwo, VariableTwo>>() {}.getGenericType();
// final ConcreteDualVariableBean thatBean = null;
// final DualVariableInterfaceBean<VariableOnePointTwo, VariableTwo> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, ConcreteDualVariableBean.class));
// final DualVariableInterfaceBean<VariableOnePointTwo, VariableTwo> thatBean = null;
// final ConcreteDualVariableBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(ConcreteDualVariableBean.class, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenOneTypeVariableIsDefinedInClassAndOneAtRuntimeAndMatch() {
final Type thisType = new TypeLiteral<DualVariableInterfaceBean<VariableOnePointTwo, VariableTwo>>() {}.getGenericType();
final Type thatType = new TypeLiteral<AbstractDualVariableBean<VariableOnePointTwo>>() {}.getGenericType();
// final AbstractDualVariableBean<VariableOnePointTwo> thatBean = null;
// final DualVariableInterfaceBean<VariableOnePointTwo, VariableTwo> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
// final DualVariableInterfaceBean<VariableOnePointTwo, VariableTwo> thatBean = null;
// final AbstractDualVariableBean<VariableOnePointTwo> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenTypeVariablesAreInheritedAndFirstDontMatch() {
final Type thisType = new TypeLiteral<DualVariableInterfaceBean<VariableOne, VariableTwo>>() {}.getGenericType();
// final ConcreteDualVariableBean thatBean = null;
// final DualVariableInterfaceBean<VariableOne, VariableTwo> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, ConcreteDualVariableBean.class));
// final DualVariableInterfaceBean<VariableOne, VariableTwo> thatBean = null;
// final ConcreteDualVariableBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(ConcreteDualVariableBean.class, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenTypeVariablesAreInheritedAndSecondDontMatch() {
final Type thisType = new TypeLiteral<DualVariableInterfaceBean<VariableOnePointTwo, VariableTwoPointTwo>>() {}.getGenericType();
// final ConcreteDualVariableBean thatBean = null;
// final DualVariableInterfaceBean<VariableOnePointTwo, VariableTwoPointTwo> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, ConcreteDualVariableBean.class));
// final DualVariableInterfaceBean<VariableOnePointTwo, VariableTwoPointTwo> thatBean = null;
// final ConcreteDualVariableBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(ConcreteDualVariableBean.class, thisType));
}
@Test
public void isAssignableShouldBeTrueWhenAssigningFromClassWithTypeVariableToTypeWithUnboundWildcard() {
final Type thisType = new TypeLiteral<AbstractDualVariableBean<?>>() {}.getGenericType();
// final ConcreteDualVariableBean thatBean = null;
// final AbstractDualVariableBean<?> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, ConcreteDualVariableBean.class));
// final AbstractDualVariableBean<?> thatBean = null;
// final ConcreteDualVariableBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(ConcreteDualVariableBean.class, thisType));
}
@Test
public void isAssignableShouldBeTrueWhenAssigningFromClassWithTypeVariableToTypeWithCorrectWildcard() {
final Type thisType = new TypeLiteral<AbstractDualVariableBean<? extends VariableOne>>() {}.getGenericType();
// final ConcreteDualVariableBean thatBean = null;
// final AbstractDualVariableBean<? extends VariableOne> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, ConcreteDualVariableBean.class));
// final AbstractDualVariableBean<? extends VariableOne> thatBean = null;
// final ConcreteDualVariableBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(ConcreteDualVariableBean.class, thisType));
}
@Test
public void isAssignableShouldBeFalseWhenAssigningFromClassWithTypeVariableToTypeWithWrongWildcard() {
final Type thisType = new TypeLiteral<AbstractDualVariableBean<? extends VariableTwo>>() {}.getGenericType();
// final ConcreteDualVariableBean thatBean = null;
// final AbstractDualVariableBean<? extends VariableTwo> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, ConcreteDualVariableBean.class));
// final AbstractDualVariableBean<? extends VariableTwo> thatBean = null;
// final ConcreteDualVariableBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(ConcreteDualVariableBean.class, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningTwoGenericClassesWithoutGenericParameters() {
// final ConcreteDualVariableBean thatBean = null;
// final AbstractDualVariableBean thisBean = thatBean; // ok, but not really type safe. Allowed for now.
assertTrue(GenericsHelper.isAssignableFrom(AbstractDualVariableBean.class, ConcreteDualVariableBean.class));
// final AbstractDualVariableBean thatBean = null;
// final ConcreteDualVariableBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(ConcreteDualVariableBean.class, AbstractDualVariableBean.class));
}
@Test
public void isAssignableFromShouldBeTrueWhenAssigningGenericClassWithoutGenericParametersToObject() {
// final AbstractDualVariableBean thatBean = null;
// final Object thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(Object.class, AbstractDualVariableBean.class));
// final Object thatBean = null;
// final AbstractDualVariableBean thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(AbstractDualVariableBean.class, Object.class));
}
@Test
public void isAssignableShouldBeTrueWhenAssigningFromClassWithTypeVariableToObject() {
final Type thatType = new TypeLiteral<List<String>>() {}.getGenericType();
// final List<String> thatBean = null;
// final Object thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(Object.class, thatType));
// final Object thatBean = null;
// final List<String> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, Object.class));
}
@Test
public void isAssignableShouldBeTrueWhenAssigningFromClassWithWildcardToObject() {
final Type thatType = new TypeLiteral<List<?>>() {}.getGenericType();
// final List<?> thatBean = null;
// final Object thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(Object.class, thatType));
// final Object thatBean = null;
// final List<?> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, Object.class));
}
@Test
public void isAssignableFromShouldBeTrueWhenMatchingWildcardWithResolvedTypeVariableOfCorrectType() {
final Type thisType = new TypeLiteral<Box<? extends Shoe>>() {}.getGenericType();
// final ShoeBoxBean thatBean = null;
// final Box<? extends Shoe> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, ShoeBoxBean.class));
// final Box<? extends Shoe> thatBean = null;
// final ShoeBoxBean thisBean = thatBean; // compile error
assertFalse(GenericsHelper.isAssignableFrom(ShoeBoxBean.class, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenMatchingWildcardWithResolvedTypeVariableOfWrongType() {
final Type thisType = new TypeLiteral<Box<? extends Pizza>>() {}.getGenericType();
// final ShoeBoxBean thatBean = null;
// final Box<? extends Pizza> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, ShoeBoxBean.class));
// final Box<? extends Pizza> thatBean = null;
// final ShoeBoxBean thisBean = thatBean; // compile error
assertFalse(GenericsHelper.isAssignableFrom(ShoeBoxBean.class, thisType));
}
@Test
public void isAssignableFromShouldReturnTrueWhenUsingNestedWildcardsAndTypeMatches() {
final Type thatType = new TypeLiteral<Collection<Movie<Horror>>>() {}.getGenericType();
final Type thisType = new TypeLiteral<Collection<? extends Movie<? extends Horror>>>() {}.getGenericType();
// final Collection<Movie<Horror>> thatBean = null;
// final Collection<? extends Movie<? extends Horror>> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Collection<? extends Movie<? extends Horror>> thatBean = null;
// final Collection<Movie<Horror>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldReturnFalseWhenUsingNestedWildcardsAndNestedTypeDoesNotMatch() {
final Type thatType = new TypeLiteral<Collection<Movie<Comedy>>>() {}.getGenericType();
final Type thisType = new TypeLiteral<Collection<? extends Movie<? extends Horror>>>() {}.getGenericType();
// final Collection<Movie<Comedy>> thatBean = null;
// final Collection<? extends Movie<? extends Horror>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Collection<? extends Movie<? extends Horror>> thatBean = null;
// final Collection<Movie<Comedy>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldReturnFalseWhenUsingWildcardAtLastLevelButNotPrevious() {
final Type thatType = new TypeLiteral<Collection<Movie<Horror>>>() {}.getGenericType();
final Type thisType = new TypeLiteral<Collection<Movie<? extends Horror>>>() {}.getGenericType();
// final Collection<Movie<Horror>> thatBean = null;
// final Collection<Movie<? extends Horror>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Collection<Movie<? extends Horror>> thatBean = null;
// final Collection<Movie<Horror>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenUsingNestedWildcardInTypeVariableOfClassAndTypeMatches() {
final Type thisType = new TypeLiteral<TypeVariableWithNestedWildcard<Container<Fanta>>>() {}.getGenericType();
// final TypeVariableWithNestedWildcardImpl thatBean = null;
// final TypeVariableWithNestedWildcard<Container<Fanta>> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, TypeVariableWithNestedWildcardImpl.class));
// final TypeVariableWithNestedWildcard<Container<Fanta>> thatBean = null;
// final TypeVariableWithNestedWildcardImpl thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(TypeVariableWithNestedWildcardImpl.class, thisType));
}
@Test
public void isAssignableFromShouldBeTrueWhenUsingNestedWildcardInTypeVariableOfClassAndTypeMatchesWildcard() {
final Type thisType = new TypeLiteral<TypeVariableWithNestedWildcard<? extends Container<? extends Liquid>>>() {}.getGenericType();
// final TypeVariableWithNestedWildcardImpl thatBean = null;
// final TypeVariableWithNestedWildcard<? extends Container<? extends Liquid>> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, TypeVariableWithNestedWildcardImpl.class));
// final TypeVariableWithNestedWildcard<? extends Container<? extends Liquid>> thatBean = null;
// final TypeVariableWithNestedWildcardImpl thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(TypeVariableWithNestedWildcardImpl.class, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenUsingNestedWildcardInTypeVariableOfClassAndNestedTypeDoesNotMatch() {
final Type thisType = new TypeLiteral<TypeVariableWithNestedWildcard<Container<Pepsi>>>() {}.getGenericType();
// final TypeVariableWithNestedWildcardImpl thatBean = null;
// final TypeVariableWithNestedWildcard<Container<Pepsi>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, TypeVariableWithNestedWildcardImpl.class));
// final TypeVariableWithNestedWildcard<Container<Pepsi>> thatBean = null;
// final TypeVariableWithNestedWildcardImpl thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(TypeVariableWithNestedWildcardImpl.class, thisType));
}
@Test
public void isAssignableFromShouldBeFalseWhenUsingNestedWildcardInTypeVariableOfClassAndNestedTypeIsSubclass() {
final Type thisType = new TypeLiteral<TypeVariableWithNestedWildcard<Container<Liquid>>>() {}.getGenericType();
// final TypeVariableWithNestedWildcardImpl thatBean = null;
// final TypeVariableWithNestedWildcard<Container<Liquid>> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thisType, TypeVariableWithNestedWildcardImpl.class));
// final TypeVariableWithNestedWildcard<Container<Liquid>> thatBean = null;
// final TypeVariableWithNestedWildcardImpl thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(TypeVariableWithNestedWildcardImpl.class, thisType));
}
@Test
public void isAssignableFromShouldBeTrueForArrayOfTheSameClassAndOneDimension() {
assertTrue(GenericsHelper.isAssignableFrom(String[].class, String[].class));
assertTrue(String[].class.isAssignableFrom(String[].class));
}
@Test
public void isAssignableFromShouldBeTrueForArrayOfTheSameClassAndTwoDimensions() {
assertTrue(GenericsHelper.isAssignableFrom(String[][].class, String[][].class));
assertTrue(String[][].class.isAssignableFrom(String[][].class));
}
@Test
public void isAssignableFromShouldBeFalseForArrayOfTheSameClassAndDifferentDimensions() {
assertFalse(GenericsHelper.isAssignableFrom(String[].class, String[][].class));
assertFalse(String[].class.isAssignableFrom(String[][].class));
assertFalse(GenericsHelper.isAssignableFrom(String[][].class, String[].class));
assertFalse(String[][].class.isAssignableFrom(String[].class));
}
@Test
public void isAssignableFromShouldBeFalseForAssignmentBetweenArrayAndRegularClassOfTheSameClass() {
assertFalse(GenericsHelper.isAssignableFrom(String.class, String[].class));
assertFalse(String.class.isAssignableFrom(String[].class));
assertFalse(GenericsHelper.isAssignableFrom(String[].class, String.class));
assertFalse(String[].class.isAssignableFrom(String.class));
}
@Test
public void isAssignableFromShouldBeTrueForAssignmentBetweenArrayAndObject() {
assertTrue(GenericsHelper.isAssignableFrom(Object.class, String[].class));
assertTrue(Object.class.isAssignableFrom(String[].class));
assertFalse(GenericsHelper.isAssignableFrom(String[].class, Object.class));
assertFalse(String[].class.isAssignableFrom(Object.class));
}
@Test
public void isAssignableFromShouldBeTrueForAssignmentBetweenArrayAndObjectArray() {
assertTrue(GenericsHelper.isAssignableFrom(Object[].class, String[].class));
assertTrue(Object[].class.isAssignableFrom(String[].class));
assertFalse(GenericsHelper.isAssignableFrom(String[].class, Object[].class));
assertFalse(String[].class.isAssignableFrom(Object[].class));
}
@Test
public void isAssignableFromShouldBeTrueForAssignmentBetweenArrayAndObjectArrayOfDifferentDimensions() {
// True because any array is also an object - does not work with any other classes
assertTrue(GenericsHelper.isAssignableFrom(Object[].class, String[][].class));
assertTrue(Object[].class.isAssignableFrom(String[][].class));
assertFalse(GenericsHelper.isAssignableFrom(String[][].class, Object[].class));
assertFalse(String[][].class.isAssignableFrom(Object[].class));
}
@Test
public void isAssignableFromShouldBeFalseForAssignmentBetweenArrayAndObjectArrayOfDifferentDimensionsWhenObjectHasMost() {
assertFalse(GenericsHelper.isAssignableFrom(Object[][].class, String[].class));
assertFalse(Object[][].class.isAssignableFrom(String[].class));
assertFalse(GenericsHelper.isAssignableFrom(String[].class, Object[][].class));
assertFalse(String[].class.isAssignableFrom(Object[][].class));
}
@Test
public void isAssignableFromShouldBeFalseForAssignmentBetweenArrayAndRegularSuperclass() {
assertTrue(Number.class.isAssignableFrom(Integer.class)); // Verify non-array assignability
assertFalse(GenericsHelper.isAssignableFrom(Number.class, Integer[].class));
assertFalse(Number.class.isAssignableFrom(Integer[].class));
assertFalse(GenericsHelper.isAssignableFrom(Integer[].class, Number.class));
assertFalse(Integer[].class.isAssignableFrom(Number.class));
}
@Test
public void isAssignableFromShouldBeFalseForAssignmentBetweenArraysWithCorrectInheritanceAndDifferentDimensions() {
assertTrue(Number.class.isAssignableFrom(Integer.class)); // Verify non-array assignability
assertFalse(GenericsHelper.isAssignableFrom(Number[].class, Integer[][].class));
assertFalse(Number[].class.isAssignableFrom(Integer[][].class));
assertFalse(GenericsHelper.isAssignableFrom(Integer[][].class, Number[].class));
assertFalse(Integer[][].class.isAssignableFrom(Number[].class));
}
@Test
public void isAssignableFromShouldBeTrueForArraysOfCorrectInheritance() {
assertTrue(GenericsHelper.isAssignableFrom(MiddleBean[].class, ChildBean[].class));
assertTrue(MiddleBean[].class.isAssignableFrom(ChildBean[].class));
assertFalse(GenericsHelper.isAssignableFrom(ChildBean[].class, MiddleBean[].class));
assertFalse(ChildBean[].class.isAssignableFrom(MiddleBean[].class));
}
@Test
public void isAssignableFromShouldBeTrueForGenericTypeWithArrayThatMatches() {
final Type thisType = new TypeLiteral<Provider<String[]>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Provider<String[]>>() {}.getGenericType();
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
}
@Test
public void isAssignableFromShouldBeFalseForGenericTypeWithArrayOfWrongType() {
final Type thisType = new TypeLiteral<Provider<Number[]>>() {}.getGenericType();
final Type thatType = new TypeLiteral<Provider<Integer[]>>() {}.getGenericType();
assertFalse(GenericsHelper.isAssignableFrom(thisType, thatType));
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueInJava7WithConcreteArrayInsteadOfGenericArray() {
// Tests an injection point with a concrete array (like Container<Fanta[]>, not Container<T[]>).
// In Java 6 both the factory point and the injection point will be GenericArrayTypes, and matches on equals.
// In Java 7 however, the injection point will be a real array, so special handling is needed to compare
// the array to a GenericArrayType.
// Since using a TypeLiteral gives different results (GenericArrayType vs real array) in Java 6 and 7
// then this test needs to use wrappers to simulate the same effect in both versions.
final Type thisConcreteArray = new WrappedParameterizedType(Container.class, new Type[] {Fanta[].class});
final Type thatGenericArray =
new WrappedParameterizedType(Container.class, new Type[] {new WrappedGenericArrayType(Fanta.class)});
assertTrue(GenericsHelper.isAssignableFrom(thisConcreteArray, thatGenericArray));
assertFalse(GenericsHelper.isAssignableFrom(thatGenericArray, thisConcreteArray));
}
@Test
public void isAssignableFromShouldBeTrueForArrayFromGenericTypeThatMatchesRegularArrayOfCorrectType() {
final Type thisProvider = new TypeLiteral<Provider<String[]>>() {}.getGenericType();
final Type thisType = GenericsHelper.getGenericArgumentAsType(thisProvider);
assertTrue(GenericsHelper.isAssignableFrom(thisType, String[].class));
assertFalse(GenericsHelper.isAssignableFrom(String[].class, thisType));
}
@Test
public void isAssignableFromShouldBeFalseForArrayFromGenericTypeWithLessDimensionsThanRegularArrayOfCorrectType() {
final Type thisProvider = new TypeLiteral<Provider<String[]>>() {}.getGenericType();
final Type thisType = GenericsHelper.getGenericArgumentAsType(thisProvider);
assertFalse(GenericsHelper.isAssignableFrom(thisType, String[][].class));
assertFalse(GenericsHelper.isAssignableFrom(String[][].class, thisType));
}
@Test
public void isAssignableFromShouldBeFalseForArrayFromGenericTypeWithMoreDimensionsThanRegularArrayOfCorrectType() {
final Type thisProvider = new TypeLiteral<Provider<String[][]>>() {}.getGenericType();
final Type thisType = GenericsHelper.getGenericArgumentAsType(thisProvider);
assertFalse(GenericsHelper.isAssignableFrom(thisType, String[].class));
assertFalse(GenericsHelper.isAssignableFrom(String[].class, thisType));
}
@Test
public void isAssignableFromShouldBeTrueForArrayFromGenericTypeThatMatchesRegularArrayOfCorrectInheritance() {
final Type thisProvider = new TypeLiteral<Provider<Number[]>>() {}.getGenericType();
final Type thisType = GenericsHelper.getGenericArgumentAsType(thisProvider);
assertTrue(GenericsHelper.isAssignableFrom(thisType, Integer[].class));
assertFalse(GenericsHelper.isAssignableFrom(Integer[].class, thisType));
}
@Test
public void isAssignableFromShouldBeTrueFromGenericArrayToWildcardOfCorrectType() {
final Type thatType = new TypeLiteral<Box<String[]>>() {}.getGenericType();
final Type thisType = new TypeLiteral<Box<? extends String[]>>() {}.getGenericType();
// final Box<String[]> thatBean = null;
// final Box<? extends String[]> thisBean = thatBean; // ok
assertTrue(GenericsHelper.isAssignableFrom(thisType, thatType));
// final Box<? extends String[]> thatBean = null;
// final Box<String[]> thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(thatType, thisType));
}
@Test
public void isAssignableFromShouldBeTrueFromArrayToWildcardOfCorrectType() {
final Type thisType = new TypeLiteral<Provider<? extends String[]>>() {}.getGenericType();
final Type thisWildcard = GenericsHelper.getGenericArgumentAsType(thisType);
// final String[] thatBean = null;
// final ? extends String[] thisBean = thatBean; // ok, but not possible to write, must come from a generic type
assertTrue(GenericsHelper.isAssignableFrom(thisWildcard, String[].class));
// final ? extends String[] thatBean = null;
// final String[] thisBean = thatBean; // compiler error
assertFalse(GenericsHelper.isAssignableFrom(String[].class, thisWildcard));
}
@Test
public void mapTypeVariablesToActualTypesShouldHandleInheritance() {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(ConcreteDualVariableBean.class);
assertEquals(3, typeMap.size());
final TypeVariable<?> interfaceF = getTypeVariable("F", DualVariableInterfaceBean.class, typeMap);
assertNotNull(interfaceF);
assertEquals(VariableOnePointTwo.class, typeMap.getActualType(interfaceF));
final TypeVariable<?> interfaceS = getTypeVariable("S", DualVariableInterfaceBean.class, typeMap);
assertNotNull(interfaceS);
assertEquals(VariableTwo.class, typeMap.getActualType(interfaceS));
final TypeVariable<?> abstractS = getTypeVariable("S", AbstractDualVariableBean.class, typeMap);
assertNotNull(abstractS);
assertEquals(VariableOnePointTwo.class, typeMap.getActualType(abstractS));
}
@Test
public void mapTypeVariablesToActualTypesShouldHandleNoTypeVariables() {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(HelloBean.class);
assertEquals(0, typeMap.size());
}
@Test
public void mapTypeVariablesToActualTypesShouldHandleNotResolvingAllTypes() {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(ArrayList.class);
assertEquals(5, typeMap.size());
final Set<TypeVariable<?>> keys = typeMap.getKeys();
for (final TypeVariable<?> key : keys) {
final Type actualType = typeMap.getActualType(key);
assertNull(actualType);
}
}
@Test
public void mapTypeVariablesToActualTypesShouldNotMapTypeVariablesDeclaredLocallyOnMethods() throws NoSuchMethodException {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(TypeVariableChild.class);
assertNotNull(typeMap);
assertEquals(1, typeMap.size());
// Verifying expected type in the map
final TypeVariable<?> typeVariable = getTypeVariable("T", TypeVariableParent.class, typeMap);
assertNotNull(typeVariable);
assertEquals(Square.class, typeMap.getActualType(typeVariable));
// Method that uses it's own declaration of T - should map to null
final Type localT = TypeVariableParent.class.getDeclaredMethod("getLocallyDeclaredT").getGenericReturnType();
assertNull(typeMap.getActualType((TypeVariable<?>) localT));
// Method that uses the class declaration of T - should map to the actual type
final Type classT = TypeVariableParent.class.getDeclaredMethod("getClassDeclaredT").getGenericReturnType();
assertEquals(Square.class, typeMap.getActualType((TypeVariable<?>) classT));
}
@Test
public void wrapTypeAndReplaceTypeVariablesShouldReplaceTypeVariableAsMainType() throws NoSuchFieldException {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(TypeVariableBeanWithFanta.class);
final Class<Fanta> expectedType = Fanta.class;
final Type fieldType = getTypeFromField("standaloneT");
assertFalse(expectedType.equals(fieldType));
final Type typeFromMap = typeMap.getActualType((TypeVariable<?>) fieldType);
assertEquals(expectedType, typeFromMap);
final Type wrappedType = GenericsHelper.wrapTypeAndReplaceTypeVariables(fieldType, typeMap);
assertEquals(expectedType, wrappedType);
}
@Test
public void wrapTypeAndReplaceTypeVariablesShouldLeaveTypeVariableAsIsIfNoReplacementWasFoundForMainType() throws NoSuchFieldException {
final TypeMap typeMap = new TypeMap();
final Type fieldType = getTypeFromField("standaloneT");
final Type typeFromMap = typeMap.getActualType((TypeVariable<?>) fieldType);
assertNull(typeFromMap);
final Type wrappedType = GenericsHelper.wrapTypeAndReplaceTypeVariables(fieldType, typeMap);
assertTrue(GenericsHelper.isTypeVariable(wrappedType));
}
@Test
public void wrapTypeAndReplaceTypeVariablesShouldReplaceTypeVariableAsSubType() throws NoSuchFieldException {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(TypeVariableBeanWithFanta.class);
final Type expectedType = new TypeLiteral<Container<Fanta>>() {}.getGenericType();
final Type unexpectedType = new TypeLiteral<Container<Pepsi>>() {}.getGenericType();
final Type fieldType = getTypeFromField("containerOfT");
assertFalse(expectedType.equals(fieldType));
final Type wrappedType = GenericsHelper.wrapTypeAndReplaceTypeVariables(fieldType, typeMap);
assertEquals(expectedType, wrappedType);
assertEquals(wrappedType, expectedType);
assertFalse(unexpectedType.equals(wrappedType));
assertFalse(wrappedType.equals(unexpectedType));
}
@Test
public void wrapTypeAndReplaceTypeVariablesShouldLeaveTypeVariableAsIsIfNoReplacementWasFoundForSubType() throws NoSuchFieldException {
final TypeMap typeMap = new TypeMap();
final Type fieldType = getTypeFromField("containerOfT");
final Type wrappedType = GenericsHelper.wrapTypeAndReplaceTypeVariables(fieldType, typeMap);
final Type wrappedTypeArgument = GenericsHelper.getGenericArgumentAsType(wrappedType);
assertTrue(GenericsHelper.isTypeVariable(wrappedTypeArgument));
}
@Test
public void wrapTypeAndReplaceTypeVariablesShouldReplaceTypeVariableAsSubSubType() throws NoSuchFieldException {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(TypeVariableBeanWithFanta.class);
final Type expectedType = new TypeLiteral<Set<Container<Fanta>>>() {}.getGenericType();
final Type unexpectedType = new TypeLiteral<Set<Container<Pepsi>>>() {}.getGenericType();
final Type fieldType = getTypeFromField("setOfContainersOfT");
assertFalse(expectedType.equals(fieldType));
final Type wrappedType = GenericsHelper.wrapTypeAndReplaceTypeVariables(fieldType, typeMap);
assertEquals(expectedType, wrappedType);
assertEquals(wrappedType, expectedType);
assertFalse(unexpectedType.equals(wrappedType));
assertFalse(wrappedType.equals(unexpectedType));
}
@Test
public void wrapTypeAndReplaceTypeVariablesShouldReplaceTypeVariableInWildcardWithExtends() throws NoSuchFieldException {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(TypeVariableBeanWithFanta.class);
final Type expectedType = new TypeLiteral<Set<Container<? extends Fanta>>>() {}.getGenericType();
final Type unexpectedType = new TypeLiteral<Set<Container<? extends Pepsi>>>() {}.getGenericType();
final Type fieldType = getTypeFromField("setOfContainersOfExtendsT");
assertFalse(expectedType.equals(fieldType));
final Type wrappedType = GenericsHelper.wrapTypeAndReplaceTypeVariables(fieldType, typeMap);
assertEquals(expectedType, wrappedType);
assertEquals(wrappedType, expectedType);
assertFalse(unexpectedType.equals(wrappedType));
assertFalse(wrappedType.equals(unexpectedType));
}
@Test
public void wrapTypeAndReplaceTypeVariablesShouldReplaceTypeVariableInWildcardWithSuper() throws NoSuchFieldException {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(TypeVariableBeanWithFanta.class);
final Type expectedType = new TypeLiteral<Set<Container<? super Fanta>>>() {}.getGenericType();
final Type unexpectedType = new TypeLiteral<Set<Container<? super Pepsi>>>() {}.getGenericType();
final Type fieldType = getTypeFromField("setOfContainersOfSuperT");
assertFalse(expectedType.equals(fieldType));
final Type wrappedType = GenericsHelper.wrapTypeAndReplaceTypeVariables(fieldType, typeMap);
assertEquals(expectedType, wrappedType);
assertEquals(wrappedType, expectedType);
assertFalse(unexpectedType.equals(wrappedType));
assertFalse(wrappedType.equals(unexpectedType));
}
@Test
public void wrapTypeAndReplaceTypeVariablesShouldReplaceTypeVariablesInArrays() throws NoSuchFieldException {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(TypeVariableBeanWithFanta.class);
final Type expectedType = new TypeLiteral<Fanta[]>() {}.getGenericType();
final Type unexpectedType = new TypeLiteral<Pepsi[]>() {}.getGenericType();
final Type fieldType = getTypeFromField("arrayT");
assertFalse(expectedType.equals(fieldType));
final Type wrappedType = GenericsHelper.wrapTypeAndReplaceTypeVariables(fieldType, typeMap);
assertEquals(expectedType, wrappedType);
assertEquals(wrappedType, expectedType);
assertFalse(unexpectedType.equals(wrappedType));
assertFalse(wrappedType.equals(unexpectedType));
}
@Test
public void wrapTypeAndReplaceTypeVariablesShouldReplaceTypeVariablesInNestedArrays() throws NoSuchFieldException {
final TypeMap typeMap = GenericsHelper.mapTypeVariablesToActualTypes(TypeVariableBeanWithFanta.class);
final Type expectedType = new TypeLiteral<Set<Container<Fanta[]>>>() {}.getGenericType();
final Type unexpectedType = new TypeLiteral<Set<Container<Pepsi[]>>>() {}.getGenericType();
final Type fieldType = getTypeFromField("setOfContainersOfArrayT");
assertFalse(expectedType.equals(fieldType));
final Type wrappedType = GenericsHelper.wrapTypeAndReplaceTypeVariables(fieldType, typeMap);
assertEquals(expectedType, wrappedType);
assertEquals(wrappedType, expectedType);
assertFalse(unexpectedType.equals(wrappedType));
assertFalse(wrappedType.equals(unexpectedType));
}
private Type getTypeFromField(final String fieldName) throws NoSuchFieldException {
final Field field = TypeVariableBean.class.getDeclaredField(fieldName);
return field.getGenericType();
}
private TypeVariable<?> getTypeVariable(final String name, final Class<?> ownerClass, final TypeMap typeMap) {
final Set<TypeVariable<?>> keys = typeMap.getKeys();
for (final TypeVariable<?> key : keys) {
if (key.getName().equals(name) && key.getGenericDeclaration().equals(ownerClass)) {
return key;
}
}
return null;
}
}