/** * 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.lcsaj; import org.evosuite.Properties; import org.evosuite.TestGenerationContext; import org.evosuite.Properties.Strategy; import org.evosuite.coverage.branch.BranchCoverageGoal; import org.evosuite.coverage.branch.BranchCoverageTestFitness; import org.evosuite.coverage.branch.BranchPool; import org.evosuite.testcase.ExecutionResult; import org.evosuite.testcase.MethodCall; import org.evosuite.testcase.TestChromosome; import org.evosuite.testcase.TestFitnessFunction; /** * Evaluate fitness of a single test case with respect to a single LCSAJ */ public class LCSAJCoverageTestFitness extends TestFitnessFunction { private static final long serialVersionUID = 1L; LCSAJ lcsaj; private final int lcsaj_finalBranchID; private double approach; /** * <p> * Constructor for LCSAJCoverageTestFitness. * </p> * * @param className * a {@link java.lang.String} object. * @param methodName * a {@link java.lang.String} object. * @param lcsaj * a {@link org.evosuite.coverage.lcsaj.LCSAJ} object. */ public LCSAJCoverageTestFitness(String className, String methodName, LCSAJ lcsaj) { this.lcsaj = lcsaj; lcsaj_finalBranchID = lcsaj.getBranchID(lcsaj.length() - 1); } /** * <p> * Constructor for LCSAJCoverageTestFitness. * </p> * * @param lcsaj * a {@link org.evosuite.coverage.lcsaj.LCSAJ} object. */ public LCSAJCoverageTestFitness(LCSAJ lcsaj) { this.lcsaj = lcsaj; lcsaj_finalBranchID = lcsaj.getBranchID(lcsaj.length() - 1); } /* * (non-Javadoc) * * @see * org.evosuite.testcase.TestFitnessFunction#getFitness(de.unisb * .cs.st.evosuite.testcase.TestChromosome, * org.evosuite.testcase.ExecutionResult) */ /** {@inheritDoc} */ @Override public double getFitness(TestChromosome individual, ExecutionResult result) { approach = lcsaj.length(); double savedFitness = approach; logger.debug("Evaluating fitness for " + lcsaj); // for all method calls: for (MethodCall call : result.getTrace().getMethodCalls()) { double currentFitness = approach; // if method call is the method of the LCSAJ if (call.className.equals(lcsaj.getClassName()) && call.methodName.equals(lcsaj.getMethodName())) { int lcsaj_position = 0; boolean found = false; logger.debug("New call: " + call.className + "." + call.methodName + " " + call.branchTrace.size()); // For each branch that was passed in this call for (int i = 0; i < call.branchTrace.size(); i++) { int actualBranch = call.branchTrace.get(i); int lcsaj_branchID = lcsaj.getBranchID(lcsaj_position); double false_distance = call.falseDistanceTrace.get(i); double true_distance = call.trueDistanceTrace.get(i); logger.debug("Current branch: " + call.branchTrace.get(i) + ": " + true_distance + "/" + false_distance + ", need " + lcsaj.getBranchID(lcsaj_position)); if (actualBranch == lcsaj_branchID) { if (lcsaj_position == 0) found = true; currentFitness -= 1.0; if (actualBranch == lcsaj_finalBranchID) { currentFitness += normalize(true_distance); if (currentFitness < savedFitness) { savedFitness = currentFitness; } if (lcsaj_position > lcsaj.getdPositionReached()) lcsaj.setPositionReached(lcsaj_position); lcsaj_position = 0; currentFitness = approach; continue; } else if (false_distance > 0) { logger.debug("Took a wrong turn with false distance " + false_distance); currentFitness += normalize(false_distance); if (currentFitness < savedFitness) savedFitness = currentFitness; if (lcsaj_position > lcsaj.getdPositionReached()) lcsaj.setPositionReached(lcsaj_position); lcsaj_position = 0; currentFitness = approach; continue; } lcsaj_position++; logger.debug("LCSAJ position: " + lcsaj_position); } else { if (LCSAJPool.isLCSAJBranch(BranchPool.getInstance(TestGenerationContext.getInstance().getClassLoaderForSUT()).getBranch(actualBranch))) { // logger.debug("Skipping pseudo branch"); continue; } if (lcsaj_position > lcsaj.getdPositionReached()) lcsaj.setPositionReached(lcsaj_position); lcsaj_position = 0; currentFitness = approach; } //} } if (Properties.STRATEGY != Strategy.EVOSUITE) { if (!found) { logger.debug("Looking for approach to initial branch: " + lcsaj.getStartBranch() + " with ID " + lcsaj.getStartBranch().getActualBranchId()); BranchCoverageGoal goal = new BranchCoverageGoal( lcsaj.getStartBranch(), true, lcsaj.getClassName(), lcsaj.getMethodName()); BranchCoverageTestFitness dependentFitness = new BranchCoverageTestFitness( goal); assert (currentFitness == approach); currentFitness += dependentFitness.getFitness(individual, result); if (currentFitness < savedFitness) savedFitness = currentFitness; //logger.debug("Initial branch has distance: " // + dependentFitness.getFitness(individual, result)); //logger.debug("Dependencies of initial branch: "); //for (Branch branch : lcsaj.getStartBranch().getAllControlDependentBranches()) { // logger.debug(branch); // } logger.debug("Resulting fitness: " + savedFitness); } else { logger.debug("Call does not match: " + call.className + "." + call.methodName + " " + call.branchTrace.size()); } } } } updateIndividual(this, individual, savedFitness); return savedFitness; } /** {@inheritDoc} */ @Override public String toString() { return lcsaj.toString(); } /* (non-Javadoc) * @see org.evosuite.testcase.TestFitnessFunction#compareTo(org.evosuite.testcase.TestFitnessFunction) */ @Override public int compareTo(TestFitnessFunction other) { if (other instanceof LCSAJCoverageTestFitness) { return lcsaj.compareTo(((LCSAJCoverageTestFitness) other).getLcsaj()); } return 0; } /** * <p> * Getter for the field <code>lcsaj</code>. * </p> * * @return a {@link org.evosuite.coverage.lcsaj.LCSAJ} object. */ public LCSAJ getLcsaj() { return this.lcsaj; } /* (non-Javadoc) * @see org.evosuite.testcase.TestFitnessFunction#getTargetClass() */ @Override public String getTargetClass() { return lcsaj.getClassName(); } /* (non-Javadoc) * @see org.evosuite.testcase.TestFitnessFunction#getTargetMethod() */ @Override public String getTargetMethod() { return lcsaj.getMethodName(); } }