use of fr.inria.spirals.repairnator.process.inspectors.Metrics 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.");
}
}
use of fr.inria.spirals.repairnator.process.inspectors.Metrics in project repairnator by Spirals-Team.
the class CheckoutRepository method businessExecute.
@Override
protected void businessExecute() {
Metrics metric = this.getInspector().getJobStatus().getMetrics();
Git git;
try {
GitHelper gitHelper = this.getInspector().getGitHelper();
git = Git.open(new File(inspector.getRepoLocalPath()));
Build build;
switch(checkoutType) {
case CHECKOUT_BUGGY_BUILD:
build = inspector.getBuggyBuild();
metric.setBugCommit(build.getCommit().getSha());
metric.setBugCommitUrl(this.getCommitUrl(build.getCommit().getSha()));
break;
case CHECKOUT_BUGGY_BUILD_SOURCE_CODE:
build = inspector.getBuggyBuild();
metric.setBugCommit(build.getCommit().getSha());
metric.setBugCommitUrl(this.getCommitUrl(build.getCommit().getSha()));
metric.setReconstructedBugCommit(true);
break;
case CHECKOUT_PATCHED_BUILD:
build = inspector.getPatchedBuild();
metric.setPatchCommit(build.getCommit().getSha());
metric.setPatchCommitUrl(this.getCommitUrl(build.getCommit().getSha()));
break;
default:
this.getLogger().warn("A case seems not to have been considered. Buggy build will be used.");
build = inspector.getBuggyBuild();
}
if (build.isPullRequest()) {
PRInformation prInformation = build.getPRInformation();
if (prInformation != null) {
if (checkoutType == CheckoutType.CHECKOUT_PATCHED_BUILD) {
this.writeProperty("is-pr", "true");
this.writeProperty("pr-remote-repo", prInformation.getOtherRepo().getSlug());
this.writeProperty("pr-head-commit-id", prInformation.getHead().getSha());
this.writeProperty("pr-head-commit-id-url", prInformation.getHead().getCompareUrl());
this.writeProperty("pr-base-commit-id", prInformation.getBase().getSha());
this.writeProperty("pr-base-commit-id-url", prInformation.getBase().getCompareUrl());
this.writeProperty("pr-id", build.getPullRequestNumber());
}
} else {
this.addStepError("Error while getting the PR information...");
this.shouldStop = true;
return;
}
gitHelper.addAndCommitRepairnatorLogAndProperties(this.getInspector().getJobStatus(), git, "After getting PR information");
String repository = this.inspector.getRepoSlug();
this.getLogger().debug("Reproduce the PR for " + repository + " by fetching remote branch and merging.");
List<String> pathes;
if (checkoutType == CheckoutType.CHECKOUT_BUGGY_BUILD_SOURCE_CODE) {
pathes = new ArrayList<String>();
for (File path : this.getInspector().getJobStatus().getRepairSourceDir()) {
URI gitRepoURI = git.getRepository().getDirectory().getParentFile().toURI();
URI pathURI = path.getCanonicalFile().toURI();
String relativePath = gitRepoURI.relativize(pathURI).getPath();
pathes.add(relativePath);
}
} else {
pathes = null;
}
boolean successfulMerge = gitHelper.mergeTwoCommitsForPR(git, build, prInformation, repository, this, pathes);
if (!successfulMerge) {
this.getLogger().debug("Error while merging two commits to reproduce the PR.");
this.shouldStop = true;
}
} else {
String commitCheckout = build.getCommit().getSha();
commitCheckout = gitHelper.testCommitExistence(git, commitCheckout, this, build);
if (commitCheckout != null) {
this.getLogger().debug("Get the commit " + commitCheckout + " for repo " + this.inspector.getRepoSlug());
if (checkoutType != CheckoutType.CHECKOUT_BUGGY_BUILD_SOURCE_CODE) {
git.checkout().setName(commitCheckout).call();
} else {
List<String> pathes = new ArrayList<String>();
for (File path : this.getInspector().getJobStatus().getRepairSourceDir()) {
URI gitRepoURI = git.getRepository().getDirectory().getParentFile().toURI();
URI pathURI = path.getCanonicalFile().toURI();
String relativePath = gitRepoURI.relativize(pathURI).getPath();
pathes.add(relativePath);
}
git.checkout().setStartPoint(commitCheckout).addPaths(pathes).call();
PersonIdent personIdent = new PersonIdent("Luc Esape", "luc.esape@gmail.com");
git.commit().setMessage("Undo changes on source code").setAuthor(personIdent).setCommitter(personIdent).call();
}
this.writeProperty("bugCommit", this.inspector.getBuggyBuild().getCommit().getCompareUrl());
} else {
this.addStepError("Error while getting the commit to checkout from the repo.");
this.shouldStop = true;
return;
}
}
} catch (IOException | GitAPIException e) {
this.addStepError("Error while getting the commit to checkout from the repo.");
this.shouldStop = true;
}
this.writeProperty("hostname", Utils.getHostname());
switch(this.getInspector().getBuildToBeInspected().getStatus()) {
case ONLY_FAIL:
this.writeProperty("bugType", "only_fail");
break;
case FAILING_AND_PASSING:
this.writeProperty("bugType", "failing_passing");
break;
case PASSING_AND_PASSING_WITH_TEST_CHANGES:
this.writeProperty("bugType", "passing_passing");
break;
}
}
use of fr.inria.spirals.repairnator.process.inspectors.Metrics in project repairnator by Spirals-Team.
the class GatherTestInformation method businessExecute.
@Override
protected void businessExecute() {
this.getLogger().debug("Gathering test information...");
File rootRepo = new File(this.inspector.getJobStatus().getPomDirPath());
final List<File> surefireDirs = new ArrayList<File>();
try {
Files.walkFileTree(rootRepo.toPath(), new SimpleFileVisitor<Path>() {
public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException {
if (file.toString().endsWith(SUREFIREREPORT_PATH)) {
surefireDirs.add(file.toFile());
return FileVisitResult.SKIP_SUBTREE;
} else {
return FileVisitResult.CONTINUE;
}
}
});
} catch (IOException e) {
this.getLogger().warn("Error while traversing files to get surefire reports: " + e);
this.addStepError(e.getMessage());
}
for (File surefireDir : surefireDirs) {
SurefireReportParser parser = new SurefireReportParser(Arrays.asList(new File[] { surefireDir }), Locale.ENGLISH, null);
try {
List<ReportTestSuite> testSuites = parser.parseXMLReportFiles();
for (ReportTestSuite testSuite : testSuites) {
if (!skipSettingStatusInformation) {
this.nbTotalTests += testSuite.getNumberOfTests();
this.nbSkippingTests += testSuite.getNumberOfSkipped();
if (testSuite.getNumberOfFailures() > 0 || testSuite.getNumberOfErrors() > 0) {
File failingModule = surefireDir.getParentFile().getParentFile();
this.failingModulePath = failingModule.getCanonicalPath();
this.getInspector().getJobStatus().setFailingModulePath(this.failingModulePath);
this.writeProperty("failingModule", this.failingModulePath);
getLogger().info("Get the following failing module path: " + failingModulePath);
for (ReportTestCase testCase : testSuite.getTestCases()) {
if (testCase.hasFailure() || testCase.hasError()) {
// sometimes surefire reports a failureType on the form:
// "java.lang.NullPointerException:" we should avoid this case
String failureType = testCase.getFailureType();
if (failureType.endsWith(":")) {
failureType = failureType.substring(0, failureType.length() - 1);
}
this.failureNames.add(failureType);
FailureType typeTof = new FailureType(testCase.getFailureType(), testCase.getFailureMessage(), testCase.hasError());
FailureLocation failureLocation = null;
for (FailureLocation location : this.failureLocations) {
if (location.getClassName().equals(testCase.getFullClassName())) {
failureLocation = location;
break;
}
}
if (failureLocation == null) {
failureLocation = new FailureLocation(testCase.getFullClassName());
this.failureLocations.add(failureLocation);
}
failureLocation.addFailure(typeTof);
if (testCase.hasError()) {
failureLocation.addErroringMethod(testCase.getFullClassName() + "#" + testCase.getName());
} else {
failureLocation.addFailingMethod(testCase.getFullClassName() + "#" + testCase.getName());
}
}
}
}
}
this.nbErroringTests += testSuite.getNumberOfErrors();
this.nbFailingTests += testSuite.getNumberOfFailures();
}
if (this.nbFailingTests > 0) {
this.setPipelineState(PipelineState.HASTESTFAILURE);
} else if (this.nbErroringTests > 0) {
this.setPipelineState(PipelineState.HASTESTERRORS);
} else {
this.setPipelineState(PipelineState.NOTFAILING);
}
} catch (MavenReportException e) {
this.addStepError("Error while parsing files to get test information:", e);
} catch (IOException e) {
this.addStepError("Error while getting the failing module path: ", e);
}
}
if (!this.skipSettingStatusInformation) {
this.writeProperty("error-types", this.failureNames);
this.writeProperty("failing-test-cases", this.failureLocations);
this.writeProperty("totalNumberFailingTests", this.nbFailingTests);
this.writeProperty("totalNumberErroringTests", this.nbErroringTests);
this.writeProperty("totalNumberSkippingTests", this.nbSkippingTests);
this.writeProperty("totalNumberRunningTests", this.nbTotalTests);
this.inspector.getJobStatus().setFailureLocations(this.failureLocations);
Metrics metrics = this.inspector.getJobStatus().getMetrics();
metrics.setFailureNames(this.failureNames);
metrics.setNbFailingTests(this.nbErroringTests + this.nbFailingTests);
metrics.setNbRunningTests(this.nbTotalTests);
}
this.shouldStop = contract.shouldBeStopped(this);
}
use of fr.inria.spirals.repairnator.process.inspectors.Metrics in project repairnator by Spirals-Team.
the class CommitPatch method computePatchStats.
private void computePatchStats(Git git, RevCommit headRev, RevCommit commit) {
try {
ObjectReader reader = git.getRepository().newObjectReader();
CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
oldTreeIter.reset(reader, headRev.getTree());
CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
newTreeIter.reset(reader, commit.getTree());
DiffFormatter diffFormatter = new DiffFormatter(DisabledOutputStream.INSTANCE);
diffFormatter.setRepository(git.getRepository());
diffFormatter.setContext(0);
List<DiffEntry> entries = diffFormatter.scan(newTreeIter, oldTreeIter);
int nbLineAdded = 0;
int nbLineDeleted = 0;
Set<String> changedFiles = new HashSet<>();
for (DiffEntry entry : entries) {
String path;
if (entry.getChangeType() == DiffEntry.ChangeType.DELETE) {
path = entry.getOldPath();
} else {
path = entry.getNewPath();
}
if (!path.contains("repairnator")) {
changedFiles.add(path);
FileHeader fileHeader = diffFormatter.toFileHeader(entry);
List<? extends HunkHeader> hunks = fileHeader.getHunks();
for (HunkHeader hunk : hunks) {
nbLineAdded += hunk.getOldImage().getLinesAdded();
nbLineDeleted += hunk.getOldImage().getLinesDeleted();
}
}
}
Metrics metric = this.getInspector().getJobStatus().getMetrics();
metric.setPatchAddedLines(nbLineAdded);
metric.setPatchDeletedLines(nbLineDeleted);
metric.setPatchChangedFiles(changedFiles.size());
} catch (IOException e) {
this.getLogger().error("Error while computing stat on the patch", e);
}
}
use of fr.inria.spirals.repairnator.process.inspectors.Metrics in project repairnator by Spirals-Team.
the class InitRepoToPush method businessExecute.
@Override
protected void businessExecute() {
if (RepairnatorConfig.getInstance().isPush()) {
this.getLogger().info("Repairnator configured to push. Start init repo to push.");
File sourceDir = new File(this.getInspector().getRepoLocalPath());
File targetDir = new File(this.getInspector().getRepoToPushLocalPath());
try {
FileUtils.copyDirectory(sourceDir, targetDir);
this.removeNotificationFromTravisYML(targetDir);
File gitTargetFolder = new File(targetDir, ".git");
FileUtils.deleteDirectory(gitTargetFolder);
File m2TargetFolder = new File(targetDir, ".m2");
FileUtils.deleteDirectory(m2TargetFolder);
Git git = Git.init().setDirectory(targetDir).call();
git.add().addFilepattern(".").call();
for (String fileToPush : this.getInspector().getJobStatus().getCreatedFilesToPush()) {
// add force is not supported by JGit...
ProcessBuilder processBuilder = new ProcessBuilder("git", "add", "-f", fileToPush).directory(git.getRepository().getDirectory().getParentFile()).inheritIO();
try {
Process p = processBuilder.start();
p.waitFor();
} catch (InterruptedException | IOException e) {
this.getLogger().error("Error while executing git command to add files: " + e);
}
}
PersonIdent personIdent = new PersonIdent("Luc Esape", "luc.esape@gmail.com");
String message = "Bug commit from the following repository " + this.getInspector().getRepoSlug() + "\n";
Metrics metrics = this.getInspector().getJobStatus().getMetrics();
message += "This bug commit is a reflect of source code from: " + metrics.getBugCommitUrl() + ".";
git.commit().setMessage(message).setAuthor(personIdent).setCommitter(personIdent).call();
this.setPushState(PushState.REPO_INITIALIZED);
} catch (IOException e) {
this.addStepError("Error while copying the folder to prepare the git repository.", e);
this.setPushState(PushState.REPO_NOT_INITIALIZED);
} catch (GitAPIException e) {
this.addStepError("Error while initializing the new git repository.", e);
this.setPushState(PushState.REPO_NOT_INITIALIZED);
}
} else {
this.getLogger().info("Repairnator configured to NOT push. Step bypassed.");
}
}
Aggregations