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

org.evosuite.maven.util.EvoSuiteRunner 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.maven.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingResult;
import org.eclipse.aether.RepositorySystemSession;
import org.evosuite.EvoSuite;
import org.evosuite.runtime.util.JavaExecCmdUtil;
import org.evosuite.utils.LoggingUtils;

/**
 * Note: we cannot call EvoSuite directly on same JVM, like the following:

 

ContinuousTestGeneration ctg = new ContinuousTestGeneration(target,cp,prefix,conf); ctg.execute();

* Reason is that Maven uses its own classloaders, and setting their classpath * becomes very messy, if possible at all. * So, we need to call EvoSuite on separated process * *

* TODO: most likely this code should be moved to a library, as other plugins (eg Netbeans) * will use it as well * */ public class EvoSuiteRunner { public static final String EVOSUITE_HOME_VARIABLE = "EVOSUITE_HOME"; /** * The maven logger of the plugin */ private final Log logger; private final List artifacts; private final ProjectBuilder projectBuilder; private final RepositorySystemSession repoSession; private Process process; public EvoSuiteRunner(Log logger, List artifacts, ProjectBuilder projectBuilder, RepositorySystemSession repoSession) { super(); this.logger = logger; this.artifacts = artifacts; this.projectBuilder = projectBuilder; this.repoSession = repoSession; } public void registerShutDownHook(){ Runtime.getRuntime().addShutdownHook(new Thread(){ @Override public void run() { if(process != null){ process.destroy(); } } }); } /** * This is blocking * @param params * @return */ public boolean runEvoSuite(String dir, List params){ List cmd = getCommandToRunEvoSuite(); if(cmd==null){ return false; } cmd.addAll(params); return runProcess(dir,cmd); } /** * We run the EvoSuite that is provided with the plugin * * @return */ private List getCommandToRunEvoSuite(){ logger.debug("EvoSuite Maven Plugin Artifacts: "+Arrays.toString(artifacts.toArray())); Artifact evosuite = null; for(Artifact art : artifacts){ //first find the main EvoSuite jar among the dependencies if(art.getArtifactId().equals("evosuite-master")){ evosuite = art; break; } } if(evosuite==null){ logger.error("CRITICAL ERROR: plugin can detect EvoSuite executable"); return null; } logger.debug("EvoSuite located at: "+evosuite.getFile()); /* * now, build a project descriptor for evosuite, which is needed to * query all of its dependencies */ DefaultProjectBuildingRequest req = new DefaultProjectBuildingRequest(); req.setRepositorySession(repoSession); req.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL); req.setSystemProperties(System.getProperties()); req.setResolveDependencies(true); ProjectBuildingResult res; try { res = projectBuilder.build(evosuite, req); } catch (ProjectBuildingException e) { logger.error("Failed: "+e.getMessage(),e); return null; } //build the classpath to run EvoSuite String cp = evosuite.getFile().getAbsolutePath(); for(Artifact dep : res.getProject().getArtifacts()){ cp += File.pathSeparator+dep.getFile().getAbsolutePath(); } logger.debug("EvoSuite classpath: "+cp); String entryPoint = EvoSuite.class.getName(); List cmd = new ArrayList<>(); cmd.add(JavaExecCmdUtil.getJavaBinExecutablePath()/*"java"*/); cmd.add("-D" + LoggingUtils.USE_DIFFERENT_LOGGING_XML_PARAMETER + "=logback-ctg-entry.xml"); cmd.add("-Dlogback.configurationFile=logback-ctg-entry.xml"); cmd.add("-cp"); cmd.add(cp); cmd.add(entryPoint); return cmd; } /** * Check if there is a valid installation of EvoSuite on the current machine * */ @Deprecated private List getCommandToRunExternalEvoSuite(){ /* * Note: we keep this code in case we want to implement * the option of running an external EvoSuite */ String home = System.getenv(EVOSUITE_HOME_VARIABLE); if(home==null || home.isEmpty()){ logger.error("Need to set the environment variable "+EVOSUITE_HOME_VARIABLE+ " pointing to where EvoSuite is installed"); return null; } File folder = new File(home); if(!folder.exists()){ logger.error("EvoSuite home "+home+" does not exist"); return null; } if(!folder.isDirectory()){ logger.error("EvoSuite home "+home+" is not a folder"); return null; } /* * TODO: this will need to be changed once we finalize how to * distribute EvoSuite */ File[] jars = folder.listFiles(new FilenameFilter(){ @Override public boolean accept(File dir, String name) { String lc = name.toLowerCase(); return lc.startsWith("evosuite") && lc.endsWith(".jar"); }}); if(jars.length == 0){ logger.error("No evosuite jar in "+folder.getPath()); return null; } if(jars.length > 1){ /* * sort in way the largest file is first. * this is needed if we put as HOME where we compile EvoSuite */ Arrays.sort(jars,new Comparator(){ @Override public int compare(File o1, File o2) { return (int) (o2.length() - o1.length()); }}); } String evo = jars[0].getAbsolutePath(); logger.info("Going to use EvoSuite jar: "+evo); List cmd = new ArrayList<>(); cmd.add(JavaExecCmdUtil.getJavaBinExecutablePath()/*"java"*/); cmd.add("-jar"); cmd.add(""+evo); return cmd; } private boolean runProcess(String baseDir, List cmd){ try{ if(baseDir==null){ baseDir = System.getProperty("user.dir"); } logger.debug("Working directory: "+baseDir); if(logger.isDebugEnabled()) { logger.debug("Going to execute command: " + String.join(" ", cmd)); } File dir = new File(baseDir); ProcessBuilder builder = new ProcessBuilder(cmd); builder.directory(dir); builder.redirectErrorStream(true); process = builder.start(); handleProcessOutput(process,logger); //output int exitCode = process.waitFor(); if(exitCode != 0){ logger.error("Error in EvoSuite"); return false; } else { logger.debug("EvoSuite terminated"); } } catch (IOException e) { logger.error("Failed to start EvoSuite: "+e.getMessage(), e); return false; } catch (InterruptedException e) { if(process!=null){ try { //be sure streamers are closed, otherwise process might hang on Windows process.getOutputStream().close(); process.getInputStream().close(); process.getErrorStream().close(); } catch (Exception t){ logger.error("Failed to close process stream: "+t.toString()); } process.destroy(); } return false; } process = null; return true; } private void handleProcessOutput(final Process process, final Log logger){ Thread reader = new Thread(){ @Override public void run(){ try{ BufferedReader in = new BufferedReader( new InputStreamReader(process.getInputStream())); while(!this.isInterrupted()){ String line = in.readLine(); if(line!=null && !line.isEmpty()){ logger.info(line); } } } catch(Exception e){ logger.debug("Exception while reading spawn process output: "+ e.toString()); } } }; reader.start(); logger.debug("Started thread to read spawn process output"); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy