From 5e85d602e9ac207321ab8a0970558fccc41e7a43 Mon Sep 17 00:00:00 2001 From: Benjamin DANGLOT Date: Mon, 18 Dec 2017 10:42:25 +0100 Subject: [PATCH] Mutant exe selector (#288) * test: selector of new mutant executed by amplified tests * feat: selector of new mutant executed by amplified tests * feat: add value for option selector to use the ExecutedMutantSelector * refactor: remove dependencies to PitExecutor --- .../selector/ExecutedMutantSelector.java | 124 ++++ .../main/java/fr/inria/stamp/JSAPOptions.java | 583 +++++++++--------- .../selector/ExecutedMutantSelectorTest.java | 78 +++ 3 files changed, 497 insertions(+), 288 deletions(-) create mode 100644 dspot/src/main/java/fr/inria/diversify/dspot/selector/ExecutedMutantSelector.java create mode 100644 dspot/src/test/java/fr/inria/diversify/dspot/selector/ExecutedMutantSelectorTest.java diff --git a/dspot/src/main/java/fr/inria/diversify/dspot/selector/ExecutedMutantSelector.java b/dspot/src/main/java/fr/inria/diversify/dspot/selector/ExecutedMutantSelector.java new file mode 100644 index 000000000..5cbb2ea8b --- /dev/null +++ b/dspot/src/main/java/fr/inria/diversify/dspot/selector/ExecutedMutantSelector.java @@ -0,0 +1,124 @@ +package fr.inria.diversify.dspot.selector; + +import fr.inria.diversify.automaticbuilder.AutomaticBuilder; +import fr.inria.diversify.automaticbuilder.AutomaticBuilderFactory; +import fr.inria.diversify.dspot.support.DSpotCompiler; +import fr.inria.diversify.mutant.pit.PitResult; +import fr.inria.diversify.mutant.pit.PitResultParser; +import fr.inria.diversify.utils.AmplificationChecker; +import fr.inria.diversify.utils.AmplificationHelper; +import fr.inria.diversify.utils.DSpotUtils; +import fr.inria.diversify.utils.sosiefier.InputConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import spoon.reflect.declaration.CtMethod; +import spoon.reflect.declaration.CtType; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Created by Benjamin DANGLOT + * benjamin.danglot@inria.fr + * on 15/12/17 + */ +public class ExecutedMutantSelector extends TakeAllSelector { + + private static final Logger LOGGER = LoggerFactory.getLogger(PitMutantScoreSelector.class); + + private List originalMutantExecuted; + + private Map, Set> mutantExecutedPerAmplifiedTestMethod; + + public ExecutedMutantSelector() { + this.mutantExecutedPerAmplifiedTestMethod = new HashMap<>(); + } + + public ExecutedMutantSelector(String pathToInitialResults) { + this.originalMutantExecuted = PitResultParser.parse(new File(pathToInitialResults)); + this.mutantExecutedPerAmplifiedTestMethod = new HashMap<>(); + } + + @Override + public void init(InputConfiguration configuration) { + super.init(configuration); + if (this.originalMutantExecuted == null) { + LOGGER.info("Computing executed mutants by the original test suite..."); + final AutomaticBuilder automaticBuilder = AutomaticBuilderFactory.getAutomaticBuilder(this.configuration); + automaticBuilder.runPit(this.program.getProgramDir()); + this.originalMutantExecuted = + PitResultParser.parseAndDelete( + this.program.getProgramDir() + automaticBuilder.getOutputDirectoryPit() + ).stream().filter(pitResult -> pitResult.getStateOfMutant() == PitResult.State.KILLED || + pitResult.getStateOfMutant() == PitResult.State.SURVIVED) + .collect(Collectors.toList()); + } + } + + @Override + public List> selectToAmplify(List> testsToBeAmplified) { + if (this.currentClassTestToBeAmplified == null && !testsToBeAmplified.isEmpty()) { + this.currentClassTestToBeAmplified = testsToBeAmplified.get(0).getDeclaringType(); + this.mutantExecutedPerAmplifiedTestMethod.clear(); + this.selectedAmplifiedTest.clear(); + } + return testsToBeAmplified; + } + + @Override + public List> selectToKeep(List> amplifiedTestToBeKept) { + if (amplifiedTestToBeKept.isEmpty()) { + return amplifiedTestToBeKept; + } + + // construct a test classes with only amplified tests + CtType clone = this.currentClassTestToBeAmplified.clone(); + clone.setParent(this.currentClassTestToBeAmplified.getParent()); + this.currentClassTestToBeAmplified.getMethods().stream() + .filter(AmplificationChecker::isTest) + .forEach(clone::removeMethod); + amplifiedTestToBeKept.forEach(clone::addMethod); + + // pretty print it + DSpotUtils.printJavaFileWithComment(clone, new File(DSpotCompiler.pathToTmpTestSources)); + + // then compile + final String classpath = AutomaticBuilderFactory + .getAutomaticBuilder(this.configuration) + .buildClasspath(this.program.getProgramDir()) + + AmplificationHelper.PATH_SEPARATOR + + this.program.getProgramDir() + "/" + this.program.getClassesDir() + + AmplificationHelper.PATH_SEPARATOR + "target/dspot/dependencies/" + + AmplificationHelper.PATH_SEPARATOR + + this.program.getProgramDir() + "/" + this.program.getTestClassesDir(); + + DSpotCompiler.compile(DSpotCompiler.pathToTmpTestSources, classpath, + new File(this.program.getProgramDir() + "/" + this.program.getTestClassesDir())); + + AutomaticBuilderFactory + .getAutomaticBuilder(this.configuration) + .runPit(this.program.getProgramDir(), clone); + final List pitResults = PitResultParser.parseAndDelete(program.getProgramDir() + AutomaticBuilderFactory + .getAutomaticBuilder(this.configuration).getOutputDirectoryPit()); + final int numberOfSelectedAmplifiedTest = pitResults.stream() + .filter(pitResult -> pitResult.getStateOfMutant() == PitResult.State.KILLED || + pitResult.getStateOfMutant() == PitResult.State.SURVIVED) + .filter(pitResult -> !this.originalMutantExecuted.contains(pitResult)) + .map(pitResult -> { + final CtMethod amplifiedTestThatExecuteMoreMutants = pitResult.getMethod(clone); + if (!this.mutantExecutedPerAmplifiedTestMethod.containsKey(amplifiedTestThatExecuteMoreMutants)) { + this.mutantExecutedPerAmplifiedTestMethod.put(amplifiedTestThatExecuteMoreMutants, new HashSet<>()); + } + this.mutantExecutedPerAmplifiedTestMethod.get(amplifiedTestThatExecuteMoreMutants).add(pitResult); + this.selectedAmplifiedTest.add(amplifiedTestThatExecuteMoreMutants); + return amplifiedTestThatExecuteMoreMutants; + }).collect(Collectors.toSet()).size(); + LOGGER.info("{} has been selected to amplify the test suite", numberOfSelectedAmplifiedTest); + return amplifiedTestToBeKept; + } +} diff --git a/dspot/src/main/java/fr/inria/stamp/JSAPOptions.java b/dspot/src/main/java/fr/inria/stamp/JSAPOptions.java index 8b85e6163..720502870 100644 --- a/dspot/src/main/java/fr/inria/stamp/JSAPOptions.java +++ b/dspot/src/main/java/fr/inria/stamp/JSAPOptions.java @@ -6,6 +6,7 @@ import fr.inria.diversify.dspot.selector.ChangeDetectorSelector; import fr.inria.diversify.dspot.selector.JacocoCoverageSelector; import fr.inria.diversify.dspot.selector.PitMutantScoreSelector; +import fr.inria.diversify.dspot.selector.ExecutedMutantSelector; import fr.inria.diversify.dspot.selector.TakeAllSelector; import fr.inria.diversify.dspot.selector.TestSelector; import fr.inria.diversify.mutant.pit.GradlePitTaskAndOptions; @@ -27,293 +28,299 @@ */ public class JSAPOptions { - private static final Logger LOGGER = LoggerFactory.getLogger(JSAPOptions.class); - - public static final JSAP options = initJSAP(); - - public enum SelectorEnum { - BranchCoverageTestSelector { - @Override - public TestSelector buildSelector() { - return new BranchCoverageTestSelector(10); - } - }, - PitMutantScoreSelector { - @Override - public TestSelector buildSelector() { - return new PitMutantScoreSelector(); - } - }, - JacocoCoverageSelector { - @Override - public TestSelector buildSelector() { - return new JacocoCoverageSelector(); - } - }, - TakeAllSelector { - @Override - public TestSelector buildSelector() { - return new TakeAllSelector(); - } - }, - ChangeDetectorSelector { - @Override - public TestSelector buildSelector() { - return new ChangeDetectorSelector(); - } - }; - public abstract TestSelector buildSelector(); - } - - public enum AmplifierEnum { - NumberLiteralAmplifier(new NumberLiteralAmplifier()), - MethodAdd(new TestMethodCallAdder()), - MethodRemove(new TestMethodCallRemover()), - TestDataMutator(new TestDataMutator()), - StatementAdd(new StatementAdd()), - None(null); - public final Amplifier amplifier; - - private AmplifierEnum(Amplifier amplifier) { - this.amplifier = amplifier; - } - } - - public static Configuration parse(String[] args) { - JSAPResult jsapConfig = options.parse(args); - Main.verbose = jsapConfig.getBoolean("verbose"); - if (!jsapConfig.success() || jsapConfig.getBoolean("help")) { - System.err.println(); - for (Iterator errs = jsapConfig.getErrorMessageIterator(); errs.hasNext(); ) { - System.err.println("Error: " + errs.next()); - } - showUsage(); - } else if (jsapConfig.getBoolean("example")) { - return null; - } - - if (jsapConfig.getString("path") == null) { - System.err.println("Error: Parameter 'path' is required."); - showUsage(); - } - - TestSelector testCriterion; - if (jsapConfig.getString("mutant") != null) { - if (!"PitMutantScoreSelector".equals(jsapConfig.getString("test-criterion"))) { - LOGGER.warn("You specify a path to mutations.csv but you did not specified the right test-criterion"); - LOGGER.warn("Forcing the Selector to PitMutantScoreSelector"); - } - testCriterion = new PitMutantScoreSelector(jsapConfig.getString("mutant")); - } else { - testCriterion = SelectorEnum.valueOf(jsapConfig.getString("test-criterion")).buildSelector(); - } - - MavenPitCommandAndOptions.descartesMode = jsapConfig.getBoolean("descartes"); - MavenPitCommandAndOptions.evosuiteMode = jsapConfig.getBoolean("evosuite"); - - GradlePitTaskAndOptions.descartesMode = jsapConfig.getBoolean("descartes"); - GradlePitTaskAndOptions.evosuiteMode = jsapConfig.getBoolean("evosuite"); - - TestRunnerFactory.useReflectiveTestRunner = jsapConfig.getBoolean("useReflection"); - - return new Configuration(jsapConfig.getString("path"), - buildAmplifiersFromString(jsapConfig.getStringArray("amplifiers")), - jsapConfig.getInt("iteration"), - Arrays.asList(jsapConfig.getStringArray("test")), - jsapConfig.getString("output"), - testCriterion, - Arrays.asList(jsapConfig.getStringArray("testCases")), - jsapConfig.getLong("seed"), - jsapConfig.getInt("timeOut"), - jsapConfig.getString("builder"), - jsapConfig.getString("mavenHome"), - jsapConfig.getInt("maxTestAmplified")); - } - - public static Amplifier stringToAmplifier(String amplifier) { - return AmplifierEnum.valueOf(amplifier).amplifier; - } - - public static List buildAmplifiersFromString(String[] amplifiersAsString) { - if (amplifiersAsString.length == 0 || "None".equals(amplifiersAsString[0])) { - return Collections.emptyList(); - } else { - return Arrays.stream(amplifiersAsString) - .map(JSAPOptions::stringToAmplifier) - .collect(Collectors.toList()); - } - } - - private static void showUsage() { - System.err.println(); - System.err.println("Usage: java -jar target/dspot-1.0.0-jar-with-dependencies.jar"); - System.err.println(" " + options.getUsage()); - System.err.println(); - System.err.println(options.getHelp()); - System.exit(1); - } - - private static JSAP initJSAP() { - JSAP jsap = new JSAP(); - - Switch help = new Switch("help"); - help.setLongFlag("help"); - help.setShortFlag('h'); - help.setHelp("shows this help"); - - Switch example = new Switch("example"); - example.setLongFlag("example"); - example.setShortFlag('e'); - example.setHelp("run the example of DSpot and leave"); - - FlaggedOption pathToConfigFile = new FlaggedOption("path"); - pathToConfigFile.setAllowMultipleDeclarations(false); - pathToConfigFile.setLongFlag("path-to-properties"); - pathToConfigFile.setShortFlag('p'); - pathToConfigFile.setStringParser(JSAP.STRING_PARSER); - pathToConfigFile.setUsageName("./path/to/myproject.properties"); - pathToConfigFile.setHelp("[mandatory] specify the path to the configuration file (format Java properties) of the target project (e.g. ./foo.properties)."); - - FlaggedOption amplifiers = new FlaggedOption("amplifiers"); - amplifiers.setList(true); - amplifiers.setLongFlag("amplifiers"); - amplifiers.setShortFlag('a'); - amplifiers.setStringParser(JSAP.STRING_PARSER); - amplifiers.setUsageName("Amplifier"); - amplifiers.setDefault("None"); - amplifiers.setHelp("[optional] specify the list of amplifiers to use. Default with all available amplifiers. Possible values: NumberLiteralAmplifier | MethodAdd | MethodRemove | TestDataMutator | StatementAdd | None"); - - FlaggedOption iteration = new FlaggedOption("iteration"); - iteration.setDefault("3"); - iteration.setStringParser(JSAP.INTEGER_PARSER); - iteration.setShortFlag('i'); - iteration.setLongFlag("iteration"); - iteration.setAllowMultipleDeclarations(false); - iteration.setHelp("[optional] specify the number of amplification iteration. A larger number may help to improve the test criterion (eg a larger number of iterations mah help to kill more mutants). This has an impact on the execution time: the more iterations, the longer DSpot runs."); - - FlaggedOption selector = new FlaggedOption("test-criterion"); - selector.setAllowMultipleDeclarations(false); - selector.setLongFlag("test-criterion"); - selector.setShortFlag('s'); - selector.setStringParser(JSAP.STRING_PARSER); - selector.setUsageName("PitMutantScoreSelector | BranchCoverageTestSelector | JacocoCoverageSelector | TakeAllSelector | ChangeDetectorSelector"); - selector.setHelp("[optional] specify the test adequacy criterion to be maximized with amplification"); - selector.setDefault("PitMutantScoreSelector"); - - FlaggedOption specificTestCase = new FlaggedOption("test"); - specificTestCase.setStringParser(JSAP.STRING_PARSER); - specificTestCase.setShortFlag('t'); - specificTestCase.setList(true); - specificTestCase.setAllowMultipleDeclarations(false); - specificTestCase.setLongFlag("test"); - specificTestCase.setDefault("all"); - specificTestCase.setUsageName("my.package.MyClassTest"); - specificTestCase.setHelp("[optional] fully qualified names of test classes to be amplified. If the value is all, DSpot will amplify the whole test suite. You can also use regex to describe a set of test classes."); - - FlaggedOption output = new FlaggedOption("output"); - output.setStringParser(JSAP.STRING_PARSER); - output.setAllowMultipleDeclarations(false); - output.setShortFlag('o'); - output.setLongFlag("output-path"); - output.setHelp("[optional] specify the output folder (default: dspot-report)"); - - FlaggedOption mutantScore = new FlaggedOption("mutant"); - mutantScore.setStringParser(JSAP.STRING_PARSER); - mutantScore.setAllowMultipleDeclarations(false); - mutantScore.setShortFlag('m'); - mutantScore.setLongFlag("path-pit-result"); - mutantScore.setUsageName("./path/to/mutations.csv"); - mutantScore.setHelp("[optional, expert mode] specify the path to the .csv of the original result of Pit Test. If you use this option the selector will be forced to PitMutantScoreSelector"); - - FlaggedOption testCases = new FlaggedOption("testCases"); - testCases.setList(true); - testCases.setAllowMultipleDeclarations(false); - testCases.setLongFlag("cases"); - testCases.setShortFlag('c'); - testCases.setStringParser(JSAP.STRING_PARSER); - testCases.setHelp("specify the test cases to amplify"); - - FlaggedOption seed = new FlaggedOption("seed"); - seed.setStringParser(JSAP.LONG_PARSER); - seed.setLongFlag("randomSeed"); - seed.setShortFlag('r'); - seed.setUsageName("long integer"); - seed.setHelp("specify a seed for the random object (used for all randomized operation)"); - seed.setDefault("23"); - - FlaggedOption timeOut = new FlaggedOption("timeOut"); - timeOut.setStringParser(JSAP.INTEGER_PARSER); - timeOut.setLongFlag("timeOut"); - timeOut.setShortFlag('v'); - timeOut.setUsageName("long integer"); - timeOut.setHelp("specify the timeout value of the degenerated tests in millisecond"); - timeOut.setDefault("10000"); - - FlaggedOption automaticBuilder = new FlaggedOption("builder"); - automaticBuilder.setStringParser(JSAP.STRING_PARSER); - automaticBuilder.setLongFlag("automatic-builder"); - automaticBuilder.setShortFlag('b'); - automaticBuilder.setUsageName("MavenBuilder | GradleBuilder"); - automaticBuilder.setHelp("[optional] specify the automatic builder to build the project"); - automaticBuilder.setDefault("MavenBuilder"); - - FlaggedOption mavenHome = new FlaggedOption("mavenHome"); - mavenHome.setStringParser(JSAP.STRING_PARSER); - mavenHome.setLongFlag("maven-home"); - mavenHome.setShortFlag('j'); - mavenHome.setUsageName("path to maven home"); - mavenHome.setHelp("specify the path to the maven home"); - - Switch descartesMode = new Switch("descartes"); - descartesMode.setShortFlag('d'); - descartesMode.setLongFlag("descartes"); - - Switch evosuiteMode = new Switch("evosuite"); - evosuiteMode.setShortFlag('k'); - evosuiteMode.setLongFlag("evosuite"); - - Switch verbose = new Switch("verbose"); - verbose.setLongFlag("verbose"); - verbose.setDefault("false"); - - FlaggedOption maxTestAmplified = new FlaggedOption("maxTestAmplified"); - maxTestAmplified.setStringParser(JSAP.INTEGER_PARSER); - maxTestAmplified.setLongFlag("max-test-amplified"); - maxTestAmplified.setShortFlag('g'); - maxTestAmplified.setUsageName("integer"); - maxTestAmplified.setHelp("[optional] specify the maximum number of amplified test that dspot keep (before generating assertion)"); - maxTestAmplified.setDefault("200"); - - Switch useReflection = new Switch("useReflection"); - useReflection.setLongFlag("useReflection"); - useReflection.setDefault("false"); - useReflection.setHelp("Use a totally isolate test runner. WARNING this test runner does not support the usage of the JacocoCoverageSelector"); - - try { - jsap.registerParameter(pathToConfigFile); - jsap.registerParameter(amplifiers); - jsap.registerParameter(iteration); - jsap.registerParameter(selector); - jsap.registerParameter(maxTestAmplified); - jsap.registerParameter(descartesMode); - jsap.registerParameter(evosuiteMode); - jsap.registerParameter(specificTestCase); - jsap.registerParameter(testCases); - jsap.registerParameter(output); - jsap.registerParameter(mutantScore); - jsap.registerParameter(automaticBuilder); - jsap.registerParameter(useReflection); - jsap.registerParameter(mavenHome); - jsap.registerParameter(seed); - jsap.registerParameter(timeOut); - jsap.registerParameter(verbose); - jsap.registerParameter(example); - jsap.registerParameter(help); - } catch (JSAPException e) { - throw new RuntimeException(e); - } - - return jsap; - } + private static final Logger LOGGER = LoggerFactory.getLogger(JSAPOptions.class); + + public static final JSAP options = initJSAP(); + + public enum SelectorEnum { + BranchCoverageTestSelector { + @Override + public TestSelector buildSelector() { + return new BranchCoverageTestSelector(10); + } + }, + PitMutantScoreSelector { + @Override + public TestSelector buildSelector() { + return new PitMutantScoreSelector(); + } + }, + JacocoCoverageSelector { + @Override + public TestSelector buildSelector() { + return new JacocoCoverageSelector(); + } + }, + TakeAllSelector { + @Override + public TestSelector buildSelector() { + return new TakeAllSelector(); + } + }, + ExecutedMutantSelector { + @Override + public TestSelector buildSelector() { + return new ExecutedMutantSelector(); + } + }, + ChangeDetectorSelector { + @Override + public TestSelector buildSelector() { + return new ChangeDetectorSelector(); + } + }; + public abstract TestSelector buildSelector(); + } + + public enum AmplifierEnum { + NumberLiteralAmplifier(new NumberLiteralAmplifier()), + MethodAdd(new TestMethodCallAdder()), + MethodRemove(new TestMethodCallRemover()), + TestDataMutator(new TestDataMutator()), + StatementAdd(new StatementAdd()), + None(null); + public final Amplifier amplifier; + + private AmplifierEnum(Amplifier amplifier) { + this.amplifier = amplifier; + } + } + + public static Configuration parse(String[] args) { + JSAPResult jsapConfig = options.parse(args); + Main.verbose = jsapConfig.getBoolean("verbose"); + if (!jsapConfig.success() || jsapConfig.getBoolean("help")) { + System.err.println(); + for (Iterator errs = jsapConfig.getErrorMessageIterator(); errs.hasNext(); ) { + System.err.println("Error: " + errs.next()); + } + showUsage(); + } else if (jsapConfig.getBoolean("example")) { + return null; + } + + if (jsapConfig.getString("path") == null) { + System.err.println("Error: Parameter 'path' is required."); + showUsage(); + } + + TestSelector testCriterion; + if (jsapConfig.getString("mutant") != null) { + if (!"PitMutantScoreSelector".equals(jsapConfig.getString("test-criterion"))) { + LOGGER.warn("You specify a path to mutations.csv but you did not specified the right test-criterion"); + LOGGER.warn("Forcing the Selector to PitMutantScoreSelector"); + } + testCriterion = new PitMutantScoreSelector(jsapConfig.getString("mutant")); + } else { + testCriterion = SelectorEnum.valueOf(jsapConfig.getString("test-criterion")).buildSelector(); + } + + MavenPitCommandAndOptions.descartesMode = jsapConfig.getBoolean("descartes"); + MavenPitCommandAndOptions.evosuiteMode = jsapConfig.getBoolean("evosuite"); + + GradlePitTaskAndOptions.descartesMode = jsapConfig.getBoolean("descartes"); + GradlePitTaskAndOptions.evosuiteMode = jsapConfig.getBoolean("evosuite"); + + TestRunnerFactory.useReflectiveTestRunner = jsapConfig.getBoolean("useReflection"); + + return new Configuration(jsapConfig.getString("path"), + buildAmplifiersFromString(jsapConfig.getStringArray("amplifiers")), + jsapConfig.getInt("iteration"), + Arrays.asList(jsapConfig.getStringArray("test")), + jsapConfig.getString("output"), + testCriterion, + Arrays.asList(jsapConfig.getStringArray("testCases")), + jsapConfig.getLong("seed"), + jsapConfig.getInt("timeOut"), + jsapConfig.getString("builder"), + jsapConfig.getString("mavenHome"), + jsapConfig.getInt("maxTestAmplified")); + } + + public static Amplifier stringToAmplifier(String amplifier) { + return AmplifierEnum.valueOf(amplifier).amplifier; + } + + public static List buildAmplifiersFromString(String[] amplifiersAsString) { + if (amplifiersAsString.length == 0 || "None".equals(amplifiersAsString[0])) { + return Collections.emptyList(); + } else { + return Arrays.stream(amplifiersAsString) + .map(JSAPOptions::stringToAmplifier) + .collect(Collectors.toList()); + } + } + + private static void showUsage() { + System.err.println(); + System.err.println("Usage: java -jar target/dspot-1.0.0-jar-with-dependencies.jar"); + System.err.println(" " + options.getUsage()); + System.err.println(); + System.err.println(options.getHelp()); + System.exit(1); + } + + private static JSAP initJSAP() { + JSAP jsap = new JSAP(); + + Switch help = new Switch("help"); + help.setLongFlag("help"); + help.setShortFlag('h'); + help.setHelp("shows this help"); + + Switch example = new Switch("example"); + example.setLongFlag("example"); + example.setShortFlag('e'); + example.setHelp("run the example of DSpot and leave"); + + FlaggedOption pathToConfigFile = new FlaggedOption("path"); + pathToConfigFile.setAllowMultipleDeclarations(false); + pathToConfigFile.setLongFlag("path-to-properties"); + pathToConfigFile.setShortFlag('p'); + pathToConfigFile.setStringParser(JSAP.STRING_PARSER); + pathToConfigFile.setUsageName("./path/to/myproject.properties"); + pathToConfigFile.setHelp("[mandatory] specify the path to the configuration file (format Java properties) of the target project (e.g. ./foo.properties)."); + + FlaggedOption amplifiers = new FlaggedOption("amplifiers"); + amplifiers.setList(true); + amplifiers.setLongFlag("amplifiers"); + amplifiers.setShortFlag('a'); + amplifiers.setStringParser(JSAP.STRING_PARSER); + amplifiers.setUsageName("Amplifier"); + amplifiers.setDefault("None"); + amplifiers.setHelp("[optional] specify the list of amplifiers to use. Default with all available amplifiers. Possible values: NumberLiteralAmplifier | MethodAdd | MethodRemove | TestDataMutator | StatementAdd | None"); + + FlaggedOption iteration = new FlaggedOption("iteration"); + iteration.setDefault("3"); + iteration.setStringParser(JSAP.INTEGER_PARSER); + iteration.setShortFlag('i'); + iteration.setLongFlag("iteration"); + iteration.setAllowMultipleDeclarations(false); + iteration.setHelp("[optional] specify the number of amplification iteration. A larger number may help to improve the test criterion (eg a larger number of iterations mah help to kill more mutants). This has an impact on the execution time: the more iterations, the longer DSpot runs."); + + FlaggedOption selector = new FlaggedOption("test-criterion"); + selector.setAllowMultipleDeclarations(false); + selector.setLongFlag("test-criterion"); + selector.setShortFlag('s'); + selector.setStringParser(JSAP.STRING_PARSER); + selector.setUsageName("PitMutantScoreSelector | ExecutedMutantSelector | BranchCoverageTestSelector | JacocoCoverageSelector | TakeAllSelector | ChangeDetectorSelector"); + selector.setHelp("[optional] specify the test adequacy criterion to be maximized with amplification"); + selector.setDefault("PitMutantScoreSelector"); + + FlaggedOption specificTestCase = new FlaggedOption("test"); + specificTestCase.setStringParser(JSAP.STRING_PARSER); + specificTestCase.setShortFlag('t'); + specificTestCase.setList(true); + specificTestCase.setAllowMultipleDeclarations(false); + specificTestCase.setLongFlag("test"); + specificTestCase.setDefault("all"); + specificTestCase.setUsageName("my.package.MyClassTest"); + specificTestCase.setHelp("[optional] fully qualified names of test classes to be amplified. If the value is all, DSpot will amplify the whole test suite. You can also use regex to describe a set of test classes."); + + FlaggedOption output = new FlaggedOption("output"); + output.setStringParser(JSAP.STRING_PARSER); + output.setAllowMultipleDeclarations(false); + output.setShortFlag('o'); + output.setLongFlag("output-path"); + output.setHelp("[optional] specify the output folder (default: dspot-report)"); + + FlaggedOption mutantScore = new FlaggedOption("mutant"); + mutantScore.setStringParser(JSAP.STRING_PARSER); + mutantScore.setAllowMultipleDeclarations(false); + mutantScore.setShortFlag('m'); + mutantScore.setLongFlag("path-pit-result"); + mutantScore.setUsageName("./path/to/mutations.csv"); + mutantScore.setHelp("[optional, expert mode] specify the path to the .csv of the original result of Pit Test. If you use this option the selector will be forced to PitMutantScoreSelector"); + + FlaggedOption testCases = new FlaggedOption("testCases"); + testCases.setList(true); + testCases.setAllowMultipleDeclarations(false); + testCases.setLongFlag("cases"); + testCases.setShortFlag('c'); + testCases.setStringParser(JSAP.STRING_PARSER); + testCases.setHelp("specify the test cases to amplify"); + + FlaggedOption seed = new FlaggedOption("seed"); + seed.setStringParser(JSAP.LONG_PARSER); + seed.setLongFlag("randomSeed"); + seed.setShortFlag('r'); + seed.setUsageName("long integer"); + seed.setHelp("specify a seed for the random object (used for all randomized operation)"); + seed.setDefault("23"); + + FlaggedOption timeOut = new FlaggedOption("timeOut"); + timeOut.setStringParser(JSAP.INTEGER_PARSER); + timeOut.setLongFlag("timeOut"); + timeOut.setShortFlag('v'); + timeOut.setUsageName("long integer"); + timeOut.setHelp("specify the timeout value of the degenerated tests in millisecond"); + timeOut.setDefault("10000"); + + FlaggedOption automaticBuilder = new FlaggedOption("builder"); + automaticBuilder.setStringParser(JSAP.STRING_PARSER); + automaticBuilder.setLongFlag("automatic-builder"); + automaticBuilder.setShortFlag('b'); + automaticBuilder.setUsageName("MavenBuilder | GradleBuilder"); + automaticBuilder.setHelp("[optional] specify the automatic builder to build the project"); + automaticBuilder.setDefault("MavenBuilder"); + + FlaggedOption mavenHome = new FlaggedOption("mavenHome"); + mavenHome.setStringParser(JSAP.STRING_PARSER); + mavenHome.setLongFlag("maven-home"); + mavenHome.setShortFlag('j'); + mavenHome.setUsageName("path to maven home"); + mavenHome.setHelp("specify the path to the maven home"); + + Switch descartesMode = new Switch("descartes"); + descartesMode.setShortFlag('d'); + descartesMode.setLongFlag("descartes"); + + Switch evosuiteMode = new Switch("evosuite"); + evosuiteMode.setShortFlag('k'); + evosuiteMode.setLongFlag("evosuite"); + + Switch verbose = new Switch("verbose"); + verbose.setLongFlag("verbose"); + verbose.setDefault("false"); + + FlaggedOption maxTestAmplified = new FlaggedOption("maxTestAmplified"); + maxTestAmplified.setStringParser(JSAP.INTEGER_PARSER); + maxTestAmplified.setLongFlag("max-test-amplified"); + maxTestAmplified.setShortFlag('g'); + maxTestAmplified.setUsageName("integer"); + maxTestAmplified.setHelp("[optional] specify the maximum number of amplified test that dspot keep (before generating assertion)"); + maxTestAmplified.setDefault("200"); + + Switch useReflection = new Switch("useReflection"); + useReflection.setLongFlag("useReflection"); + useReflection.setDefault("false"); + useReflection.setHelp("Use a totally isolate test runner. WARNING this test runner does not support the usage of the JacocoCoverageSelector"); + + try { + jsap.registerParameter(pathToConfigFile); + jsap.registerParameter(amplifiers); + jsap.registerParameter(iteration); + jsap.registerParameter(selector); + jsap.registerParameter(maxTestAmplified); + jsap.registerParameter(descartesMode); + jsap.registerParameter(evosuiteMode); + jsap.registerParameter(specificTestCase); + jsap.registerParameter(testCases); + jsap.registerParameter(output); + jsap.registerParameter(mutantScore); + jsap.registerParameter(automaticBuilder); + jsap.registerParameter(useReflection); + jsap.registerParameter(mavenHome); + jsap.registerParameter(seed); + jsap.registerParameter(timeOut); + jsap.registerParameter(verbose); + jsap.registerParameter(example); + jsap.registerParameter(help); + } catch (JSAPException e) { + throw new RuntimeException(e); + } + + return jsap; + } } \ No newline at end of file diff --git a/dspot/src/test/java/fr/inria/diversify/dspot/selector/ExecutedMutantSelectorTest.java b/dspot/src/test/java/fr/inria/diversify/dspot/selector/ExecutedMutantSelectorTest.java new file mode 100644 index 000000000..7c366ca68 --- /dev/null +++ b/dspot/src/test/java/fr/inria/diversify/dspot/selector/ExecutedMutantSelectorTest.java @@ -0,0 +1,78 @@ +package fr.inria.diversify.dspot.selector; + +import fr.inria.diversify.Utils; +import fr.inria.diversify.automaticbuilder.AutomaticBuilderFactory; +import fr.inria.diversify.dspot.DSpot; +import fr.inria.diversify.dspot.amplifier.TestDataMutator; +import fr.inria.diversify.dspot.support.DSpotCompiler; +import fr.inria.diversify.mutant.pit.PitResult; +import fr.inria.diversify.mutant.pit.PitResultParser; +import fr.inria.diversify.utils.AmplificationHelper; +import fr.inria.diversify.utils.DSpotUtils; +import fr.inria.stamp.Main; +import org.junit.Before; +import org.junit.Test; +import spoon.reflect.declaration.CtType; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertTrue; + +/** + * Created by Benjamin DANGLOT + * benjamin.danglot@inria.fr + * on 15/12/17 + */ +public class ExecutedMutantSelectorTest { + + @Before + public void setUp() throws Exception { + Utils.reset(); + Utils.init("src/test/resources/test-projects/test-projects.properties"); + } + + @Test + public void test() throws Exception { + + // pre computing the number of executed mutants... + Main.verbose = true; + AutomaticBuilderFactory.getAutomaticBuilder(Utils.getInputConfiguration()) + .runPit(Utils.getInputProgram().getProgramDir()); + final List pitResults = PitResultParser.parseAndDelete(Utils.getInputProgram().getProgramDir() + "target/pit-reports/"); + + final ExecutedMutantSelector testSelector = new ExecutedMutantSelector(); + DSpot dspot = new DSpot(Utils.getInputConfiguration(), 1, Collections.singletonList(new TestDataMutator()), testSelector); + final CtType amplifyTest = dspot.amplifyTest(Utils.findClass("example.TestSuiteExample"), + Collections.singletonList(Utils.findMethod("example.TestSuiteExample", "test8"))); + + // pretty print it + DSpotUtils.printJavaFileWithComment(amplifyTest, new File(DSpotCompiler.pathToTmpTestSources)); + + // then compile + final String classpath = AutomaticBuilderFactory + .getAutomaticBuilder(Utils.getInputConfiguration()) + .buildClasspath(Utils.getInputProgram().getProgramDir()) + + AmplificationHelper.PATH_SEPARATOR + + Utils.getInputProgram().getProgramDir() + "/" + Utils.getInputProgram().getClassesDir() + + AmplificationHelper.PATH_SEPARATOR + "target/dspot/dependencies/" + + AmplificationHelper.PATH_SEPARATOR + + Utils.getInputProgram().getProgramDir() + "/" + Utils.getInputProgram().getTestClassesDir(); + + DSpotCompiler.compile(DSpotCompiler.pathToTmpTestSources, classpath, + new File(Utils.getInputProgram().getProgramDir() + "/" + Utils.getInputProgram().getTestClassesDir())); + + AutomaticBuilderFactory.getAutomaticBuilder(Utils.getInputConfiguration()) + .runPit(Utils.getInputProgram().getProgramDir()); + final List amplifiedPitResults = PitResultParser.parseAndDelete(Utils.getInputProgram().getProgramDir() + "target/pit-reports/"); + + assertTrue(pitResults.stream() + .filter(pitResult -> pitResult.getStateOfMutant() == PitResult.State.KILLED || + pitResult.getStateOfMutant() == PitResult.State.SURVIVED).count() < + amplifiedPitResults.stream() + .filter(pitResult -> pitResult.getStateOfMutant() == PitResult.State.KILLED || + pitResult.getStateOfMutant() == PitResult.State.SURVIVED).count()); + Main.verbose = false; + } +}