org.evosuite.utils.TestGenericClass.java Source code

Java tutorial

Introduction

Here is the source code for org.evosuite.utils.TestGenericClass.java

Source

/**
 * Copyright (C) 2010-2016 Gordon Fraser, Andrea Arcuri and EvoSuite
 * contributors
 *
 * This file is part of EvoSuite.
 *
 * EvoSuite 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.0 of the License, or
 * (at your option) any later version.
 *
 * EvoSuite 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 Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>.
 */
package org.evosuite.utils;

import static org.junit.Assert.assertEquals;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.apache.commons.lang3.reflect.TypeUtils;
import org.evosuite.ga.ConstructionFailedException;
import org.evosuite.instrumentation.InstrumentingClassLoader;
import org.evosuite.utils.generic.GenericClass;
import org.evosuite.utils.generic.WildcardTypeImpl;
import org.junit.Assert;
import org.junit.Test;

import com.examples.with.different.packagename.generic.AbstractGuavaExample;
import com.examples.with.different.packagename.generic.GuavaExample5;
import com.googlecode.gentyref.GenericTypeReflector;
import com.googlecode.gentyref.TypeToken;

import java.lang.reflect.AnnotatedType;

public class TestGenericClass {

    @Test
    public void testWildcardClassloader() {
        GenericClass clazz = new GenericClass(Class.class).getWithWildcardTypes();
        assertEquals("java.lang.Class<?>", clazz.getTypeName());
        clazz.changeClassLoader(TestGenericClass.class.getClassLoader());
        assertEquals("java.lang.Class<?>", clazz.getTypeName());
    }

    @Test
    public void testAssignablePrimitives() {
        GenericClass clazz1 = new GenericClass(int.class);
        GenericClass clazz2 = new GenericClass(int.class);
        Assert.assertTrue(clazz1.isAssignableTo(clazz2));
        Assert.assertTrue(clazz1.isAssignableFrom(clazz2));
    }

    @Test
    public void testAssignableObject() {
        GenericClass clazz1 = new GenericClass(Object.class);
        GenericClass clazz2 = new GenericClass(Object.class);
        Assert.assertTrue(clazz1.isAssignableTo(clazz2));
    }

    @Test
    public void testAssignableIntegerObject() {
        GenericClass clazz1 = new GenericClass(Integer.class);
        GenericClass clazz2 = new GenericClass(Object.class);
        Assert.assertTrue(clazz1.isAssignableTo(clazz2));
        Assert.assertFalse(clazz1.isAssignableFrom(clazz2));
    }

    @Test
    public void testAssignableIntegerNumber() {
        GenericClass clazz1 = new GenericClass(Integer.class);
        GenericClass clazz2 = new GenericClass(Number.class);
        Assert.assertTrue(clazz1.isAssignableTo(clazz2));
        Assert.assertFalse(clazz1.isAssignableFrom(clazz2));
    }

    @Test
    public void testAssignableIntInteger() {
        GenericClass clazz1 = new GenericClass(Integer.class);
        GenericClass clazz2 = new GenericClass(int.class);
        Assert.assertTrue(clazz1.isAssignableTo(clazz2));
        Assert.assertTrue(clazz1.isAssignableFrom(clazz2));
    }

    @Test
    public void testAssignableClass() {
        GenericClass clazzTypeVar = new GenericClass(Class.class);
        GenericClass clazzWildcard = clazzTypeVar.getWithWildcardTypes();

        ParameterizedType type = new ParameterizedTypeImpl(Class.class, new Type[] { Integer.class }, null);
        GenericClass clazzConcrete = new GenericClass(type);

        Assert.assertFalse(clazzWildcard.isAssignableTo(clazzConcrete));
        Assert.assertFalse(clazzWildcard.isAssignableTo(clazzTypeVar));
        Assert.assertTrue(clazzWildcard.isAssignableTo(clazzWildcard));

        Assert.assertFalse(clazzTypeVar.isAssignableTo(clazzConcrete));
        Assert.assertTrue(clazzTypeVar.isAssignableTo(clazzTypeVar));
        Assert.assertTrue(clazzTypeVar.isAssignableTo(clazzWildcard));

        Assert.assertTrue(clazzConcrete.isAssignableTo(clazzConcrete));
        Assert.assertFalse(clazzConcrete.isAssignableTo(clazzTypeVar));
        Assert.assertTrue(clazzConcrete.isAssignableTo(clazzWildcard));
    }

