/**
   * {@inheritDoc}
   *
   * <p>A different splitting point is selected for each individual
   */
  @Override
  public void crossOver(Chromosome parent1, Chromosome parent2) throws ConstructionFailedException {

    if (parent1.size() < 2 || parent2.size() < 2) {
      return;
    }
    // Choose a position in the middle
    int point1 = Randomness.nextInt(parent1.size() - 1) + 1;
    int point2 = Randomness.nextInt(parent2.size() - 1) + 1;

    Chromosome t1 = parent1.clone();
    Chromosome t2 = parent2.clone();

    parent1.crossOver(t2, point1, point2);
    parent2.crossOver(t1, point2, point1);
  }
 @Override
 public void randomize() {
   String url = Randomness.choice(tc.getAccessedEnvironment().getViewOfRemoteURLs());
   if (url != null) {
     setValue(new EvoSuiteURL(url));
   } else {
     setValue(null);
   }
 }
  public static GenericClass selectClass(List<GenericClass> candidates) {
    double r = Randomness.nextDouble();
    double d =
        Properties.RANK_BIAS
            - Math.sqrt(
                (Properties.RANK_BIAS * Properties.RANK_BIAS)
                    - (4.0 * (Properties.RANK_BIAS - 1.0) * r));
    int length = candidates.size();

    d = d / 2.0 / (Properties.RANK_BIAS - 1.0);

    int index = (int) (length * d);
    return candidates.get(index);
  }
  @Test
  public void testDSEMultiObjective() {

    Randomness.setSeed(1545420);

    // should it be trivial for DSE ?
    Properties.SEARCH_BUDGET = 20;
    Properties.TIMEOUT = Integer.MAX_VALUE;
    Properties.CONCOLIC_TIMEOUT = Integer.MAX_VALUE;
    Properties.LOCAL_SEARCH_RATE = 1;
    Properties.DSE_PROBABILITY = 1.0;
    //		Properties.LOCAL_SEARCH_BUDGET_TYPE = LocalSearchBudgetType.TIME;
    Properties.LOCAL_SEARCH_BUDGET_TYPE = LocalSearchBudgetType.TESTS;
    Properties.LOCAL_SEARCH_BUDGET = 5;
    Properties.CRITERION =
        new Criterion[] {
          Criterion.LINE,
          Criterion.BRANCH,
          Criterion.EXCEPTION,
          Criterion.WEAKMUTATION,
          Criterion.OUTPUT,
          Criterion.METHOD
        };
    Properties.STOPPING_CONDITION = StoppingCondition.MAXTIME;

    EvoSuite evosuite = new EvoSuite();
    String targetClass = DseBar.class.getCanonicalName();
    Properties.TARGET_CLASS = targetClass;

    Properties.DSE_PROBABILITY = 1.0; // force using only DSE, no LS

    String[] command = new String[] {"-generateSuite", "-class", targetClass};

    Object result = evosuite.parseCommandLine(command);
    GeneticAlgorithm<?> ga = getGAFromResult(result);
    TestSuiteChromosome best = (TestSuiteChromosome) ga.getBestIndividual();
    System.out.println("EvolvedTestSuite:\n" + best);
  }
  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;
  }
  private void minimizeAssertions(
      StructuredTestCase test,
      ExecutionResult origResult,
      Map<Mutation, ExecutionResult> mutationResults) {
    Set<Integer> killedMutants = new HashSet<Integer>();

    for (int position = test.size() - 1; position >= test.getFirstExerciseStatement(); position--) {
      Statement statement = test.getStatement(position);
      if (!statement.hasAssertions()) continue;

      List<Assertion> assertions = new ArrayList<Assertion>(statement.getAssertions());
      Map<Integer, Set<Integer>> killMap = getKillMap(assertions, mutationResults);
      int num = 0;

      // This is to make sure we prefer assertions on return values.
      // TODO: Refactor
      for (Assertion assertion : assertions) {
        if (assertion instanceof PrimitiveAssertion) {
          boolean killsNew = false;
          for (Integer mutationId : killMap.get(num)) {
            if (!killedMutants.contains(mutationId)) {
              killsNew = true;
              break;
            }
          }
          if (!killsNew) {
            statement.removeAssertion(assertion);
          } else {
            killedMutants.addAll(killMap.get(num));
          }
        }
        num++;
      }

      for (int i = 0; i < assertions.size(); i++) {
        if (!killMap.containsKey(i)) {
          statement.removeAssertion(assertions.get(i));
          continue;
        }
        Assertion assertion = assertions.get(i);
        boolean killsNew = false;
        for (Integer mutationId : killMap.get(i)) {
          if (!killedMutants.contains(mutationId)) {
            killsNew = true;
            break;
          }
        }
        if (!killsNew) {
          statement.removeAssertion(assertion);
        } else {
          killedMutants.addAll(killMap.get(i));
        }
      }

      // If we have no assertions, then add...something?
      if (!statement.hasAssertions()) {
        boolean addedPrimitive = false;
        for (Assertion assertion : assertions) {
          if (assertion instanceof PrimitiveAssertion) {
            statement.addAssertion(assertion);
            addedPrimitive = true;
          }
        }
        if (!addedPrimitive) statement.addAssertion(Randomness.choice(assertions));
      }
    }
  }