use of fr.inria.lille.repair.nopol.NoPol in project repairnator by Spirals-Team.
the class NopolRepair method businessExecute.
@Override
protected void businessExecute() {
this.getLogger().debug("Start to use nopol to repair...");
this.setPipelineState(PipelineState.NOPOL_NOTPATCHED);
Metrics metric = this.inspector.getJobStatus().getMetrics();
List<URL> classPath = this.inspector.getJobStatus().getRepairClassPath();
File[] sources = this.inspector.getJobStatus().getRepairSourceDir();
if (classPath != null && sources != null) {
String[] sourcesStr = new String[sources.length];
int i = 0;
for (File f : sources) {
sourcesStr[i++] = f.getAbsolutePath();
}
List<FailureLocation> failureLocationList = new ArrayList<>(this.inspector.getJobStatus().getFailureLocations());
Collections.sort(failureLocationList, new ComparatorFailureLocation());
boolean patchCreated = false;
int passingTime = 0;
for (FailureLocation failureLocation : failureLocationList) {
Set<String> erroringTests = failureLocation.getErroringMethods();
Set<String> failingTests = failureLocation.getFailingMethods();
// this one is used to loop on Nopol over tests to ignore. It can be a list containing an empty list.
List<List<String>> listOfTestToIgnore = new ArrayList<>();
boolean ignoreError = false;
// in that case: no tests to ignore
if (erroringTests.isEmpty() || failingTests.isEmpty()) {
listOfTestToIgnore.add(new ArrayList<>());
// then we will first try to ignore erroring tests, then to ignore failing tests
} else {
listOfTestToIgnore.add(new ArrayList<>(erroringTests));
listOfTestToIgnore.add(new ArrayList<>(failingTests));
ignoreError = true;
}
for (List<String> testsToIgnore : listOfTestToIgnore) {
NopolInformation nopolInformation;
if (testsToIgnore.isEmpty()) {
nopolInformation = new NopolInformation(failureLocation, IgnoreStatus.NOTHING_TO_IGNORE);
} else {
if (ignoreError) {
nopolInformation = new NopolInformation(failureLocation, IgnoreStatus.IGNORE_ERRORING);
ignoreError = false;
} else {
nopolInformation = new NopolInformation(failureLocation, IgnoreStatus.IGNORE_FAILING);
}
}
this.nopolInformations.add(nopolInformation);
nopolInformation.setStatus(NopolStatus.RUNNING);
String testClass = failureLocation.getClassName();
int timeout = (TOTAL_MAX_TIME - passingTime) / 2;
if (timeout < MIN_TIMEOUT) {
timeout = MIN_TIMEOUT;
}
nopolInformation.setAllocatedTime(timeout);
this.getLogger().debug("Launching repair with Nopol for following test class: " + testClass + " (should timeout in " + timeout + " minutes)");
NopolContext nopolContext = new NopolContext(sources, classPath.toArray(new URL[classPath.size()]), new String[] { testClass }, testsToIgnore);
nopolContext.setComplianceLevel(8);
nopolContext.setTimeoutTestExecution(300);
nopolContext.setMaxTimeEachTypeOfFixInMinutes(15);
nopolContext.setMaxTimeInMinutes(timeout);
nopolContext.setLocalizer(NopolContext.NopolLocalizer.COCOSPOON);
nopolContext.setSolverPath(this.getConfig().getZ3solverPath());
nopolContext.setSynthesis(NopolContext.NopolSynthesis.DYNAMOTH);
nopolContext.setType(RepairType.COND_THEN_PRE);
nopolContext.setOnlyOneSynthesisResult(false);
nopolContext.setOutputFolder(this.getInspector().getRepoLocalPath());
nopolInformation.setNopolContext(nopolContext);
SolverFactory.setSolver(nopolContext.getSolver(), nopolContext.getSolverPath());
long beforeNopol = new Date().getTime();
try {
final NoPol nopol = new NoPol(nopolContext);
Factory spoonFactory = nopol.getSpooner().spoonFactory();
List<PatchAndDiff> patchAndDiffs = new ArrayList<>();
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future<NopolResult> nopolExecution = executor.submit(new Callable<NopolResult>() {
@Override
public NopolResult call() throws Exception {
NopolResult result = null;
try {
result = nopol.build();
} catch (RuntimeException e) {
addStepError("Got runtime exception while running Nopol", e);
}
return result;
}
});
try {
executor.shutdown();
NopolResult result = nopolExecution.get(nopolContext.getMaxTimeInMinutes(), TimeUnit.MINUTES);
if (result == null) {
result = nopol.getNopolResult();
}
nopolInformation.setNbStatements(result.getNbStatements());
nopolInformation.setNbAngelicValues(result.getNbAngelicValues());
String failureLocationWithoutDots = failureLocation.getClassName().replace('.', '/');
metric.addAngelicValueByTest(failureLocationWithoutDots, result.getNbAngelicValues());
List<Patch> patches = result.getPatches();
if (patches != null && !patches.isEmpty()) {
for (Patch patch : patches) {
String diff = patch.toDiff(spoonFactory, nopolContext);
patchAndDiffs.add(new PatchAndDiff(patch, diff));
}
nopolInformation.setPatches(patchAndDiffs);
nopolInformation.setStatus(NopolStatus.PATCH);
patchCreated = true;
} else {
nopolInformation.setStatus(NopolStatus.NOPATCH);
}
} catch (TimeoutException exception) {
this.addStepError("Timeout: execution time > " + nopolContext.getMaxTimeInMinutes() + " " + TimeUnit.MINUTES);
nopolExecution.cancel(true);
executor.shutdownNow();
nopolInformation.setStatus(NopolStatus.TIMEOUT);
NopolResult result = nopol.getNopolResult();
nopolInformation.setNbStatements(result.getNbStatements());
nopolInformation.setNbAngelicValues(result.getNbAngelicValues());
} catch (InterruptedException | ExecutionException e) {
this.addStepError(e.getMessage());
nopolExecution.cancel(true);
executor.shutdownNow();
nopolInformation.setStatus(NopolStatus.EXCEPTION);
nopolInformation.setExceptionDetail(e.getMessage());
NopolResult result = nopol.getNopolResult();
nopolInformation.setNbStatements(result.getNbStatements());
nopolInformation.setNbAngelicValues(result.getNbAngelicValues());
}
} catch (SpoonException e) {
this.addStepError(e.getMessage());
nopolInformation.setStatus(NopolStatus.EXCEPTION);
nopolInformation.setExceptionDetail(e.getMessage());
}
long afterNopol = new Date().getTime();
nopolInformation.setDateEnd();
int localPassingTime = Math.round((afterNopol - beforeNopol) / 60000);
nopolInformation.setPassingTime(localPassingTime);
passingTime += localPassingTime;
}
}
File nopolLog = new File(System.getProperty("user.dir"), "debug.log");
if (nopolLog.exists()) {
String nopolDestName = "repairnator.nopol.log";
File nopolDest = new File(this.getInspector().getRepoLocalPath(), nopolDestName);
try {
Files.move(nopolLog.toPath(), nopolDest.toPath());
this.getInspector().getJobStatus().addFileToPush(nopolDestName);
} catch (IOException e) {
getLogger().error("Error while renaming nopol log", e);
}
}
File nopolProperties = new File(this.getInspector().getRepoLocalPath() + "/repairnator.nopol.results");
this.getInspector().getJobStatus().addFileToPush("repairnator.nopol.results");
File patchDir = new File(this.getInspector().getRepoLocalPath() + "/repairnatorPatches");
patchDir.mkdir();
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(nopolProperties));
int infoNumber = 0;
for (NopolInformation information : this.nopolInformations) {
String informationStr = "nopolinfo #" + (infoNumber++) + "\n" + "location: " + information.getLocation() + "\n" + "status: " + information.getStatus().name() + "\n" + "dateEnd: " + information.getDateEnd().toString() + "\n" + "allocatedtime: " + information.getAllocatedTime() + "minutes \n" + "passingTime: " + information.getPassingTime() + "minutes \n" + "nb patches: " + information.getPatches().size() + "\n" + "nopol context: " + information.getNopolContext() + "\n" + "exception: " + information.getExceptionDetail() + "\n" + "nbStatements: " + information.getNbStatements() + "\n" + "nbAngelicValues: " + information.getNbAngelicValues() + "\n" + "ignoreStatus: " + information.getIgnoreStatus().name() + "\n" + "----------\n\n";
writer.write(informationStr);
writer.newLine();
writer.newLine();
writer.flush();
int patchNumber = 0;
for (PatchAndDiff patchAndDiff : information.getPatches()) {
File patchFile = new File(patchDir.getPath() + "/" + information.getLocation().getClassName() + "_patch_" + (patchNumber++));
Patch patch = patchAndDiff.getPatch();
BufferedWriter patchWriter = new BufferedWriter(new FileWriter(patchFile));
String patchWrite = "location: " + patch.getSourceLocation() + "\n" + "type: " + patch.getType() + "\n" + "patch: " + patchAndDiff.getDiff();
patchWriter.write(patchWrite);
patchWriter.flush();
patchWriter.close();
}
}
writer.close();
} catch (IOException e) {
this.addStepError("Error while writing nopol informations");
this.getLogger().error("Error while writing nopol informations", e);
}
if (!patchCreated) {
this.addStepError("No patch has been generated by Nopol. Look at the trace to get more information.");
return;
}
this.setPipelineState(PipelineState.NOPOL_PATCHED);
this.getInspector().getJobStatus().setHasBeenPatched(true);
List<String> nopolPatches = new ArrayList<>();
for (NopolInformation information : this.nopolInformations) {
for (PatchAndDiff p : information.getPatches()) {
nopolPatches.add(p.getDiff());
}
}
this.getInspector().getJobStatus().setNopolPatches(nopolPatches);
} else {
this.addStepError("No classpath or sources directory has been given. Nopol can't be launched.");
}
}
Aggregations