    private static class A {
    }

    @SuppressWarnings({ "rawtypes", "unused", "unchecked" })
    @Test
    public void test01() throws Throwable {

        /*
         * This test case come from compilation issue found during SBST'13 competition:
         * 
         * String string0 = vM0.run(vM0.stack);
         * 
         * SUT at:  http://www.massapi.com/source/jabref-2.6/src/java/net/sf/jabref/bst/VM.java.html
         * 
         * Snippet of interest:
         * 
         * 1) Stack<Object> stack = new Stack<Object>();
         * 2)  public String run(Collection<BibtexEntry> bibtex) {
         */

        Collection<?> col0 = new Stack<Object>();
        Collection<A> col1 = new Stack();
        Collection col2 = new Stack();
        Collection col3 = new Stack<Object>();

        /*
         *  following does not compile
         *  
         *  Collection<A> col = new Stack<Object>();
         *  
         *  but it can be generated by EvoSuite
         */

        GenericClass stack = new GenericClass(Stack.class).getWithWildcardTypes();
        GenericClass collection = new GenericClass(Collection.class).getWithWildcardTypes();
        Assert.assertTrue(stack.isAssignableTo(collection));

        GenericClass objectStack = new GenericClass(col0.getClass());
        Assert.assertTrue(objectStack.isAssignableTo(collection));

        Type typeColA = new TypeToken<Collection<A>>() {
        }.getType();
        Type typeStack = new TypeToken<Stack>() {
        }.getType();
        Type typeObjectStack = new TypeToken<Stack<Object>>() {
        }.getType();

        GenericClass classColA = new GenericClass(typeColA);
        GenericClass classStack = new GenericClass(typeStack).getWithWildcardTypes();
        GenericClass classObjectStack = new GenericClass(typeObjectStack);

        Assert.assertFalse(classStack.isAssignableTo(classColA));
        Assert.assertFalse(classObjectStack.isAssignableTo(classColA));
        Assert.assertFalse(classColA.isAssignableFrom(classObjectStack));
    }

    @Test
    public void test1() {
        Type listOfString = new TypeToken<List<String>>() {
        }.getType();
        Type listOfInteger = new TypeToken<List<Integer>>() {
        }.getType();

        GenericClass listOfStringClass = new GenericClass(listOfString);
        GenericClass listOfIntegerClass = new GenericClass(listOfInteger);

        Assert.assertFalse(listOfStringClass.isAssignableFrom(listOfIntegerClass));
        Assert.assertFalse(listOfStringClass.isAssignableTo(listOfIntegerClass));
    }

    @SuppressWarnings("rawtypes")
    @Test
    public void test2() {
        Type listOfString = new TypeToken<List<String>>() {
        }.getType();
        Type plainList = new TypeToken<List>() {
        }.getType();
        Type objectList = new TypeToken<List<Object>>() {
        }.getType();

        GenericClass listOfStringClass = new GenericClass(listOfString);
        GenericClass plainListClass = new GenericClass(plainList).getWithWildcardTypes();
        GenericClass objectListClass = new GenericClass(objectList);

        /*
         * Note:
         * 
         *       List<String> l = new LinkedList<Object>();
         * 
         *  does not compile
         */

        Assert.assertFalse(listOfStringClass.isAssignableTo(objectListClass));

        Assert.assertFalse(listOfStringClass.isAssignableFrom(plainListClass));
        Assert.assertTrue(listOfStringClass.isAssignableTo(plainListClass));
    }

