/**
* Copyright (C) 2010-2017 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.coverage.mutation;
import org.evosuite.Properties;
import org.evosuite.coverage.archive.TestsArchive;
import org.evosuite.testcase.ExecutableChromosome;
import org.evosuite.testcase.execution.ExecutionResult;
import org.evosuite.testsuite.AbstractTestSuiteChromosome;
import org.evosuite.testsuite.TestSuiteChromosome;
import java.util.*;
import java.util.Map.Entry;
/**
* <p>
* WeakMutationSuiteFitness class.
* </p>
*
* @author fraser
*/
public class WeakMutationSuiteFitness extends MutationSuiteFitness {
private static final long serialVersionUID = -1812256816400338180L;
/* (non-Javadoc)
* @see org.evosuite.ga.FitnessFunction#getFitness(org.evosuite.ga.Chromosome)
*/
/** {@inheritDoc} */
@Override
public double getFitness(
AbstractTestSuiteChromosome<? extends ExecutableChromosome> individual) {
/**
* e.g. classes with only static constructors
*/
if (mutationGoals.size() == 0) {
updateIndividual(this, individual, 0.0);
((TestSuiteChromosome) individual).setCoverage(this, 1.0);
((TestSuiteChromosome) individual).setNumOfCoveredGoals(this, 0);
return 0.0;
}
List<ExecutionResult> results = runTestSuite(individual);
// First objective: achieve branch coverage
logger.debug("Calculating branch fitness: ");
/*
* Note: results are cached, so the test suite is not executed again when we
* calculated the branch fitness
*/
double fitness = branchFitness.getFitness(individual);
Map<Integer, Double> mutant_distance = new HashMap<Integer, Double>();
Set<Integer> touchedMutants = new HashSet<Integer>(removedMutants);
for (ExecutionResult result : results) {
// Using private reflection can lead to false positives
// that represent unrealistic behaviour. Thus, we only
// use reflection for basic criteria, not for mutation
if(result.calledReflection())
continue;
touchedMutants.addAll(result.getTrace().getTouchedMutants());
for (Entry<Integer, Double> entry : result.getTrace().getMutationDistances().entrySet()) {
if(!mutants.contains(entry.getKey()) || removedMutants.contains(entry.getKey()))
continue;
if(entry.getValue() == 0.0) {
result.test.addCoveredGoal(mutantMap.get(entry.getKey()));
if(Properties.TEST_ARCHIVE) {
toRemoveMutants.add(entry.getKey());
TestsArchive.instance.putTest(this, mutantMap.get(entry.getKey()), result);
individual.isToBeUpdated(true);
}
}
if (!mutant_distance.containsKey(entry.getKey()))
mutant_distance.put(entry.getKey(), entry.getValue());
else {
mutant_distance.put(entry.getKey(),
Math.min(mutant_distance.get(entry.getKey()),
entry.getValue()));
}
}
}
// Second objective: touch all mutants?
fitness += MutationPool.getMutantCounter() - touchedMutants.size();
int covered = removedMutants.size();
for (Double distance : mutant_distance.values()) {
if (distance < 0) {
logger.warn("Distance is " + distance + " / " + Integer.MAX_VALUE + " / "
+ Integer.MIN_VALUE);
distance = 0.0; // FIXXME
}
fitness += normalize(distance);
if (distance == 0.0) {
covered++;
}
}
updateIndividual(this, individual, fitness);
((TestSuiteChromosome) individual).setCoverage(this, 1.0 * covered / mutationGoals.size());
((TestSuiteChromosome) individual).setNumOfCoveredGoals(this, covered);
return fitness;
}
}