/**
* 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.eclipse.replace;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.evosuite.coverage.TestFitnessFactory;
import org.evosuite.testcase.TestCase;
import org.evosuite.testcase.TestCaseMinimizer;
import org.evosuite.testcase.TestChromosome;
import org.evosuite.testcase.TestCodeVisitor;
import org.evosuite.testcase.TestFitnessFunction;
import org.evosuite.testcase.execution.ExecutionResult;
/**
* This class is the fitness function, which calculates for a given test
* chromosome how different it is to the test case we are trying to replace
*
*/
public class DifferenceFitnessFunction extends TestFitnessFunction {
private static final long serialVersionUID = -7316773344809958156L;
/** The test we want to replace */
private final TestCase originalTest;
/** Set of coverage objectives satisfied by the test we want to replace */
private final Set<TestFitnessFunction> originalCoveredGoals = new HashSet<TestFitnessFunction>();
/** Set of coverage objectives not satisfied by the test we want to replace */
private final Set<TestFitnessFunction> originalUncoveredGoals = new HashSet<TestFitnessFunction>();
//private Set<Integer> distanceRecord=new HashSet<Integer>();
//private Set<String> stringRecord=new HashSet<String>();
private final HashMap distanceRecord = new HashMap();
private final HashMap stringRecord = new HashMap();
private final int count = 0;
private HashMap replaceTokenRecord = new HashMap(); //.get(key)
private HashMap replaceTypeRecord = new HashMap();
private HashMap originalTokenRecord = new HashMap(); //.get(key)
private HashMap originalTypeRecord = new HashMap();
private int loopNo = 0;
private NWAlgo nw;
/**
* Constructor to initialize the test we want to replace
*
* @param originalTest
*/
public DifferenceFitnessFunction(TestCase originalTest, List<TestCase> otherTests,
TestFitnessFactory factory) { //step 1
this.originalTest = originalTest;
determineOriginalGoals(factory, otherTests);
System.out.println("Original test covers " + originalCoveredGoals.size()
+ " goals");
}
/**
* @return the originalTest
*/
public TestCase getOriginalTest() {
return originalTest;
}
/**
* Iterate over all coverage goals (e.g. branches) and determine which of
* these are covered only by the original test case
*
* @param factory
*/
private void determineOriginalGoals(TestFitnessFactory factory,
List<TestCase> otherTests) { //step 2
List<TestFitnessFunction> goals = factory.getCoverageGoals();
for (TestFitnessFunction goal : goals) {
if (goal.isCovered(originalTest)) {
if (!goal.isCovered(otherTests)) {
// This is a goal that is uniquely covered only by the target test
originalCoveredGoals.add(goal);
System.out.println("Uniquely covered goal: " + goal);
}
} else {
originalUncoveredGoals.add(goal);
}
}
}
/**
* Return the set of goals the original test covered uniquely
*
* @return
*/
public Set<TestFitnessFunction> getOriginalGoals() { //enter by TestCaseReplacer
return originalCoveredGoals;
}
/**
* Determine how close we are in terms of covering the same goals as the
* original test case
*
* @param individual
* @return
*/
private double getCoverage(TestChromosome individual) {
double similarity = 0.0;
for (TestFitnessFunction coverageGoal : originalCoveredGoals) {
similarity += coverageGoal.getFitness(individual);
// similarity += 1 - normalize(coverageGoal.getFitness(individual));
}
return similarity;
}
/**
* Determine the syntactic distance between the string representation of two
* test cases.
*
*
* @param individual
* @return
*/
private double getSyntacticSimilarity(TestChromosome individual) {
// The method toCode converts a test case to its JUnit representation
String originalString = originalTest.toCode();
//System.out.println("\n orgString: "+ originalString);
// The length of test cases varies during the search
// therefore the comparison needs to be on a test case
// where we have removed all the irrelevant statements
TestCaseMinimizer minimizer = new TestCaseMinimizer(originalCoveredGoals);
TestChromosome copy = (TestChromosome) individual.clone();
minimizer.minimize(copy);
TestCodeVisitor visitor = new TestCodeVisitor();
copy.getTestCase().accept(visitor);
TestCodeVisitor workaroundVisitor = new TestCodeVisitor();
originalTest.accept(workaroundVisitor); // <-- new add, replace = original
Set<String> varNames = new HashSet<String>(visitor.getVariableNames());
varNames.addAll(workaroundVisitor.getVariableNames());
Set<String> classNames = new HashSet<String>(visitor.getClassNames());
classNames.addAll(workaroundVisitor.getClassNames());
String newString = visitor.getCode(); //System.out.println(newString);
//System.out.println(classNames +"var: " +varNames );
//String newString = copy.getTestCase().toCode();
// TODO: Now we need to calculate the syntactic difference
// by comparing originalString and newString
//start
//getCollection(individual,copy,minimizer ); //mine
//end
if (!newString.isEmpty()) {
if (loopNo == 0) {
TokenSlicer ts1 = new TokenSlicer(originalString, varNames, classNames);
originalTokenRecord = ts1.getTokenRecord();
originalTypeRecord = ts1.getTypeRecord();
loopNo++;
}
TokenSlicer ts2 = new TokenSlicer(newString, varNames, classNames);
replaceTokenRecord = ts2.getTokenRecord();
replaceTypeRecord = ts2.getTypeRecord();
/*
System.out.println("\noriginal:");
for(int i=0; i<=originalTokenRecord.size();i++){
System.out.print(originalTokenRecord.get(i)+ " ");
}
System.out.println("\n"+originalTokenRecord +"\n replace: ");
for(int i=0; i<=replaceTypeRecord.size();i++){
System.out.print(replaceTypeRecord.get(i)+ " ");
}*/
//System.out.println("\nreplaced test token:\n "+replaceTokenRecord);
//System.out.println("replaced test type: \n"+replaceTypeRecord);
//System.out.println("replaced test case: "+newString);
nw = new NWAlgo(originalTokenRecord, replaceTokenRecord, originalTypeRecord,
replaceTypeRecord);
double nwDistance = nw.getDistance();
return nwDistance;
}//notEmpty
return originalString.length() + 10;
}
/**
* This method calculates the actual fitness value for a given individual
*/
@Override
public double getFitness(TestChromosome individual, ExecutionResult result) {
double fitness = 0.0;
// TODO: Calculate the fitness value
// The following are just examples
// We will want to make sure that the new test case executes
// the same code as the original test case. We can achieve this
// by checking if it satisfies the same coverage goals.
double coverage = getCoverage(individual);
// The test case should look as different as possible to the
// last test case, therefore we want to maximize syntactic
// distance
double similarity = getSyntacticSimilarity(individual); //hv to find the biggest un-similar
// Now we need to combine the measures somehow to a fitness value
fitness = coverage + (1.0 - normalize(Math.abs(similarity)));
// fitness = coverage > 0 ? 1/coverage : 1 + similarity;
// fitness = 1000 * (1/(coverage+1)) + similarity;
// ...
//System.out.println("Fitness: " + fitness);
//System.out.println("\n\n---------------");
updateIndividual(this, individual, fitness);
return fitness;
}
/* (non-Javadoc)
* @see org.evosuite.testcase.TestFitnessFunction#isMaximizationFunction()
*/
@Override
public boolean isMaximizationFunction() {
// If the optimal fitness value is 0, then this needs to be set to true
return false;
}
@Override
public int compareTo(TestFitnessFunction arg0) {
return 0;
}
@Override
public String getTargetClass() {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see org.evosuite.testcase.TestFitnessFunction#getTargetMethod()
*/
@Override
public String getTargetMethod() {
// TODO Auto-generated method stub
return null;
}
}