Skip to content

Commit

Permalink
Fix Windows-compatibility (#362)
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Monperrus <martin.monperrus@gnieh.org>
  • Loading branch information
zaricu22 and monperrus authored Aug 6, 2024
1 parent 2bc900b commit 8907168
Show file tree
Hide file tree
Showing 30 changed files with 393 additions and 230 deletions.
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.inria.sacha.automaticRepair</groupId>
<artifactId>astor</artifactId>
Expand Down Expand Up @@ -170,13 +170,13 @@
<repository>
<id>EvoSuite</id>
<name>EvoSuite Repository</name>
<url>http://www.evosuite.org/m2</url>
<url>https://www.evosuite.org/m2</url>
</repository>

<repository>
<id>sachaproject.gforge.inria.fr-release</id>
<name>Maven Repository for Spoon Release</name>
<url>http://sachaproject.gforge.inria.fr/repositories/releases/</url>
<url>https://sachaproject.gforge.inria.fr/repositories/releases/</url>
<snapshots />
</repository>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,12 @@ public TestCaseVariantValidationResult runTestFromEvoSuite(ProgramVariant curren
// Set up dirs
String classpathForCompile = "";
classpathForCompile = projectFacade.getProperties().getDependenciesString() + File.pathSeparator
+ projectFacade.getOutDirWithPrefix(currentVariant.currentMutatorIdentifier()) + File.pathSeparator//
+ new File(projectFacade.getOutDirWithPrefix(currentVariant.currentMutatorIdentifier()))
.getAbsolutePath()
+ File.pathSeparator//
+ new File(ConfigurationProperties.getProperty("evosuitejar")).getAbsolutePath() + File.pathSeparator
+ projectFacade.getOutDirWithPrefix(currentVariant.DEFAULT_ORIGINAL_VARIANT);
+ new File(projectFacade.getOutDirWithPrefix(currentVariant.DEFAULT_ORIGINAL_VARIANT))
.getAbsolutePath();

String outPutTest = projectFacade.getOutDirWithPrefix("/evosuite/evosuite-tests/" + sufix);

Expand Down Expand Up @@ -129,8 +132,8 @@ public TestCaseVariantValidationResult runTestFromEvoSuite(ProgramVariant curren
List<String> pathTestGenerated = new ArrayList<String>();

log.debug("Generating test for the first time");
boolean executed = fev.runEvosuite(currentVariant, classesToGenerateTests, projectFacade, testEScodepath,
runOverOriginal);
boolean executed = fev.runEvosuite(currentVariant, classesToGenerateTests, projectFacade,
esPath.getAbsolutePath(), runOverOriginal);

// we collect the files generated

Expand All @@ -145,7 +148,7 @@ public TestCaseVariantValidationResult runTestFromEvoSuite(ProgramVariant curren
// Collect test generated from files generated by ES
for (String f : pathTestGenerated) {
String qualifiedTestName = f.replace(".java", "").replace(esPath.toString(), "")
.replace("/evosuite-tests/", "").replace(File.separator, ".");
.replace(File.separator,".").replace(".evosuite-tests.", "");
if (!qualifiedTestName.endsWith(EvoSuiteFacade.EVOSUITE_scaffolding_SUFFIX) && classesToGenerateTests
.contains(qualifiedTestName.replace(EvoSuiteFacade.EVOSUITE_SUFFIX, ""))) {
testGenerated.add(qualifiedTestName);
Expand All @@ -165,18 +168,21 @@ public TestCaseVariantValidationResult runTestFromEvoSuite(ProgramVariant curren

// WE COMPILE EVO TEST
log.info("Classpath " + classpathForCompile);

String envOS = System.getProperty("os.name");
String javaPath = ConfigurationProperties.getProperty("jvm4evosuitetestexecution");
List<String> command = new ArrayList<String>();
command.add(javaPath + File.separator + "javac");
if (!envOS.contains("Windows"))
command.add(javaPath + File.separator + "javac");
else
command.add("\"" + javaPath + File.separator + "javac" + "\"");
command.add("-classpath");
command.add(classpathForCompile);
command.add("-d");

//// Save compiled
File fout = new File(outPutTest);
fout.mkdirs();
command.add(outPutTest);
command.add(fout.getAbsolutePath());

// Adding the files
for (String testPath : pathTestGenerated) {
Expand All @@ -189,8 +195,8 @@ public TestCaseVariantValidationResult runTestFromEvoSuite(ProgramVariant curren
log.debug("Any test to generate, all test cases were generated before: " + testAlreadyGenerated);
}

String classpathForRunTest = classpathForCompile + (File.pathSeparator) + outPutTest + File.pathSeparator
+ System.getProperty("java.class.path");
String classpathForRunTest = classpathForCompile + (File.pathSeparator) + new File(outPutTest).getAbsolutePath()
+ File.pathSeparator + System.getProperty("java.class.path");
log.info("Process classpath " + classpathForRunTest);

ProcessEvoSuiteValidator evoProcess = new ProcessEvoSuiteValidator();
Expand Down Expand Up @@ -231,4 +237,4 @@ public TestCasesProgramValidationResult executeRegressionTesting(URL[] processCl
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
Expand Down Expand Up @@ -49,11 +50,14 @@ public TestResult execute(String jvmPath, URL[] classpath, List<String> classesT
boolean outputInFile = ConfigurationProperties.getPropertyBool("processoutputinfile");

public TestResult execute(String jvmPath, String classpath, List<String> classesToExecute, int waitTime) {
String envOS = System.getProperty("os.name");
String timeZone = ConfigurationProperties.getProperty("timezone");

Process p = null;
jvmPath += File.separator + "java";
UUID procWinUUID = null;

String newJvmPath = jvmPath + File.separator + "java";
List<String> cls = new ArrayList<>(new HashSet(classesToExecute));

String newClasspath = classpath;
if (ConfigurationProperties.getPropertyBool("runjava7code") || ProjectConfiguration.isJDKLowerThan8()) {
newClasspath = (new File(ConfigurationProperties.getProperty("executorjar")).getAbsolutePath())
Expand All @@ -67,23 +71,36 @@ public TestResult execute(String jvmPath, String classpath, List<String> classes

List<String> command = new ArrayList<String>();

command.add(jvmPath);
command.add("\"" + newJvmPath + "\"");
command.add("-Xmx2048m");

String[] ids = ConfigurationProperties.getProperty(MetaGenerator.METALL).split(File.pathSeparator);
for (String mutid : ids) {
command.add("-D" + MetaGenerator.MUT_IDENTIFIER + mutid + "="
+ ConfigurationProperties.getProperty(MetaGenerator.MUT_IDENTIFIER + mutid));
}
if (envOS.contains("Windows")) {
procWinUUID = UUID.randomUUID();
command.add("-DwinProcUUID=" + procWinUUID);
System.setProperty("user.timezone", timeZone);
}

command.add("-cp");
command.add(newClasspath);
command.add("\"" + newClasspath + "\"");
command.add(laucherClassName().getCanonicalName());
command.addAll(cls);

printCommandToExecute(command, waitTime);

ProcessBuilder pb = new ProcessBuilder("/bin/bash");
ProcessBuilder pb;
if (!envOS.contains("Windows")) {
printCommandToExecute(command, waitTime);
pb = new ProcessBuilder("/bin/bash");
} else {
command.set(0, "'" + newJvmPath + "'");
command.set(5, "'" + newClasspath + "'");
// On Windows, BufferedWriter have a problem to write over 8192 characters.
// We must provide command in ProcessBuilder constructor.
pb = new ProcessBuilder("powershell", "-Command", "& " + toString(command));
}

if (outputInFile) {
pb.redirectOutput(ftemp);
Expand All @@ -97,22 +114,23 @@ public TestResult execute(String jvmPath, String classpath, List<String> classes
BufferedWriter p_stdin = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));

try {
// Set up the timezone
String timeZone = ConfigurationProperties.getProperty("timezone");
p_stdin.write("TZ=\"" + timeZone + "\"");
p_stdin.newLine();
p_stdin.flush();
p_stdin.write("export TZ");
p_stdin.newLine();
p_stdin.flush();
p_stdin.write("echo $TZ");
p_stdin.newLine();
p_stdin.flush();
// Writing the command
p_stdin.write(toString(command));

p_stdin.newLine();
p_stdin.flush();
if (!envOS.contains("Windows")) {
// Set up the timezone
p_stdin.write("TZ=\"" + timeZone + "\"");
p_stdin.newLine();
p_stdin.flush();
p_stdin.write("export TZ");
p_stdin.newLine();
p_stdin.flush();
p_stdin.write("echo $TZ");
p_stdin.newLine();
p_stdin.flush();
// Writing the command
p_stdin.write(toString(command));

p_stdin.newLine();
p_stdin.flush();
}

// end
p_stdin.write("exit");
Expand All @@ -125,13 +143,12 @@ public TestResult execute(String jvmPath, String classpath, List<String> classes

//
if (!p.waitFor(waitTime, TimeUnit.MILLISECONDS)) {
killProcess(p, waitTime);
killProcess(p, waitTime, procWinUUID);

return null;
}
long t_end = System.currentTimeMillis();
// log.debug("Execution time " + ((t_end - t_start) / 1000) + "
// seconds");
log.debug("Execution time " + ((t_end - t_start) / 1000) + "seconds");

if (!avoidInterruption) {
// We force obtaining the exit value.
Expand All @@ -143,12 +160,13 @@ public TestResult execute(String jvmPath, String classpath, List<String> classes
output = new BufferedReader(new FileReader(ftemp.getAbsolutePath()));
else
output = new BufferedReader(new InputStreamReader(p.getInputStream()));

TestResult tr = getTestResult(output);
p.destroyForcibly();
return tr;
} catch (IOException | InterruptedException | IllegalThreadStateException ex) {
log.info("The Process that runs JUnit test cases had problems: " + ex.getMessage());
killProcess(p, waitTime);
killProcess(p, waitTime, procWinUUID);
}
return null;
}
Expand All @@ -159,41 +177,62 @@ public TestResult execute(String jvmPath, String classpath, List<String> classes
*
* @param waitTime
*/
private void killProcess(Process p, int waitTime) {
private void killProcess(Process p, int waitTime, UUID procWinUUID) {
if (p == null)
return;

Object pid = null;
try {
Field f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
pid = f.get(p);
log.debug("-Killed id: pid->" + pid);

} catch (Exception e) {
if (procWinUUID != null) {
Process survivedPID = Runtime.getRuntime()
.exec("wmic process where \"commandline like '%-DwinProcUUID=" + procWinUUID
+ "%' and name like '%java.exe%'\" get processid");
BufferedReader outputSurvivedPIDs = new BufferedReader(
new InputStreamReader(survivedPID.getInputStream()));
String line;
int i = 0;
while ((line = outputSurvivedPIDs.readLine()) != null) {
if (i == 2 && !line.isEmpty()) {
pid = line.trim();
break;
}
i++;
}
} else {
Field f = p.getClass().getDeclaredField("pid");
f.setAccessible(true);
pid = f.get(p);
}
} catch (IOException | NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
log.error(e);
}
p.destroyForcibly();

p.destroyForcibly();
log.info("The Process that runs JUnit test cases did not terminate within waitTime of "
+ TimeUnit.MILLISECONDS.toSeconds(waitTime) + " seconds");
log.info("Killed the Process that runs JUnit test cases " + pid);
log.info("Killing the Process that runs JUnit test cases " + pid);

// workarrond!!
if (ConfigurationProperties.getPropertyBool("forcesubprocesskilling")) {
Integer subprocessid = Integer.valueOf(pid.toString()) + 1;
try {
log.debug("Killing subprocess " + subprocessid);
Process process = new ProcessBuilder(new String[] { "kill", subprocessid.toString() }).start();
Process process;
if (procWinUUID != null) {
log.error("Killing Windows process " + pid);
process = Runtime.getRuntime().exec("taskkill /T /F /PID " + pid);
} else {
log.debug("Killing subprocess " + subprocessid);
process = new ProcessBuilder(new String[] { "kill", subprocessid.toString() }).start();
}
process.waitFor();

} catch (Exception e) {
log.error("Problems killing subprocess " + subprocessid);
} catch (IOException | InterruptedException e) {
if (procWinUUID != null)
log.error("Problems killing Windows process " + pid);
else
log.error("Problems killing subprocess " + subprocessid);
log.error(e);
}

}

}

protected String urlArrayToString(URL[] urls) {
Expand Down Expand Up @@ -289,4 +328,4 @@ protected TestResult getTestResult(BufferedReader in) {
}
}

}
}
9 changes: 7 additions & 2 deletions src/main/java/fr/inria/astor/util/EvoSuiteFacade.java
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ protected static URL[] redefineURL(File foutgen, URL[] originalURL) throws Malfo
* @return
*/
protected boolean runProcess(URL[] urlClasspath, String[] argumentsEvo) {
String envOS = System.getProperty("os.name");

Process p = null;

String javaPath = ConfigurationProperties.getProperty("jvm4evosuitetestexecution");
Expand All @@ -227,7 +229,10 @@ protected boolean runProcess(URL[] urlClasspath, String[] argumentsEvo) {
try {

List<String> command = new ArrayList<String>();
command.add(javaPath);
if (!envOS.contains("Windows"))
command.add(javaPath);
else
command.add("\"" + javaPath + "\"");
command.add("-jar");
command.add(new File(ConfigurationProperties.getProperty("evosuitejar")).getAbsolutePath());

Expand Down Expand Up @@ -439,4 +444,4 @@ public static void runProcess(String[] command) throws Exception {
logger.debug(command + " exitValue() " + pro.exitValue());
}

}
}
Loading

0 comments on commit 8907168

Please sign in to comment.