All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.evosuite.coverage.exception.ExceptionCoverageSuiteFitness Maven / Gradle / Ivy

/**
 * Copyright (C) 2010-2018 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 .
 */
package org.evosuite.coverage.exception;

import org.evosuite.Properties;
import org.evosuite.coverage.MethodNameMatcher;
import org.evosuite.ga.archive.Archive;
import org.evosuite.testcase.ExecutableChromosome;
import org.evosuite.testcase.TestChromosome;
import org.evosuite.testcase.execution.ExecutionResult;
import org.evosuite.testsuite.AbstractTestSuiteChromosome;
import org.evosuite.testsuite.TestSuiteFitnessFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * Exception fitness is different from the others, as we do not know a priori how
 * many exceptions could be thrown in the SUT. In other words, we cannot really
 * speak about coverage percentage here
 */
public class ExceptionCoverageSuiteFitness extends TestSuiteFitnessFunction {

	private static final long serialVersionUID = 1565793073526627496L;

	private static Logger logger = LoggerFactory.getLogger(ExceptionCoverageSuiteFitness.class);

    private static int maxExceptionsCovered = 0;

	public ExceptionCoverageSuiteFitness() {
	}
	
    public static int getMaxExceptionsCovered() {
        return maxExceptionsCovered;
    }

	@Override
	public double getFitness(
	        AbstractTestSuiteChromosome suite) {
		logger.trace("Calculating exception fitness");


		/*
		 * for each method in the SUT, we keep track of which kind of exceptions were thrown.
		 * we distinguish between "implicit", "explicit" and "declared"
		 */
		Map>> implicitTypesOfExceptions = new HashMap<>();
        Map>> explicitTypesOfExceptions = new HashMap<>();
        Map>> declaredTypesOfExceptions = new HashMap<>();

		List results = runTestSuite(suite);

		calculateExceptionInfo(results,implicitTypesOfExceptions,explicitTypesOfExceptions,declaredTypesOfExceptions, this);
		
		if(Properties.TEST_ARCHIVE) {
			// If we are using the archive, then fitness is by definition 0
			// as all assertions already covered are in the archive
			suite.setFitness(this,  0.0);
			suite.setCoverage(this, 1.0);
			maxExceptionsCovered = ExceptionCoverageFactory.getGoals().size();
			return 0.0;
		}
		
		int nExc = getNumExceptions(implicitTypesOfExceptions) + getNumExceptions(explicitTypesOfExceptions) +
                getNumExceptions(declaredTypesOfExceptions);

        if (nExc > maxExceptionsCovered) {
            logger.info("(Exceptions) Best individual covers " + nExc + " exceptions");
            maxExceptionsCovered = nExc;
        }

        // We cannot set a coverage here, as it does not make any sense
       	// suite.setCoverage(this, 1.0);

		double exceptionFitness = 1d / (1d + nExc);

        suite.setFitness(this, exceptionFitness);
        if(maxExceptionsCovered > 0)
        	suite.setCoverage(this, nExc / maxExceptionsCovered);
        else
        	suite.setCoverage(this, 1.0);
        
        return exceptionFitness;
	}

	
	
