Skip to content

Commit 87cedc1

Browse files
committed
Changes:
- Updated dependencyAnalizer.jar to allow reuse of main.api.DependencyScanner. - Refactoring in mujava.app.Core and mujava.app.MutationScore to allow more mutant information when calculating mutation score. - mujava.app.MutantInfo now holds a listo of mujava.app.MutationInformation instead of having mutations, lines and operators listed independently and with only the last mutated method. - mujava.app.TestResult now shows the name of the runned test class. - test classes verification will only load the selected test classes * the previous (load all classes in test folder) implementation caused exceptions in incomplete projects Fixes: - toughness analysis per mutant was being calculated for each test instead of using all tests. - fixed a bug in test/mutationScore.BooleanOpsAndTests that caused a test case to fail on a correct implementation of utils.BooleanOps#and(boolean, boolean). - fixed mujava.util.ConfigReader#stringArgumentsAsArray(String) returning a one element array (with an empty string) when no arguments where declared. Additions: - mujava.app.MutationInformation, a simple holder class that contains method, line and mutation. - new property option mutation.advanced.outputMutationsInfoInMutationScore to enable the output mutations made on each mutant when running mutation score - new property option mutation.advanced.useSimpleClassNames to choose whether type are written using their simple name or the fully qualified name * e.g.: java.lang.String is written as String when this option is set to true * fully qualified names can cause non-compiling mutants when using generics - mujava.generations.Generator now adds the parent mutant information (his MutationInformation list) to each new mutant * this is just for information, the parents mutations can't be used (maybe they can but it would be very difficult and not recomended) - Preliminary code added to the following classes to allow annotations in the original file to be written in the mutants : * mujava.op.util.MutantCodeWrite * mujava.op.util.OLMO * mujava.openjava.extension.EvaluationShuttle * mujava.openjava.extension.VariableBinder * to make this work, changes in OJ grammar must be done and that has been proved to be more difficult than expected
1 parent 8d96cae commit 87cedc1

18 files changed

Lines changed: 556 additions & 197 deletions

default.properties

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ path.mutants= /home/stein/mutants/
1616
mutation.basic.class= utils.BooleanOps
1717

1818
//methods to mutate (separated by spaces)
19-
mutation.basic.methods= and
19+
mutation.basic.methods= and or
2020

2121
//operators to use (separated by spaces)
2222
mutation.basic.operators= COR COI
@@ -49,9 +49,13 @@ mutation.advanced.allowedPackagesToReload= utils mutationScore
4949
mutation.advanced.allowNumericLiteralVariations= false
5050

5151
//stop at the first failing test for each mutant
52-
mutation.advanced.quickDeath= true
52+
mutation.advanced.quickDeath= false
5353

5454
//enable full verbose information
5555
mutation.advanced.fullVerbose= false
5656

5757
mutation.advanced.toughness= true
58+
59+
mutation.advanced.outputMutationsInfoInMutationScore= true
60+
61+
mutation.advanced.generations= 2

lib/dependencyAnalizer.jar

-226 KB
Binary file not shown.

src/mujava/app/Core.java

Lines changed: 100 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import java.util.List;
1313
import java.util.Map;
1414
import java.util.Set;
15-
import java.util.Map.Entry;
15+
//import java.util.Map.Entry;
1616

1717
import org.junit.runner.notification.Failure;
1818

