Skip to content

Commit e3ab89e

Browse files
authored
refactor: simplifies angelic value analysis (SpoonLabs#175)
1 parent 75a5418 commit e3ab89e

File tree

6 files changed

+59
-53
lines changed

6 files changed

+59
-53
lines changed

.travis_defects4j_math.sh

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
#!/usr/bin/env bash
2-
# executing all tests in Defects4jEvaluationTest
2+
# executing all tests of Commons Math in Defects4J
3+
4+
# fails if any command fails
5+
set -e
6+
37
cd nopol
4-
mvn -q versions:set -DnewVersion=TRAVIS
5-
# creating target/nopol-TRAVIS-jar-with-dependencies.jar
6-
mvn -q clean package -DskipTests
78

8-
env NOPOL_EVAL_DEFECTS4J=1 mvn -q test -Dtest="Defects4jEvaluationMathTest"
9+
NOPOL_EVAL_DEFECTS4J=1 mvn test -Dtest="fr.inria.lille.repair.nopol.Defects4jEvaluationMathTest#test_Math42"
10+
11+
NOPOL_EVAL_DEFECTS4J=1 mvn test -Dtest="fr.inria.lille.repair.nopol.Defects4jEvaluationMathTest#test_Math49"
12+
13+
NOPOL_EVAL_DEFECTS4J=1 mvn test -Dtest="fr.inria.lille.repair.nopol.Defects4jEvaluationMathTest#test_Math69"
914

15+
# NOPOL_EVAL_DEFECTS4J=1 mvn test -Dtest="fr.inria.lille.repair.nopol.Defects4jEvaluationMathTest#test_Math32"
1016

17+
NOPOL_EVAL_DEFECTS4J=1 mvn test -Dtest="fr.inria.lille.repair.nopol.Defects4jEvaluationMathTest#test_Math33"
1118

nopol/src/main/java/fr/inria/lille/commons/synthesis/ConstraintBasedSynthesis.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.util.Arrays;
2121
import java.util.Collection;
22+
import java.util.LinkedList;
2223
import java.util.List;
2324
import java.util.Map;
2425

@@ -83,7 +84,7 @@ protected Expression<?> outputExpressionFor(Class<?> outputClass) {
8384
}
8485

8586
private <T> Collection<Map<String, Object>> synthesisInputValues(Collection<Specification<T>> specifications, Expression<?> outputExpression) {
86-
logCollection(logger(), "Specifications:", specifications);
87+
// logCollection(logger(), "Specifications:", new LinkedList<>(specifications).subList(0, Math.max(Math.min(20, specifications.size()-1), specifications.size()-1)));
8788
Collection<Map<String, Object>> synthesisInputs = MetaList.newLinkedList();
8889
for (Specification<T> specification : specifications) {
8990
Map<String, Object> newMap = specification.inputs();

nopol/src/main/java/fr/inria/lille/repair/nopol/synth/ConstraintModelBuilder.java

+24-21
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import java.util.ArrayList;
3939
import java.util.Collection;
4040
import java.util.Collections;
41-
import java.util.Iterator;
4241
import java.util.List;
4342

4443
/**
@@ -47,7 +46,6 @@
4746
public final class ConstraintModelBuilder implements InstrumentedProgram<Boolean> {
4847

4948
private final Logger logger = LoggerFactory.getLogger(this.getClass());
50-
private boolean viablePatch;
5149
private final ClassLoader classLoader;
5250
private RuntimeValues<Boolean> runtimeValues;
5351
private SourceLocation sourceLocation;
@@ -86,7 +84,7 @@ public Collection<Specification<Boolean>> collectSpecifications(URL[] classpath,
8684
// come back to default mode
8785
AngelicExecution.disable();
8886

89-
if (!determineViability(firstResult, secondResult)) {
87+
if (!isSynthesisPossible(firstResult, secondResult)) {
9088
return Collections.emptyList();
9189
}
9290
/* to collect information for passing tests */
@@ -140,26 +138,31 @@ public void testRunStarted(Description description)
140138

141139

142140

143-
private boolean determineViability(final Result firstResult, final Result secondResult) {
144-
Collection<Description> firstFailures = TestSuiteExecution.collectDescription(firstResult.getFailures());
145-
Collection<Description> secondFailures = TestSuiteExecution.collectDescription(secondResult.getFailures());
146-
firstFailures.retainAll(secondFailures);
147-
viablePatch = firstFailures.isEmpty();
148-
int nbFirstSuccess = firstResult.getRunCount() - firstResult.getFailureCount();
149-
int nbSecondSuccess = secondResult.getRunCount() - secondResult.getFailureCount();
150-
if (!viablePatch || (nbFirstSuccess == 0 && nbSecondSuccess == 0)) {
151-
logger.debug("Failing test(s): {}\n{}", sourceLocation, firstFailures);
141+
private boolean isSynthesisPossible(final Result firstResultWithFalse, final Result secondResultWithTrue) {
142+
// this method is a key optimization in Nopol
143+
// it enables to not start the synthesis when we are sure that it is not possible
144+
// only based on the observed test outcomes with angelic values
145+
146+
Collection<Description> testFailuresWithFalse = TestSuiteExecution.collectDescription(firstResultWithFalse.getFailures());
147+
Collection<Description> testFailuresWithTrue = TestSuiteExecution.collectDescription(secondResultWithTrue.getFailures());
148+
149+
// contract: all test failures must either in testFailuresWithFalse or in secondFailures
150+
// removes from testFailuresWithFalse all of its elements that are not contained in testFailuresWithTrue
151+
// consequently, it remains the elements that are always failing
152+
Collection<Description> testsThatAreAlwasyFailing = new ArrayList<>(testFailuresWithFalse);
153+
testsThatAreAlwasyFailing.retainAll(testFailuresWithTrue);
154+
155+
boolean synthesisIsPossible = testsThatAreAlwasyFailing.isEmpty();
156+
157+
// some logging
158+
int nbFirstSuccess = firstResultWithFalse.getRunCount() - firstResultWithFalse.getFailureCount();
159+
int nbSecondSuccess = secondResultWithTrue.getRunCount() - secondResultWithTrue.getFailureCount();
160+
if (!synthesisIsPossible || (nbFirstSuccess == 0 && nbSecondSuccess == 0)) {
152161
Logger testsOutput = LoggerFactory.getLogger("tests.output");
153-
testsOutput.debug("First set: \n{}", firstResult.getFailures());
154-
testsOutput.debug("Second set: \n{}", secondResult.getFailures());
162+
testsOutput.debug("Failing tests with false: \n{}", firstResultWithFalse.getFailures());
163+
testsOutput.debug("Failing tests with true: \n{}", secondResultWithTrue.getFailures());
155164
}
156-
return viablePatch;
165+
return synthesisIsPossible;
157166
}
158167

159-
/**
160-
* @see InstrumentedProgram#isAViablePatch()
161-
*/
162-
public boolean isAViablePatch() {
163-
return viablePatch;
164-
}
165168
}

nopol/src/main/java/fr/inria/lille/repair/nopol/synth/InstrumentedProgram.java

-1
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,4 @@ public interface InstrumentedProgram<T> {
2222
*/
2323
Collection<Specification<T>> collectSpecifications(final URL[] classpath, List<TestResult> testClasses, final Collection<TestCase> failures);
2424

25-
boolean isAViablePatch();
2625
}

nopol/src/main/java/fr/inria/lille/repair/nopol/synth/SMTNopolSynthesizer.java

-6
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,6 @@ public List<Patch> findAngelicValuesAndBuildPatch(URL[] classpath, List<TestResu
7878
}
7979

8080

81-
// and it should be a viable patch, ie. fix the bug
82-
if (!instrumentedProgram.isAViablePatch()) {
83-
LoggerFactory.getLogger(this.getClass()).info("Changing only this statement does not solve the bug. {}", sourceLocation);
84-
return Collections.EMPTY_LIST;
85-
}
86-
8781
nopolResult.incrementNbAngelicValues(sourceLocation, conditionalProcessor);
8882
nbStatementsWithAngelicValue++;
8983

nopol/src/test/java/fr/inria/lille/repair/nopol/Defects4jEvaluationMathTest.java

+21-19
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,20 @@
1212

1313
public class Defects4jEvaluationMathTest {
1414

15-
@Test(timeout = FIVE_MINUTES_TIMEOUT *2)
15+
@Test(timeout = FIFTEEN_MINUTES_TIMEOUT)
1616
public void test_Math32() throws Exception {
1717
// On Travis 454sec
18+
// Sep 30: 2018 timeout on Travis with ten minutes (600 seconds), moving to 15 minutes
1819
if (!testShouldBeRun()) { return; }
1920
NopolContext nopolContext = nopolConfigFor("Math32");
2021
NopolResult result = new NoPol(nopolContext).build();
2122
assertEquals(1, result.getPatches().size());
2223
}
2324

24-
@Test(timeout = FIVE_MINUTES_TIMEOUT *2)
25+
@Test(timeout = FIFTEEN_MINUTES_TIMEOUT)
2526
public void test_Math33() throws Exception {
2627
// on Travis: 458sec
28+
// Sep 30: 2018 timeout on Travis with ten minutes (600 seconds), moving to 15 minutes
2729
if (!testShouldBeRun()) { return; }
2830
NopolContext nopolContext = nopolConfigFor("Math33");
2931
NopolResult result = new NoPol(nopolContext).build();
@@ -57,14 +59,14 @@ public void test_Math49() throws Exception {
5759
assertEquals(1, result.getPatches().size());
5860
}
5961

60-
@Test(timeout = FIFTEEN_MINUTES_TIMEOUT)
61-
public void test_Math50() throws Exception {
62-
// on Travis: 8 minutes, sometimes more than 10 minutes
63-
if (!testShouldBeRun()) { return; }
64-
NopolContext nopolContext = nopolConfigFor("Math50");
65-
NopolResult result = new NoPol(nopolContext).build();
66-
assertEquals(1, result.getPatches().size());
67-
}
62+
// @Test(timeout = FIFTEEN_MINUTES_TIMEOUT)
63+
// public void test_Math50() throws Exception {
64+
// // on Travis: 8 minutes, sometimes more than 10 minutes
65+
// if (!testShouldBeRun()) { return; }
66+
// NopolContext nopolContext = nopolConfigFor("Math50");
67+
// NopolResult result = new NoPol(nopolContext).build();
68+
// assertEquals(1, result.getPatches().size());
69+
// }
6870

6971
// @Test(timeout = FIVE_MINUTES_TIMEOUT *2)
7072
// public void test_Math57() throws Exception {
@@ -84,15 +86,15 @@ public void test_Math50() throws Exception {
8486
// assertEquals(1, result.getPatches().size());
8587
// }
8688

87-
// @Test(timeout = FIVE_MINUTES_TIMEOUT *2)
88-
// public void test_Math69() throws Exception {
89-
// // on Travis: 22sec
90-
// if (!testShouldBeRun()) { return; }
91-
// NopolContext nopolContext = nopolConfigFor("Math69");
92-
// NopolResult result = new NoPol(nopolContext).build();
93-
// assertEquals(1, result.getPatches().size());
94-
// }
95-
//
89+
@Test(timeout = FIVE_MINUTES_TIMEOUT *2)
90+
public void test_Math69() throws Exception {
91+
// on Travis: 22sec
92+
if (!testShouldBeRun()) { return; }
93+
NopolContext nopolContext = nopolConfigFor("Math69");
94+
NopolResult result = new NoPol(nopolContext).build();
95+
assertEquals(1, result.getPatches().size());
96+
}
97+
9698
// @Test(timeout = FIVE_MINUTES_TIMEOUT *2)
9799
// public void test_Math71() throws Exception {
98100
// if (!testShouldBeRun()) { return; }

0 commit comments

Comments
 (0)