    @Test
    public void test3() {
        Type listOfInteger = new TypeToken<List<Integer>>() {
        }.getType();
        Type listOfSerializable = new TypeToken<List<Serializable>>() {
        }.getType();

        GenericClass listOfIntegerClass = new GenericClass(listOfInteger);
        GenericClass listOfSerializableClass = new GenericClass(listOfSerializable);

        Assert.assertFalse(listOfIntegerClass.isAssignableFrom(listOfSerializableClass));
        Assert.assertFalse(listOfSerializableClass.isAssignableFrom(listOfIntegerClass));

        Assert.assertTrue(listOfIntegerClass.isAssignableFrom(listOfIntegerClass));
        Assert.assertTrue(listOfSerializableClass.isAssignableFrom(listOfSerializableClass));
    }

    private class NumberBoundary<T extends Number> {
    }

    private class ComparableBoundary<T extends Comparable<T>> {
    }

    private class RefinedComparableBoundary<T extends java.util.Date> extends ComparableBoundary<java.util.Date> {
    }

    @Test
    public void testTypeVariableBoundariesNumber() {
        TypeVariable<?> numberTypeVariable = NumberBoundary.class.getTypeParameters()[0];

        GenericClass listOfIntegerClass = new GenericClass(Integer.class);
        GenericClass listOfSerializableClass = new GenericClass(Serializable.class);

        Assert.assertTrue(listOfIntegerClass.satisfiesBoundaries(numberTypeVariable));
        Assert.assertFalse(listOfSerializableClass.satisfiesBoundaries(numberTypeVariable));
    }

    @Test
    public void testTypeVariableBoundariesComparable() {
        TypeVariable<?> comparableTypeVariable = ComparableBoundary.class.getTypeParameters()[0];

        GenericClass listOfIntegerClass = new GenericClass(Integer.class);
        GenericClass listOfSerializableClass = new GenericClass(Serializable.class);

        Assert.assertTrue(listOfIntegerClass.satisfiesBoundaries(comparableTypeVariable));
        Assert.assertFalse(listOfSerializableClass.satisfiesBoundaries(comparableTypeVariable));
    }

    @Test
    public void testGuavaExample() {
        Type abstractGuavaExampleString = new TypeToken<AbstractGuavaExample<String>>() {
        }.getType();
        Type guavaExample5 = new TypeToken<GuavaExample5<String>>() {
        }.getType();

        GenericClass abstractClass = new GenericClass(abstractGuavaExampleString);
        GenericClass concreteClass = new GenericClass(guavaExample5);

        Assert.assertTrue(TypeUtils.isAssignable(concreteClass.getType(), abstractClass.getType()));
        Assert.assertTrue("Cannot assign " + concreteClass + " to " + abstractClass,
                abstractClass.isAssignableFrom(concreteClass));
        Assert.assertTrue(concreteClass.isAssignableTo(abstractClass));
    }

    @Test
    public void testTypeVariableBoundariesRefined() {
        TypeVariable<?> dateTypeVariable = RefinedComparableBoundary.class.getTypeParameters()[0];
        TypeVariable<?> comparableTypeVariable = ComparableBoundary.class.getTypeParameters()[0];

        GenericClass listOfIntegerClass = new GenericClass(Integer.class);
        GenericClass listOfComparableClass = new GenericClass(Comparable.class);
        GenericClass listOfDateClass = new GenericClass(java.util.Date.class);
        GenericClass listOfSqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertFalse(listOfIntegerClass.satisfiesBoundaries(dateTypeVariable));
        Assert.assertFalse(listOfComparableClass.satisfiesBoundaries(dateTypeVariable));
        Assert.assertTrue(listOfDateClass.satisfiesBoundaries(dateTypeVariable));
        Assert.assertTrue(listOfSqlDateClass.satisfiesBoundaries(dateTypeVariable));

        Assert.assertTrue(listOfIntegerClass.satisfiesBoundaries(comparableTypeVariable));
        //      Assert.assertTrue(listOfComparableClass.satisfiesBoundaries(comparableTypeVariable));
        Assert.assertTrue(listOfDateClass.satisfiesBoundaries(comparableTypeVariable));
        // Assert.assertTrue(listOfSqlDateClass.satisfiesBoundaries(comparableTypeVariable));
    }