	/**
	 * Given the list of results, fill the 3 given (empty) maps with exception information.
	 * Also, add exception coverage goals to mapping in {@link ExceptionCoverageFactory}
	 * 
	 * @param results
	 * @param implicitTypesOfExceptions
	 * @param explicitTypesOfExceptions
     * @param declaredTypesOfExceptions
	 * @throws IllegalArgumentException
	 */
	public static void calculateExceptionInfo(List results, 
			Map>> implicitTypesOfExceptions, Map>> explicitTypesOfExceptions,
            Map>> declaredTypesOfExceptions, ExceptionCoverageSuiteFitness contextFitness)
		throws IllegalArgumentException{

		MethodNameMatcher matcher = new MethodNameMatcher();

		if(results==null || implicitTypesOfExceptions==null || explicitTypesOfExceptions==null ||
				!implicitTypesOfExceptions.isEmpty() || !explicitTypesOfExceptions.isEmpty() ||
                declaredTypesOfExceptions==null || !declaredTypesOfExceptions.isEmpty()){
			throw new IllegalArgumentException();
		}

		// for each test case
		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 exception
			if (result.hasTimeout() || result.hasTestException() || result.noThrownExceptions() || result.calledReflection()) {
				continue;
			}

			TestChromosome test = new TestChromosome();
			test.setTestCase(result.test);
			test.setLastExecutionResult(result);
			test.setChanged(false);

			//iterate on the indexes of the statements that resulted in an exception
			for (Integer i : result.getPositionsWhereExceptionsWereThrown()) {
				if(ExceptionCoverageHelper.shouldSkip(result,i)){
					continue;
				}

				Class exceptionClass = ExceptionCoverageHelper.getExceptionClass(result,i);
				String methodIdentifier = ExceptionCoverageHelper.getMethodIdentifier(result, i); //eg name+descriptor
				if (!matcher.methodMatches(methodIdentifier)) {
					logger.info("Method {} does not match criteria. ",methodIdentifier);
					continue;
				}
				boolean sutException = ExceptionCoverageHelper.isSutException(result,i); // was the exception originated by a direct call on the SUT?

				/*
				 * We only consider exceptions that were thrown by calling directly the SUT (not the other
				 * used libraries). However, this would ignore cases in which the SUT is indirectly tested
				 * through another class
				 */

				if (sutException) {

					boolean notDeclared = ! ExceptionCoverageHelper.isDeclared(result,i);

                    if(notDeclared) {
                        /*
					     * we need to distinguish whether it is explicit (ie "throw" in the code, eg for validating
					     * input for pre-condition) or implicit ("likely" a real fault).
					     */

                        boolean isExplicit = ExceptionCoverageHelper.isExplicit(result,i);

                        if (isExplicit) {

                            if (!explicitTypesOfExceptions.containsKey(methodIdentifier)) {
                                explicitTypesOfExceptions.put(methodIdentifier, new HashSet>());
                            }
                            explicitTypesOfExceptions.get(methodIdentifier).add(exceptionClass);
                        } else {

                            if (!implicitTypesOfExceptions.containsKey(methodIdentifier)) {
                                implicitTypesOfExceptions.put(methodIdentifier, new HashSet>());
                            }
                            implicitTypesOfExceptions.get(methodIdentifier).add(exceptionClass);
                        }
                    } else {
                        if (!declaredTypesOfExceptions.containsKey(methodIdentifier)) {
                            declaredTypesOfExceptions.put(methodIdentifier, new HashSet>());
                        }
                        declaredTypesOfExceptions.get(methodIdentifier).add(exceptionClass);
                    }


					ExceptionCoverageTestFitness.ExceptionType type = ExceptionCoverageHelper.getType(result,i);
                    /*
                     * Add goal to ExceptionCoverageFactory
                     */
                    ExceptionCoverageTestFitness goal = new ExceptionCoverageTestFitness(Properties.TARGET_CLASS, methodIdentifier, exceptionClass, type);
                    String key = goal.getKey();
                    if(!ExceptionCoverageFactory.getGoals().containsKey(key)) {
                    	ExceptionCoverageFactory.getGoals().put(key, goal);
                    	test.getTestCase().addCoveredGoal(goal);
                    	if(Properties.TEST_ARCHIVE && contextFitness != null) {
                               Archive.getArchiveInstance().addTarget(goal);
                               Archive.getArchiveInstance().updateArchive(goal, test, 0.0);
                    	}
                    }
				}

			}
		}
	}
	
	public static int getNumExceptions(Map>> exceptions) {
		int total = 0;
		for (Set> exceptionSet : exceptions.values()) {
			total += exceptionSet.size();
		}
		return total;
	}

	public static int getNumClassExceptions(Map>> exceptions) {
		Set> classExceptions = new HashSet>();
		for (Set> exceptionSet : exceptions.values()) {
			classExceptions.addAll(exceptionSet);
		}
		return classExceptions.size();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy