public void addCastClass(GenericClass clazz, int depth) {
    if (clazz.getRawClass() == null) {
      logger.warn("ADDING NULL!");
      assert (false);
    }
    if (clazz.isAbstract()) {
      for (Class<?> concreteClass :
          ConcreteClassAnalyzer.getConcreteClasses(
              clazz.getRawClass(), TestCluster.getInheritanceTree())) {
        GenericClass c = new GenericClass(concreteClass);
        if (TestUsageChecker.canUse(c.getRawClass())) {
          classMap.put(c, depth);
        }
      }

      if (Properties.P_FUNCTIONAL_MOCKING > 0.0) {
        if (TestUsageChecker.canUse(clazz.getRawClass())) classMap.put(clazz, depth);
      }

    } else {
      if (TestUsageChecker.canUse(clazz.getRawClass())) classMap.put(clazz, depth);
    }
  }
  private boolean addAssignableClass(
      TypeVariable<?> typeVariable, Map<TypeVariable<?>, Type> typeMap) {
    Set<Class<?>> classes = TestCluster.getInstance().getAnalyzedClasses();
    Set<Class<?>> assignableClasses = new LinkedHashSet<Class<?>>();

    for (Class<?> clazz : classes) {
      if (!TestUsageChecker.canUse(clazz)) continue;

      GenericClass genericClass = new GenericClass(clazz).getWithWildcardTypes();

      if (!genericClass.satisfiesBoundaries(typeVariable, typeMap)) {
        logger.debug("Not assignable: " + clazz);
      } else {
        logger.debug("Assignable");
        assignableClasses.add(clazz);
      }
    }
    for (Type t : typeMap.values()) {
      if (t instanceof WildcardType) continue; // TODO: For now.

      Class<?> clazz = GenericTypeReflector.erase(t);
      if (!TestUsageChecker.canUse(GenericTypeReflector.erase(clazz))) continue;

      GenericClass genericClass = new GenericClass(clazz).getWithWildcardTypes();
      if (!genericClass.satisfiesBoundaries(typeVariable, typeMap)) {
        logger.debug("Not assignable: " + clazz);
      } else {
        logger.debug("Assignable");
        assignableClasses.add(clazz);
      }
    }
    /*
    for (Type t : typeVariable.getBounds()) {
    	if (typeMap.containsKey(t))
    		t = typeMap.get(t);

    	Class<?> clazz = GenericTypeReflector.erase(t);
    	logger.debug("Checking bound: " + t);

    	if (!TestClusterGenerator.canUse(clazz))
    		continue;

    	GenericClass genericClass = new GenericClass(t);
    	//if (genericClass.hasTypeVariables()) {
    	logger.debug("Has type variables: " + genericClass
    	        + ", checking wildcard version with type map " + typeMap);
    	GenericClass wildcardClass = genericClass.getWithWildcardTypes();
    	//if (!wildcardClass.satisfiesBoundaries(typeVariable, typeMap)) {
    	//	logger.debug("Not assignable: " + clazz);
    	//} else {
    	//	logger.debug("Assignable");
    	assignableClasses.add(clazz);
    	//}
    	//} else {
    	//	logger.debug("Adding directly: " + genericClass);
    	//	assignableClasses.add(genericClass.getRawClass());
    	//	classMap.put(genericClass, 10);
    	//}
    }
    */
    logger.debug(
        "Found assignable classes for type variable "
            + typeVariable
            + ": "
            + assignableClasses.size());
    if (!assignableClasses.isEmpty()) {
      Class<?> clazz = Randomness.choice(assignableClasses);
      GenericClass castClass = new GenericClass(clazz);
      logger.debug("Adding cast class " + castClass);
      classMap.put(castClass, 10);
      return true;
    } else {
      InheritanceTree inheritanceTree = DependencyAnalysis.getInheritanceTree();
      Set<Class<?>> boundCandidates = new LinkedHashSet<Class<?>>();
      for (Type bound : typeVariable.getBounds()) {
        Class<?> rawBound = GenericTypeReflector.erase(bound);
        boundCandidates.add(rawBound);
        logger.debug("Getting concrete classes for " + rawBound);
        boundCandidates.addAll(ConcreteClassAnalyzer.getConcreteClasses(rawBound, inheritanceTree));
      }
      for (Class<?> clazz : boundCandidates) {
        if (!TestUsageChecker.canUse(clazz)) continue;

        boolean isAssignable = true;
        for (Type bound : typeVariable.getBounds()) {
          if (GenericTypeReflector.erase(bound).equals(Enum.class)) {
            if (clazz.isEnum()) continue;
          }

          if (!GenericClass.isAssignable(bound, clazz)) {
            isAssignable = false;
            logger.debug("Not assignable: " + clazz + " to bound " + bound);
            break;
          }
          if (bound instanceof ParameterizedType) {
            if (Arrays.asList(((ParameterizedType) bound).getActualTypeArguments())
                .contains(typeVariable)) {
              isAssignable = false;
              break;
            }
          }
        }
        if (isAssignable) {
          assignableClasses.add(clazz);
        }
      }
      logger.debug(
          "After adding bounds, found "
              + assignableClasses.size()
              + " assignable classes for type variable "
              + typeVariable
              + ": "
              + assignableClasses);
      if (!assignableClasses.isEmpty()) {
        // TODO: Add all classes?
        //				for(Class<?> clazz : assignableClasses) {
        //					GenericClass castClass = new GenericClass(clazz);
        //					logger.debug("Adding cast class " + castClass);
        //					classMap.put(castClass, 10);
        //				}
        Class<?> clazz = Randomness.choice(assignableClasses);
        GenericClass castClass = new GenericClass(clazz);
        logger.debug("Adding cast class " + castClass);
        classMap.put(castClass, 10);
        return true;
      }
    }

    return false;
  }
  private boolean addAssignableClass(
      WildcardType wildcardType, Map<TypeVariable<?>, Type> typeMap) {
    Set<Class<?>> classes = TestCluster.getInstance().getAnalyzedClasses();
    Set<Class<?>> assignableClasses = new LinkedHashSet<Class<?>>();

    for (Class<?> clazz : classes) {
      if (!TestUsageChecker.canUse(clazz)) continue;

      GenericClass genericClass = new GenericClass(clazz).getWithWildcardTypes();
      if (!genericClass.satisfiesBoundaries(wildcardType, typeMap)) {
        logger.debug("Not assignable: " + clazz);
      } else {
        logger.debug("Assignable");
        assignableClasses.add(clazz);
      }
    }
    for (Type t : typeMap.values()) {
      if (t instanceof WildcardType) continue; // TODO: For now.

      Class<?> clazz = GenericTypeReflector.erase(t);
      if (!TestUsageChecker.canUse(GenericTypeReflector.erase(clazz))) continue;

      GenericClass genericClass = new GenericClass(clazz).getWithWildcardTypes();
      if (!genericClass.satisfiesBoundaries(wildcardType, typeMap)) {
        logger.debug("Not assignable: " + clazz);
      } else {
        logger.debug("Assignable");
        assignableClasses.add(clazz);
      }
    }
    for (Type t : wildcardType.getUpperBounds()) {
      if (typeMap.containsKey(t)) t = typeMap.get(t);

      Class<?> clazz = GenericTypeReflector.erase(t);
      logger.debug("Checking bound: " + t);

      if (!TestUsageChecker.canUse(clazz)) continue;

      GenericClass genericClass = new GenericClass(t);
      if (genericClass.hasTypeVariables()) {
        logger.debug("Has type variables: " + genericClass);
        GenericClass wildcardClass = genericClass.getWithWildcardTypes();
        if (!wildcardClass.satisfiesBoundaries(wildcardType, typeMap)) {
          logger.debug("Not assignable: " + clazz);
        } else {
          logger.debug("Assignable");
          assignableClasses.add(clazz);
        }
      } else {
        logger.debug("Adding directly: " + genericClass);
        assignableClasses.add(genericClass.getRawClass());
        classMap.put(genericClass, 10);
      }
    }
    logger.debug(
        "Found assignable classes for wildcardtype "
            + wildcardType
            + ": "
            + assignableClasses.size());
    if (!assignableClasses.isEmpty()) {
      Class<?> clazz = Randomness.choice(assignableClasses);
      GenericClass castClass = new GenericClass(clazz);
      logger.debug("Adding cast class " + castClass);
      classMap.put(castClass, 10);
      return true;
    }

    return false;
  }
  @Test
  public void testTwoInts()
      throws NoSuchMethodException, SecurityException, ClassNotFoundException,
          ConstructionFailedException {
    Properties.TARGET_CLASS = IntExampleWithNoElse.class.getCanonicalName();
    TestChromosome test1 = new TestChromosome();
    test1.setTestCase(getTwoIntTest(1, 22, 22, 22));
    TestChromosome test2 = new TestChromosome();
    test2.setTestCase(getTwoIntTest(-23423423, 234234234, -23423423, 234234234));
    TestChromosome test3 = new TestChromosome();
    test3.setTestCase(getTwoIntTest(0, 0, 0, 0));

    TestSuiteChromosome suite = new TestSuiteChromosome();
    BranchCoverageSuiteFitness fitness = new BranchCoverageSuiteFitness();

    assertEquals(6.0, fitness.getFitness(suite), 0.0F);
    suite.addTest(test1);
    assertEquals(2.0, fitness.getFitness(suite), 0.0F);
    suite.addTest(test2);
    suite.addTest(test3);

    Class<?> sut =
        TestGenerationContext.getInstance()
            .getClassLoaderForSUT()
            .loadClass(Properties.TARGET_CLASS);
    Method m = sut.getMethod("testMe", new Class<?>[] {int.class, int.class});
    GenericMethod method = new GenericMethod(m, sut);

    TestCluster.getInstance().addTestCall(method);

    Properties.P_TEST_CHANGE = 0.0;
    Properties.P_TEST_DELETE = 1.0;
    Properties.P_TEST_INSERT = 0.0;

    double oldFitness = fitness.getFitness(suite);
    int notChanged = 0;
    System.out.println("Original: " + test1);
    for (int i = 0; i < 100; i++) {
      TestChromosome testNew = (TestChromosome) test1.clone();
      testNew.mutate();
      if (testNew.isChanged()) {
        System.out.println("Trying: " + testNew);
        suite.deleteTest(test1);
        suite.addTest(testNew);
        double newFitness = fitness.getFitness(suite);
        if (newFitness < oldFitness) {
          test1 = testNew;
          oldFitness = newFitness;
          if (newFitness == 0.0) {
            System.out.println("Iterations: " + i);
            System.out.println("Not changed: " + notChanged);
            break;
          }
        } else {
          suite.deleteTest(testNew);
          suite.addTest(test1);
          fitness.getFitness(suite);
        }
      } else {
        notChanged++;
      }
    }

    System.out.println("Fitness: " + fitness.getFitness(suite));
    System.out.println("Test suite: " + suite);
    assertEquals(0.0, fitness.getFitness(suite), 0.1F);
  }
  @Test
  public void testSimpleInt()
      throws NoSuchMethodException, SecurityException, ClassNotFoundException,
          ConstructionFailedException {
    Properties.TARGET_CLASS = TrivialInt.class.getCanonicalName();
    TestChromosome test1 = new TestChromosome();
    test1.setTestCase(getIntTest(2938, -1000000));
    TestChromosome test2 = (TestChromosome) test1.clone();

    TestSuiteChromosome suite = new TestSuiteChromosome();
    BranchCoverageSuiteFitness fitness = new BranchCoverageSuiteFitness();

    assertEquals(4.0, fitness.getFitness(suite), 0.0F);
    suite.addTest(test1);
    assertEquals(1.0, fitness.getFitness(suite), 0.0F);
    suite.addTest(test2);
    assertEquals(1.0, fitness.getFitness(suite), 0.01F); // 0.99...

    Class<?> sut =
        TestGenerationContext.getInstance()
            .getClassLoaderForSUT()
            .loadClass(Properties.TARGET_CLASS);
    Method m = sut.getMethod("testMe", new Class<?>[] {int.class});
    GenericMethod method = new GenericMethod(m, sut);

    TestCluster.getInstance().addTestCall(method);

    Properties.P_TEST_CHANGE = 0.0;
    Properties.P_TEST_DELETE = 1.0;
    Properties.P_TEST_INSERT = 0.0;

    double oldFitness = suite.getFitness();
    int notChanged = 0;
    for (int i = 0; i < 100; i++) {
      TestChromosome testNew = (TestChromosome) test1.clone();
      testNew.mutate();
      if (testNew.isChanged()) {
        suite.deleteTest(test1);
        suite.addTest(testNew);
        System.out.println(testNew.getTestCase().toCode());
        double newFitness = fitness.getFitness(suite);
        if (newFitness < oldFitness) {
          System.out.println("Improved: " + newFitness);
          test1 = testNew;
          oldFitness = newFitness;
          System.out.println(
              ""
                  + i
                  + ":"
                  + ((IntPrimitiveStatement) test1.getTestCase().getStatement(1)).getValue());
          if (newFitness == 0.0) {
            System.out.println("Iterations: " + i);
            System.out.println("Not changed: " + notChanged);
            break;
          }
        } else {
          System.out.println("Not improved: " + newFitness);
          suite.deleteTest(testNew);
          suite.addTest(test1);
          fitness.getFitness(suite);
        }
      } else {
        notChanged++;
      }
    }

    System.out.println("Fitness: " + fitness.getFitness(suite));
    System.out.println("Test suite: " + suite);
    assertEquals(0.0, fitness.getFitness(suite), 0.1F);
  }