    @Test
    public void testWildcardObjectBoundaries() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { Object.class }, new Type[] {});

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertTrue(integerClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(dateClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testWildcardNumberBoundaries() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { Number.class }, new Type[] {});

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertTrue(integerClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(dateClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testWildcardIntegerBoundaries() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { Integer.class }, new Type[] {});

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertTrue(integerClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(dateClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testWildcardComparableBoundaries() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { Comparable.class }, new Type[] {});

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertTrue(integerClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(dateClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testWildcardDateBoundaries() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { java.util.Date.class }, new Type[] {});

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertFalse(integerClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(dateClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testWildcardSqlDateBoundaries() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { java.sql.Date.class }, new Type[] {});

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertFalse(integerClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(dateClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testWildcardDateSuperBoundaries() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { Object.class },
                new Type[] { java.util.Date.class });

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertFalse(integerClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(dateClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testWildcardDateBothBoundaries() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { java.util.Date.class },
                new Type[] { java.util.Date.class });

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertFalse(integerClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(dateClass.satisfiesBoundaries(objectType));
        // Does not satisfy lower bound, so needs to be false
        Assert.assertFalse(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testWildcardDateBothBoundaries2() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { Comparable.class },
                new Type[] { java.util.Date.class });

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertFalse(integerClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertTrue(dateClass.satisfiesBoundaries(objectType));
        // Does not satisfy lower boundary
        Assert.assertFalse(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testWildcardInvalidBoundaries() {

        WildcardType objectType = new WildcardTypeImpl(new Type[] { Number.class },
                new Type[] { java.util.Date.class });

        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass comparableClass = new GenericClass(Comparable.class);
        GenericClass dateClass = new GenericClass(java.util.Date.class);
        GenericClass sqlDateClass = new GenericClass(java.sql.Date.class);

        Assert.assertFalse(integerClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(comparableClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(dateClass.satisfiesBoundaries(objectType));
        Assert.assertFalse(sqlDateClass.satisfiesBoundaries(objectType));
    }

    @Test
    public void testGenericSuperclassWildcards() {
        GenericClass listOfInteger = new GenericClass(new TypeToken<List<Integer>>() {
        }.getType());
        GenericClass listOfWildcard = new GenericClass(new TypeToken<List<?>>() {
        }.getType());

        Assert.assertTrue(listOfWildcard.isGenericSuperTypeOf(listOfInteger));
        Assert.assertFalse(listOfInteger.isGenericSuperTypeOf(listOfWildcard));
        Assert.assertTrue(listOfInteger.hasGenericSuperType(listOfWildcard));
        Assert.assertFalse(listOfWildcard.hasGenericSuperType(listOfInteger));

        GenericClass mapOfInteger = new GenericClass(new TypeToken<Map<Integer, String>>() {
        }.getType());
        GenericClass mapOfWildcard = new GenericClass(new TypeToken<Map<?, ?>>() {
        }.getType());
        Assert.assertTrue(mapOfWildcard.isGenericSuperTypeOf(mapOfInteger));
        Assert.assertFalse(mapOfInteger.isGenericSuperTypeOf(mapOfWildcard));
        Assert.assertTrue(mapOfInteger.hasGenericSuperType(mapOfWildcard));
        Assert.assertFalse(mapOfWildcard.hasGenericSuperType(mapOfInteger));
    }

    @Test
    public void testGenericSuperclassConcreteList() {
        GenericClass listOfInteger = new GenericClass(new TypeToken<List<Integer>>() {
        }.getType());
        GenericClass linkedlistOfInteger = new GenericClass(new TypeToken<LinkedList<Integer>>() {
        }.getType());

        Assert.assertTrue(linkedlistOfInteger.canBeInstantiatedTo(listOfInteger));
        Assert.assertFalse(listOfInteger.canBeInstantiatedTo(linkedlistOfInteger));
    }

    @Test
    public void testGenericSuperclassToWildcardList() {
        GenericClass listOfWildcard = new GenericClass(new TypeToken<List<Integer>>() {
        }.getType()).getWithWildcardTypes();
        GenericClass linkedlistOfInteger = new GenericClass(new TypeToken<LinkedList<Integer>>() {
        }.getType());

        Assert.assertTrue(linkedlistOfInteger.canBeInstantiatedTo(listOfWildcard));
        Assert.assertFalse(listOfWildcard.canBeInstantiatedTo(linkedlistOfInteger));
    }

    @Test
    public void testGenericSuperclassFromWildcardList() {
        GenericClass listOfInteger = new GenericClass(new TypeToken<List<Integer>>() {
        }.getType());
        GenericClass linkedlistOfWildcard = new GenericClass(new TypeToken<LinkedList<Integer>>() {
        }.getType()).getWithWildcardTypes();

        Assert.assertTrue(linkedlistOfWildcard.canBeInstantiatedTo(listOfInteger));
        Assert.assertFalse(listOfInteger.canBeInstantiatedTo(linkedlistOfWildcard));
    }

    @SuppressWarnings("rawtypes")
    @Test
    public void testGenericSuperclassToTypeVariableList() {
        GenericClass listOfTypeVariable = new GenericClass(new TypeToken<List>() {
        }.getType());
        GenericClass linkedlistOfInteger = new GenericClass(new TypeToken<LinkedList<Integer>>() {
        }.getType());

        Assert.assertTrue(linkedlistOfInteger.canBeInstantiatedTo(listOfTypeVariable));
        Assert.assertFalse(listOfTypeVariable.canBeInstantiatedTo(linkedlistOfInteger));
    }

    @SuppressWarnings("rawtypes")
    @Test
    public void testGenericSuperclassFromTypeVariableList() {
        GenericClass listOfInteger = new GenericClass(new TypeToken<List<Integer>>() {
        }.getType());
        GenericClass linkedlistOfTypeVariable = new GenericClass(new TypeToken<LinkedList>() {
        }.getType());

        Assert.assertTrue(linkedlistOfTypeVariable.canBeInstantiatedTo(listOfInteger));
        Assert.assertFalse(listOfInteger.canBeInstantiatedTo(linkedlistOfTypeVariable));
    }

    @Test
    public void testPrimitiveWrapper() {
        GenericClass integerClass = new GenericClass(Integer.class);
        GenericClass intClass = new GenericClass(int.class);

        Assert.assertTrue(integerClass.canBeInstantiatedTo(intClass));
        Assert.assertFalse(intClass.canBeInstantiatedTo(integerClass));
    }

    @SuppressWarnings("rawtypes")
    @Test
    public void testGenericInstantiationIntegerList() throws ConstructionFailedException {
        GenericClass listOfInteger = new GenericClass(new TypeToken<List<Integer>>() {
        }.getType());
        GenericClass linkedlistOfTypeVariable = new GenericClass(new TypeToken<LinkedList>() {
        }.getType());

        GenericClass instantiatedClass = linkedlistOfTypeVariable.getWithParametersFromSuperclass(listOfInteger);
        //GenericClass instantiatedClass = linkedlistOfTypeVariable.getGenericInstantiation(listOfInteger.getTypeVariableMap());
        Assert.assertEquals(Integer.class, instantiatedClass.getParameterTypes().get(0));
    }

    @SuppressWarnings("rawtypes")
    @Test
    public void testGenericInstantiationMapSubclass() throws ConstructionFailedException {
        GenericClass mapOfStringAndWildcard = new GenericClass(new TypeToken<Map<String, ?>>() {
        }.getType());
        GenericClass hashMapClass = new GenericClass(new TypeToken<HashMap>() {
        }.getType());

        GenericClass instantiatedClass = hashMapClass.getWithParametersFromSuperclass(mapOfStringAndWildcard);
        //GenericClass instantiatedClass = linkedlistOfTypeVariable.getGenericInstantiation(listOfInteger.getTypeVariableMap());
        System.out.println(instantiatedClass.toString());
        Assert.assertEquals(String.class, instantiatedClass.getParameterTypes().get(0));
    }

    @Test
    public void testGenericInstantiationMapType() throws ConstructionFailedException {
        GenericClass genericClass = new GenericClass(
                com.examples.with.different.packagename.generic.GenericParameterExtendingGenericBounds.class);
        GenericClass instantiatedClass = genericClass.getGenericInstantiation();
        //GenericClass instantiatedClass = linkedlistOfTypeVariable.getGenericInstantiation(listOfInteger.getTypeVariableMap());
        System.out.println(instantiatedClass.toString());
        Type parameterType = instantiatedClass.getParameterTypes().get(0);
        Assert.assertTrue(TypeUtils.isAssignable(parameterType, Map.class));
        Assert.assertTrue(parameterType instanceof ParameterizedType);

        ParameterizedType parameterizedType = (ParameterizedType) parameterType;
        Assert.assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]);
    }

    @Test
    public void testIterableAndList() throws ConstructionFailedException {
        GenericClass iterableIntegerClass = new GenericClass(new TypeToken<java.lang.Iterable<Integer>>() {
        }.getType());
        GenericClass arrayListClass = new GenericClass(java.util.ArrayList.class);

        Assert.assertTrue(arrayListClass.canBeInstantiatedTo(iterableIntegerClass));
        Assert.assertFalse(iterableIntegerClass.canBeInstantiatedTo(arrayListClass));

        GenericClass instantiatedList = arrayListClass.getWithParametersFromSuperclass(iterableIntegerClass);

        Type parameterType = instantiatedList.getParameterTypes().get(0);
        Assert.assertEquals(Integer.class, GenericTypeReflector.erase(parameterType));
    }

    @SuppressWarnings("rawtypes")
    @Test
    public void testIterableAndListBoundaries() {
        Map<TypeVariable<?>, Type> typeMap = new HashMap<TypeVariable<?>, Type>();
        final GenericClass iterableIntegerClass = new GenericClass(new TypeToken<java.lang.Iterable<Integer>>() {
        }.getType());

        TypeVariable<?> var = new TypeVariable() {

            public AnnotatedType[] getAnnotatedBounds() {
                return null;
            }

            @Override
            public Type[] getBounds() {
                return new Type[] { iterableIntegerClass.getType() };
            }

            @Override
            public GenericDeclaration getGenericDeclaration() {
                // TODO Auto-generated method stub
                return null;
            }

            @Override
            public String getName() {
                return "Test";
            }

            /* (non-Javadoc)
             * @see java.lang.Object#toString()
             */
            @Override
            public String toString() {
                return "Dummy Variable";
            }

            public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
                // TODO Auto-generated method stub
                return null;
            }

            public Annotation[] getAnnotations() {
                // TODO Auto-generated method stub
                return null;
            }

            public Annotation[] getDeclaredAnnotations() {
                // TODO Auto-generated method stub
                return null;
            }

            //public void getAnnotatedBounds() {
            // TODO Auto-generated method stub
            //}

        };

        typeMap.put(var, iterableIntegerClass.getType());

        GenericClass arrayListClass = new GenericClass(new TypeToken<java.util.ArrayList<String>>() {
        }.getType());

        Assert.assertFalse(arrayListClass.satisfiesBoundaries(var, typeMap));

        arrayListClass = new GenericClass(new TypeToken<java.util.ArrayList<Integer>>() {
        }.getType());

        Assert.assertTrue(arrayListClass.satisfiesBoundaries(var, typeMap));

    }

    @Test
    public void testSatisfiesTypeVariableInSubtype() {
        GenericClass iterableIntegerClass = new GenericClass(
                new TypeToken<com.examples.with.different.packagename.generic.GuavaExample4<java.lang.Iterable<Integer>>>() {
                }.getType());
        ParameterizedType iterableInteger = (ParameterizedType) iterableIntegerClass.getParameterTypes().get(0);
        TypeVariable<?> typeVariable = ((Class<?>) iterableInteger.getRawType()).getTypeParameters()[0];

        TypeVariable<?> iterableTypeVariable = iterableIntegerClass.getTypeVariables().get(0);

        GenericClass listOfIntegerClass = new GenericClass(
                com.examples.with.different.packagename.generic.GuavaExample4.class);

        // Object bound
        Assert.assertTrue(iterableIntegerClass.satisfiesBoundaries(typeVariable));
        Assert.assertTrue(listOfIntegerClass.satisfiesBoundaries(typeVariable));

        // Iterable bound
        Assert.assertTrue(iterableIntegerClass.satisfiesBoundaries(iterableTypeVariable));
        Assert.assertTrue(listOfIntegerClass.satisfiesBoundaries(iterableTypeVariable));

    }

    @Test
    public void reloadArrayClass() {
        GenericClass arrayClass = new GenericClass(Object[].class);
        ClassLoader loader = new InstrumentingClassLoader();
        arrayClass.changeClassLoader(loader);
        Class<?> rawClass = arrayClass.getRawClass();
        Assert.assertTrue(rawClass.isArray());

    }

    @Test
    public void reloadNonArrayClass() {
        GenericClass arrayClass = new GenericClass(Integer.class);
        ClassLoader loader = new InstrumentingClassLoader();
        arrayClass.changeClassLoader(loader);
        Class<?> rawClass = arrayClass.getRawClass();
        Assert.assertFalse(rawClass.isArray());
    }

    @Test
    public void testWildcardInstantiation() throws ConstructionFailedException {

        GenericClass integerWildcardListClass = new GenericClass(
                new TypeToken<java.util.List<? extends Integer>>() {
                }.getType());

        GenericClass integerListClass = new GenericClass(new TypeToken<java.util.List<Integer>>() {
        }.getType());
        GenericClass objectListClass = new GenericClass(new TypeToken<java.util.List<Object>>() {
        }.getType());

        Assert.assertTrue(integerWildcardListClass.isAssignableFrom(integerListClass));
        Assert.assertFalse(integerWildcardListClass.isAssignableFrom(objectListClass));

        GenericClass integerWildcardListInstantiation = integerWildcardListClass.getGenericInstantiation();
        Assert.assertTrue(integerWildcardListClass.isAssignableFrom(integerWildcardListInstantiation));
    }

    @Test
    public void testWildcardWithSuperIntegerBoundaryInstantiation() throws ConstructionFailedException {

        GenericClass integerWildcardListClass = new GenericClass(new TypeToken<java.util.List<? super Integer>>() {
        }.getType());

        GenericClass integerListClass = new GenericClass(new TypeToken<java.util.List<Integer>>() {
        }.getType());
        GenericClass numberListClass = new GenericClass(new TypeToken<java.util.List<Number>>() {
        }.getType());
        GenericClass objectListClass = new GenericClass(new TypeToken<java.util.List<Object>>() {
        }.getType());

        Assert.assertTrue(integerWildcardListClass.isAssignableFrom(integerListClass));
        Assert.assertTrue(integerWildcardListClass.isAssignableFrom(numberListClass));
        Assert.assertTrue(integerWildcardListClass.isAssignableFrom(objectListClass));

        GenericClass integerWildcardListInstantiation = integerWildcardListClass.getGenericInstantiation();
        Assert.assertTrue(integerWildcardListClass.isAssignableFrom(integerWildcardListInstantiation));
    }

    @Test
    public void testWildcardWithSuperNumberBoundaryInstantiation() throws ConstructionFailedException {

        GenericClass numberWildcardListClass = new GenericClass(new TypeToken<java.util.List<? super Number>>() {
        }.getType());

        GenericClass integerListClass = new GenericClass(new TypeToken<java.util.List<Integer>>() {
        }.getType());
        GenericClass numberListClass = new GenericClass(new TypeToken<java.util.List<Number>>() {
        }.getType());
        GenericClass objectListClass = new GenericClass(new TypeToken<java.util.List<Object>>() {
        }.getType());

        Assert.assertFalse(numberWildcardListClass.isAssignableFrom(integerListClass));
        Assert.assertTrue(numberWildcardListClass.isAssignableFrom(numberListClass));
        Assert.assertTrue(numberWildcardListClass.isAssignableFrom(objectListClass));

        GenericClass integerWildcardListInstantiation = numberWildcardListClass.getGenericInstantiation();
        System.out.println(integerWildcardListInstantiation.toString());
        Assert.assertTrue(numberWildcardListClass.isAssignableFrom(integerWildcardListInstantiation));
    }

}