@@ -48,7 +48,8 @@ public class Core {
4848
private Map<String, List<String>> mutantsFolders;
4949
private Exception error;
5050
private MutationScore ms;
51-
private int generation = -1 ;
51+
//private int generation = -1 ;
52+
private List<MutantInfo> lastGeneration = null;
5253
public static boolean fullVerbose = false;
5354
public static boolean showSurvivingMutants = false;
5455
public static final int mujavappVersion = 20151011;
@@ -111,7 +112,8 @@ public boolean generateMutants(String className, String[] methods, Mutant[] mutO
111112
GenerationsInformation generationsInfo= generator.generate(false, true);
112113
if (Core.fullVerbose) System.out.println(generationsInfo.showBasicInformation());
113114
this.mutantsFolders = generator.getMutantsFolderForGeneration(generation);
114-
this.generation = generation;
115+
//this.generation = generation;
116+
this.lastGeneration = generationsInfo.getLastGeneration();
115117
} catch (Exception e) {
116118
this.error = e;
117119
}
@@ -168,55 +170,110 @@ public String getOutputDir() {
168170
}
169171

170172
public float calculateMutationScore(String[] testClasses, String className) {
173+
if (this.lastGeneration == null) {
174+
this.error = new IllegalStateException("There are no recorder mutants in the last generation");
175+
return -1;
176+
}
171177
List<String> survivingMutantsPaths = new LinkedList<>();
172178
int failedToCompile = 0;
173179
int mutantsKilled = 0;
174180
int mutants = 0;
175181
int timedOut = 0;
176-
for (Entry<String, List<String>> entry : lastMutantsFolder().entrySet()) {
177-
for (String path : entry.getValue()) {
178-
mutants++;
179-
String currGen = "generation-" + this.generation;
180-
String pathToFile = currGen + SEPARATOR + entry.getKey() + SEPARATOR + path;
181-
String fullPathToJavaFile = pathToFile + className.replaceAll("\\.", SEPARATOR)+".java";
182-
if (!ms.compile(fullPathToJavaFile)){
183-
System.out.println("File : " + Core.outputDir + pathToFile + className.replaceAll("\\.", SEPARATOR)+".java" + " didn't compile\n");
184-
failedToCompile++;
185-
continue;
186-
}
187-
boolean killed = false;
188-
List<TestResult> results = ms.runTestsWithMutants(Arrays.asList(testClasses), pathToFile, className);
189-
if (results == null) {
190-
System.out.println("An error ocurred while running tests for mutants");
191-
System.out.println(ms.getLastError()!=null?ms.getLastError().toString():"no exception to display, contact your favorite mujava++ developer");
192-
return -1;
193-
}
194-
for (TestResult r : results) {
195-
//System.out.println("Runned : " + r.getRunCount() + " tests (pass : " + (r.getRunCount()-r.getFailureCount()) + " | failed : " + r.getFailureCount() + ")\n");
196-
System.out.println(r.toString()+"\n");
197-
if (!r.wasSuccessful()) {
198-
if (r.getTimedoutTests() > 0) timedOut++;
199-
for (Failure f : r.getFailures()) {
200-
if (Core.fullVerbose || toughnessAnalysis()) System.out.println("mutant : " + Core.outputDir + pathToFile + className.replaceAll("\\.", SEPARATOR)+".java");
201-
if (toughnessAnalysis()) {
202-
float toughness = 1.0f - ((r.getTotalFailures() * 1.0f) / (r.getRunnedTestsCount() * 1.0f));
203-
this.addToughnessValue(toughness);
204-
System.out.println("Toughness: " + toughness + " [failed : " + r.getTotalFailures() + " | total : " + r.getRunnedTestsCount() + "]");
205-
}
206-
if (Core.fullVerbose) System.out.println("test : " + f.getTestHeader());
207-
if (Core.fullVerbose) System.out.println("failure description: " + f.getDescription());
208-
if (Core.fullVerbose && !(f.getException() instanceof java.lang.AssertionError)) System.out.println("exception: " + f.getException());
209-
if (Core.fullVerbose && !(f.getException() instanceof java.lang.AssertionError)) System.out.println("trace: " + f.getTrace());
210-
}
182+
for (MutantInfo mut : this.lastGeneration) {
183+
mutants++;
184+
String pathToFile = mut.getPath();
185+
if (!ms.compile(pathToFile)){
186+
System.out.println("File : " + pathToFile + " didn't compile\n"); //Core.outputDir + pathToFile + className.replaceAll("\\.", SEPARATOR)+".java" + " didn't compile\n");
187+
failedToCompile++;
188+
continue;
189+
}
190+
boolean killed = false;
191+
List<TestResult> results = ms.runTestsWithMutants(Arrays.asList(testClasses), mut);
192+
if (results == null) {
193+
System.out.println("An error ocurred while running tests for mutants");
194+
System.out.println(ms.getLastError()!=null?ms.getLastError().toString():"no exception to display, contact your favorite mujava++ developer");
195+
return -1;
196+
}
197+
int runnedTestsCount = 0;
198+
int totalFailures = 0;
199+
for (TestResult r : results) {
200+
//System.out.println("Runned : " + r.getRunCount() + " tests (pass : " + (r.getRunCount()-r.getFailureCount()) + " | failed : " + r.getFailureCount() + ")\n");
201+
System.out.println(r.toString()+"\n");
202+
runnedTestsCount += r.getRunnedTestsCount();
203+
totalFailures += r.getTotalFailures();
204+
if (!r.wasSuccessful()) {
205+
if (r.getTimedoutTests() > 0) timedOut++;
206+
for (Failure f : r.getFailures()) {
207+
// if (Core.fullVerbose || toughnessAnalysis()) System.out.println("mutant : " + mut.getPath());//Core.outputDir + pathToFile + className.replaceAll("\\.", SEPARATOR)+".java");
208+
// if (toughnessAnalysis()) {
209+
// float toughness = 1.0f - ((r.getTotalFailures() * 1.0f) / (r.getRunnedTestsCount() * 1.0f));
210+
// this.addToughnessValue(toughness);
211+
// System.out.println("Toughness: " + toughness + " [failed : " + r.getTotalFailures() + " | total : " + r.getRunnedTestsCount() + "]");
212+
// }
213+
if (Core.fullVerbose) System.out.println("test : " + f.getTestHeader());
214+
if (Core.fullVerbose) System.out.println("failure description: " + f.getDescription());
215+
if (Core.fullVerbose && !(f.getException() instanceof java.lang.AssertionError)) System.out.println("exception: " + f.getException());
216+
if (Core.fullVerbose && !(f.getException() instanceof java.lang.AssertionError)) System.out.println("trace: " + f.getTrace());
211217
}
212-
if (!killed && !r.wasSuccessful()) killed = true;
213-
}
214-
if (killed) mutantsKilled++;
215-
if (!killed && Core.showSurvivingMutants) {
216-
survivingMutantsPaths.add(fullPathToJavaFile);
217218
}
219+
if (!killed && !r.wasSuccessful()) killed = true;
220+
}
221+
if (toughnessAnalysis()) {
222+
float toughness = 1.0f - ((totalFailures * 1.0f) / (runnedTestsCount * 1.0f));
223+
this.addToughnessValue(toughness);
224+
System.out.println("Toughness: " + toughness + " [failed : " + totalFailures + " | total : " + runnedTestsCount + "]");
225+
System.out.println();
226+
}
227+
if (killed) mutantsKilled++;
228+
if (!killed && Core.showSurvivingMutants) {
229+
survivingMutantsPaths.add(pathToFile);
218230
}
231+
219232
}
233+
// for (Entry<String, List<String>> entry : lastMutantsFolder().entrySet()) {
234+
// for (String path : entry.getValue()) {
235+
// mutants++;
236+
// String currGen = "generation-" + this.generation;
237+
// String pathToFile = currGen + SEPARATOR + entry.getKey() + SEPARATOR + path;
238+
// String fullPathToJavaFile = pathToFile + className.replaceAll("\\.", SEPARATOR)+".java";
239+
// if (!ms.compile(fullPathToJavaFile)){
240+
// System.out.println("File : " + Core.outputDir + pathToFile + className.replaceAll("\\.", SEPARATOR)+".java" + " didn't compile\n");
241+
// failedToCompile++;
242+
// continue;
243+
// }
244+
// boolean killed = false;
245+
// List<TestResult> results = ms.runTestsWithMutants(Arrays.asList(testClasses), pathToFile, className);
246+
// if (results == null) {
247+
// System.out.println("An error ocurred while running tests for mutants");
248+
// System.out.println(ms.getLastError()!=null?ms.getLastError().toString():"no exception to display, contact your favorite mujava++ developer");
249+
// return -1;
250+
// }
251+
// for (TestResult r : results) {
252+
// //System.out.println("Runned : " + r.getRunCount() + " tests (pass : " + (r.getRunCount()-r.getFailureCount()) + " | failed : " + r.getFailureCount() + ")\n");
253+
// System.out.println(r.toString()+"\n");
254+
// if (!r.wasSuccessful()) {
255+
// if (r.getTimedoutTests() > 0) timedOut++;
256+
// for (Failure f : r.getFailures()) {
257+
// if (Core.fullVerbose || toughnessAnalysis()) System.out.println("mutant : " + Core.outputDir + pathToFile + className.replaceAll("\\.", SEPARATOR)+".java");
258+
// if (toughnessAnalysis()) {
259+
// float toughness = 1.0f - ((r.getTotalFailures() * 1.0f) / (r.getRunnedTestsCount() * 1.0f));
260+
// this.addToughnessValue(toughness);
261+
// System.out.println("Toughness: " + toughness + " [failed : " + r.getTotalFailures() + " | total : " + r.getRunnedTestsCount() + "]");
262+
// }
263+
// if (Core.fullVerbose) System.out.println("test : " + f.getTestHeader());
264+
// if (Core.fullVerbose) System.out.println("failure description: " + f.getDescription());
265+
// if (Core.fullVerbose && !(f.getException() instanceof java.lang.AssertionError)) System.out.println("exception: " + f.getException());
266+
// if (Core.fullVerbose && !(f.getException() instanceof java.lang.AssertionError)) System.out.println("trace: " + f.getTrace());
267+
// }
268+
// }
269+
// if (!killed && !r.wasSuccessful()) killed = true;
270+
// }
271+
// if (killed) mutantsKilled++;
272+
// if (!killed && Core.showSurvivingMutants) {
273+
// survivingMutantsPaths.add(fullPathToJavaFile);
274+
// }
275+
// }
276+
// }
220277
System.out.println("Mutants : "+ mutants + " | didn't compile : " + failedToCompile + " | mutants killed by tests : "+ mutantsKilled + " | surviving mutants : " + (mutants-failedToCompile-mutantsKilled) + " | total tests that timedout : " + timedOut + " | mutation score : "+((mutantsKilled+failedToCompile)*100.0)/mutants+ " | mutation score (only compiling mutants) : " + (mutantsKilled*100.0)/(mutants-failedToCompile) + '\n');
221278
if (Core.showSurvivingMutants) {
222279
System.out.println("Surviving mutants paths:\n");

src/mujava/app/Main.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
import mujava.api.Api;
2222
import mujava.api.Configuration;
2323
import mujava.api.Mutant;
24-
import mujava.api.MutantsInformationHolder;
2524
import mujava.loader.Reloader;
2625
import mujava.op.PRVO;
26+
import mujava.op.util.MutantCodeWriter;
2727
import mujava.util.Config;
2828
import mujava.util.ConfigReader;
2929

@@ -278,13 +278,27 @@ public static void main(String[] args) {
278278
Core.fullVerbose = false;
279279
}
280280

281+
if (config.outputMutationsInfo()) {
282+
System.out.println("Mutations information enabled on mutation score analysis");
283+
MutationScore.outputMutationsInfo = true;
284+
} else {
285+
MutationScore.outputMutationsInfo = false;
286+
}
287+
281288
if (config.toughnessAnalysis()) {
282289
System.out.println("Toughness analysis enabled");
283290
Configuration.add(Core.ENABLE_TOUGHNESS, Boolean.TRUE);
284291
} else {
285292
Configuration.add(Core.ENABLE_TOUGHNESS, Boolean.FALSE);
286293
}
287294

295+
if (config.useSimpleClassNames()) {
296+
System.out.println("Using simple class names when writing mutants");
297+
MutantCodeWriter.useSimpleClassNames(true);
298+
} else {
299+
MutantCodeWriter.useSimpleClassNames(false);
300+
}
301+
288302
if (config.allowPrimitiveToObjectAssignments()) {
289303
System.out.println("Primitive to Object assignments are disabled");
290304
Configuration.add(PRVO.ENABLE_PRIMITIVE_TO_OBJECT_ASSIGNMENTS, Boolean.FALSE);
@@ -538,6 +552,7 @@ public static void main(String[] args) {
538552
MutationScore ms = MutationScore.newInstance(mutantsSourceDir, originalBinDir, testBinDir);
539553
core.setMutationScore(ms);
540554
float mutationScoreResult = core.calculateMutationScore(testClasses, classToMutate);
555+
System.out.println();
541556
System.out.println(classToMutate + " scored : " + mutationScoreResult + " with tests : " + Arrays.asList(testClasses).toString());
542557
Core.killStillRunningJUnitTestcaseThreads();
543558
}
@@ -576,6 +591,7 @@ private static void deleteDirRecursively(File file){
576591
private static boolean confirmDirectoryCleaning(File file) {
577592
String input;
578593
System.out.print("Please confirm that you want to delete everything inside " + file.getAbsolutePath() + " (Yes|Y|S|Si|N|No) : ");
594+
@SuppressWarnings("resource")
579595
Scanner in = new Scanner(System.in);
580596
input = in.next();
581597
if (input.toLowerCase().matches("(yes|y|si|s)")) {

0 commit comments

Comments
 (0)