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

org.evosuite.testcarver.extraction.CarvingManager Maven / Gradle / Ivy

The newest version!
/**
 * 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.testcarver.extraction;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.evosuite.Properties;
import org.evosuite.classpath.ResourceList;
import org.evosuite.rmi.ClientServices;
import org.evosuite.rmi.service.ClientState;
import org.evosuite.testcarver.capture.FieldRegistry;
import org.evosuite.testcarver.testcase.CarvedTestCase;
import org.evosuite.testcase.TestCase;
import org.evosuite.testcase.execution.ExecutionResult;
import org.evosuite.testcase.execution.TestCaseExecutor;
import org.evosuite.utils.LoggingUtils;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CarvingManager {

	private static Logger logger = LoggerFactory.getLogger(CarvingManager.class);
	
	private static CarvingManager instance = null;
	
	private CarvingManager() {
		
	}
	
	public static CarvingManager getInstance() {
		if(instance == null)
			instance = new CarvingManager();
		
		return instance;
	}
	
	private Map, List> carvedTests = new LinkedHashMap<>();
	
	private boolean carvingDone = false;
	
	private Collection getListOfJUnitClassNames() throws IllegalStateException {

		String prop = Properties.SELECTED_JUNIT;
		if (prop == null || prop.trim().isEmpty()) {
			throw new IllegalStateException(
			        "Trying to use a test carver factory, but empty Properties.SELECTED_JUNIT");
		}

		String[] paths = prop.split(":");
		Collection junitTestNames = new HashSet();
		for (String s : paths) {
			junitTestNames.add(s.trim());
		}

		/* 
		Pattern pattern = Pattern.compile(Properties.JUNIT_PREFIX+".*.class");
		Collection junitTestNames = ResourceList.getResources(pattern);		
		logger.info("Found "+junitTestNames.size()+" candidate junit classes for pattern "+pattern);
		*/
		return junitTestNames;
	}
	

	private void chopException(TestCase test, ExecutionResult result) {
		if (!result.noThrownExceptions()) {
			// No code including or after an exception should be in the pool
			Integer pos = result.getFirstPositionOfThrownException();
			if (pos != null) {
				test.chop(pos);
			} else {
				test.chop(test.size() - 1);
			}
		}
	}
	
	private void readTestCases() throws IllegalStateException {
		ClientServices.getInstance().getClientNode().changeState(ClientState.CARVING);
		Collection junitTestNames = getListOfJUnitClassNames();
		LoggingUtils.getEvoLogger().info("* Executing tests from {} test {} for carving",
				junitTestNames.size(), junitTestNames.size() == 1 ? "class" : "classes");
		final JUnitCore runner = new JUnitCore();
		final CarvingRunListener listener = new CarvingRunListener();
		runner.addListener(listener);


		final List> junitTestClasses = new ArrayList>();
		final org.evosuite.testcarver.extraction.CarvingClassLoader classLoader = new org.evosuite.testcarver.extraction.CarvingClassLoader();
		// TODO: This really needs to be done in a nicer way!
		FieldRegistry.carvingClassLoader = classLoader;
		try {
			// instrument target class
			classLoader.loadClass(Properties.TARGET_CLASS);
		} catch (final ClassNotFoundException e) {
			throw new RuntimeException(e);
		}

		for (String className : junitTestNames) {
			String classNameWithDots = ResourceList.getClassNameFromResourcePath(className);
			try {
				final Class junitClass = classLoader.loadClass(classNameWithDots);
				junitTestClasses.add(junitClass);
			} catch (ClassNotFoundException e) {
				logger.error("Failed to load JUnit test class {}: {}", classNameWithDots, e);
			}
		}

		final Class[] classes = new Class[junitTestClasses.size()];
		junitTestClasses.toArray(classes);
		Result result = runner.run(classes);
		logger.info("Result: {}/{}", result.getFailureCount(), result.getRunCount());
		for(Failure failure : result.getFailures()) {
			logger.info("Failure: {}", failure.getMessage());
			logger.info("Exception: {}", failure.getException());
		}
		
		Map, List> testMap = listener.getTestCases();
		for(Class targetClass : testMap.keySet()) {

			List processedTests = new ArrayList<>();
			for (TestCase test : testMap.get(targetClass)) {
				String testName = ((CarvedTestCase)test).getName();
				if (test.isEmpty())
					continue;
				ExecutionResult executionResult = null;
				try {
					executionResult = TestCaseExecutor.runTest(test);
					
				} catch(Throwable t) {
					logger.info("Error while executing carved test {}: {}", testName, t);
					continue;
				}
				if (executionResult.noThrownExceptions()) {
					logger.info("Adding carved test without exception");
					logger.info(test.toCode());
					processedTests.add(test);
				} else {
					logger.info("Exception thrown in carved test {}: {}", testName,
							executionResult.getExceptionThrownAtPosition(executionResult.getFirstPositionOfThrownException()));
					for (StackTraceElement elem : executionResult.getExceptionThrownAtPosition(executionResult.getFirstPositionOfThrownException()).getStackTrace()) {
						logger.info(elem.toString());
					}
					logger.info(test.toCode(executionResult.exposeExceptionMapping()));
					if (Properties.CHOP_CARVED_EXCEPTIONS) {
						logger.info("Chopping exception of carved test");
						chopException(test, executionResult);
						if (test.hasObject(Properties.getTargetClassAndDontInitialise(), test.size())) {
							processedTests.add(test);
						} else {
							logger.info("Chopped test is empty");
						}
					} else {
						logger.info("Not adding carved test with exception: ");
					}
				}
			}
			// junitTests.addAll(listener.getTestCases());

			if (processedTests.size() > 0) {
				LoggingUtils.getEvoLogger().info(" -> Carved {} tests for class {} from existing JUnit tests",
						processedTests.size(), targetClass);
				if (logger.isDebugEnabled()) {
					for (TestCase test : processedTests) {
						logger.debug("Carved Test {}: {}", ((CarvedTestCase) test).getName(), test.toCode());
					}
				}
			} else {
				//String outcome = "";
				//for (Failure failure : result.getFailures()) {
				//	outcome += "(" + failure.getDescription() + ", " + failure.getTrace()
				//			+ ") ";
				//}
				logger.info("It was not possible to carve any test case for class {} from {}", targetClass.getName(),
						Arrays.toString(junitTestNames.toArray()));
				//		+ ". Test execution results: " + outcome);
			}
			carvedTests.put(targetClass, processedTests);
		}
		carvingDone = true;
		
		// TODO: Argh.
		FieldRegistry.carvingClassLoader = null;
		// TODO:
		// ClientNodeLocal client = ClientServices.getInstance().getClientNode();
		// client.trackOutputVariable(RuntimeVariable.CarvedTests, totalNumberOfTestsCarved);
		// client.trackOutputVariable(RuntimeVariable.CarvedCoverage,carvedCoverage);

	}
	
	public void clear() {
		carvingDone = false;
		carvedTests.clear();
	}
	
	public List getTestsForClass(Class clazz) {
		if(!carvingDone)
			readTestCases();
		
		if(!carvedTests.containsKey(clazz))
			return new ArrayList();
		
		return carvedTests.get(clazz);
	}
	
	public Set> getClassesWithTests() {
		if(!carvingDone)
			readTestCases();

		return carvedTests.keySet();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy