Skip to content

Commit

Permalink
Merge pull request #1369 from hcoles/feature/dry_run_support
Browse files Browse the repository at this point in the history
Feature/dry run support
  • Loading branch information
hcoles authored Dec 16, 2024
2 parents 116ef37 + 5a41bf9 commit 175105c
Show file tree
Hide file tree
Showing 21 changed files with 264 additions and 51 deletions.
13 changes: 8 additions & 5 deletions pitest-ant/src/main/java/org/pitest/ant/PitestTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -268,16 +268,19 @@ public void setArgLine(String value) {
this.setOption(ConfigOption.ARG_LINE, value);
}

public void setUseClasspathJar(String value) {
this.setOption(ConfigOption.USE_CLASSPATH_JAR, value);
}

public void setDryRun(String value) {
this.setOption(ConfigOption.DRY_RUN, value);
}

private void setOption(final ConfigOption option, final String value) {
if (!"".equals(value)) {
this.options.put(option.getParamName(), value);
}
}

public void setUseClasspathJar(String value) {
this.setOption(ConfigOption.USE_CLASSPATH_JAR, value);
}



}
13 changes: 13 additions & 0 deletions pitest-ant/src/test/java/org/pitest/ant/PitestTaskTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,19 @@ public void passesArgLineToJavaTask() {
verify(this.arg).setValue("--argLine=-Dfoo=\"bar\"");
}

@Test
public void passesDryRunFlagToJavaTask() {
this.pitestTask.setDryRun("true");
this.pitestTask.execute(this.java);
verify(this.arg).setValue("--dryRun=true");
}

@Test
public void defaultDryRunToFalse() {
this.pitestTask.execute(this.java);
verify(this.arg, never()).setValue("--dryRun=true");
}

private static class PathMatcher implements ArgumentMatcher<Path> {

private final String[] expectedPaths;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.pitest.classpath.ClassPath;
import org.pitest.functional.FCollection;
import org.pitest.mutationtest.config.ConfigOption;
import org.pitest.mutationtest.config.ExecutionMode;
import org.pitest.mutationtest.config.ReportOptions;
import org.pitest.testapi.TestGroupConfig;
import org.pitest.util.Glob;
Expand Down Expand Up @@ -54,6 +55,7 @@
import static org.pitest.mutationtest.config.ConfigOption.CLASSPATH_FILE;
import static org.pitest.mutationtest.config.ConfigOption.CODE_PATHS;
import static org.pitest.mutationtest.config.ConfigOption.COVERAGE_THRESHOLD;
import static org.pitest.mutationtest.config.ConfigOption.DRY_RUN;
import static org.pitest.mutationtest.config.ConfigOption.EXCLUDED_CLASSES;
import static org.pitest.mutationtest.config.ConfigOption.EXCLUDED_GROUPS;
import static org.pitest.mutationtest.config.ConfigOption.EXCLUDED_METHOD;
Expand Down Expand Up @@ -152,6 +154,7 @@ public class OptionsParser {
private final OptionSpec<File> projectBaseSpec;
private final OptionSpec<String> inputEncoding;
private final OptionSpec<String> outputEncoding;
private final ArgumentAcceptingOptionSpec<Boolean> dryRunSpec;

public OptionsParser(Predicate<String> dependencyFilter) {

Expand Down Expand Up @@ -407,6 +410,12 @@ public OptionsParser(Predicate<String> dependencyFilter) {
this.projectBaseSpec = parserAccepts(PROJECT_BASE)
.withRequiredArg().ofType(File.class);

this.dryRunSpec = parserAccepts(DRY_RUN)
.withOptionalArg()
.ofType(Boolean.class)
.defaultsTo(VERBOSE.getDefault(Boolean.class))
.describedAs("enable or disable dry run mode");

}

private OptionSpecBuilder parserAccepts(final ConfigOption option) {
Expand Down Expand Up @@ -448,21 +457,16 @@ private ParseResult parseCommandLine(final ReportOptions data,
data.setArgLine(this.argLine.value(userArgs));

data.addChildJVMArgs(this.jvmArgsProcessor.values(userArgs));
data.setFullMutationMatrix(
(userArgs.has(this.fullMutationMatrixSpec) && !userArgs.hasArgument(this.fullMutationMatrixSpec))
|| this.fullMutationMatrixSpec.value(userArgs));
data.setDetectInlinedCode(
(userArgs.has(this.detectInlinedCode) && !userArgs.hasArgument(this.detectInlinedCode))
|| this.detectInlinedCode.value(userArgs));
data.setIncludeLaunchClasspath(
(userArgs.has(this.includeLaunchClasspathSpec) && !userArgs.hasArgument(this.includeLaunchClasspathSpec))
|| this.includeLaunchClasspathSpec.value(userArgs));
data.setUseClasspathJar(
(userArgs.has(this.useClasspathJarSpec) && !userArgs.hasArgument(this.useClasspathJarSpec))
|| this.useClasspathJarSpec.value(userArgs));
data.setShouldCreateTimestampedReports(
(userArgs.has(this.timestampedReportsSpec) && !userArgs.hasArgument(this.timestampedReportsSpec))
|| this.timestampedReportsSpec.value(userArgs));
data.setFullMutationMatrix(booleanValue(fullMutationMatrixSpec, userArgs));

data.setDetectInlinedCode(booleanValue(detectInlinedCode, userArgs));

data.setIncludeLaunchClasspath(booleanValue(includeLaunchClasspathSpec, userArgs));

data.setUseClasspathJar(booleanValue(useClasspathJarSpec, userArgs));

data.setShouldCreateTimestampedReports(booleanValue(timestampedReportsSpec, userArgs));

data.setNumberOfThreads(this.threadsSpec.value(userArgs));
data.setTimeoutFactor(this.timeoutFactorSpec.value(userArgs));
data.setTimeoutConstant(this.timeoutConstSpec.value(userArgs));
Expand All @@ -475,12 +479,10 @@ private ParseResult parseCommandLine(final ReportOptions data,
configureVerbosity(data, userArgs);

data.addOutputFormats(this.outputFormatSpec.values(userArgs));
data.setFailWhenNoMutations(
(userArgs.has(this.failWhenNoMutations) && !userArgs.hasArgument(this.failWhenNoMutations))
|| this.failWhenNoMutations.value(userArgs));
data.setSkipFailingTests(
(userArgs.has(this.skipFailingTests) && !userArgs.hasArgument(this.skipFailingTests))
|| this.skipFailingTests.value(userArgs));
data.setFailWhenNoMutations(booleanValue(failWhenNoMutations, userArgs));

data.setSkipFailingTests(booleanValue(skipFailingTests, userArgs));

data.setCodePaths(this.codePaths.values(userArgs));
data.setMutationUnitSize(this.mutationUnitSizeSpec.value(userArgs));
data.setHistoryInputLocation(this.historyInputSpec.value(userArgs));
Expand All @@ -491,9 +493,7 @@ private ParseResult parseCommandLine(final ReportOptions data,
data.setCoverageThreshold(this.coverageThreshHoldSpec.value(userArgs));
data.setMutationEngine(this.mutationEngine.value(userArgs));
data.setFreeFormProperties(listToProperties(this.pluginPropertiesSpec.values(userArgs)));
data.setExportLineCoverage(
(userArgs.has(this.exportLineCoverageSpec) && !userArgs.hasArgument(this.exportLineCoverageSpec))
|| this.exportLineCoverageSpec.value(userArgs));
data.setExportLineCoverage(booleanValue(exportLineCoverageSpec, userArgs));

setClassPath(userArgs, data);

Expand All @@ -506,6 +506,8 @@ private ParseResult parseCommandLine(final ReportOptions data,

setEncoding(data, userArgs);

configureExecutionMode(data, userArgs);

if (userArgs.has(projectBaseSpec)) {
data.setProjectBase(this.projectBaseSpec.value(userArgs).toPath());
}
Expand All @@ -523,16 +525,21 @@ private void setEncoding(ReportOptions data, OptionSet userArgs) {
}

private void configureVerbosity(ReportOptions data, OptionSet userArgs) {
boolean isVerbose = (userArgs.has(this.verboseSpec) && !userArgs.hasArgument(this.verboseSpec))
|| this.verboseSpec.value(userArgs);
if (isVerbose) {
if (booleanValue(verboseSpec, userArgs)) {
data.setVerbosity(Verbosity.VERBOSE);
} else {
data.setVerbosity(Verbosity.fromString(this.verbositySpec.value(userArgs)));
}

}

private void configureExecutionMode(ReportOptions data, OptionSet userArgs) {
if (booleanValue(dryRunSpec, userArgs)) {
data.setExecutionMode(ExecutionMode.DRY_RUN);
}
}


private void setClassPath(final OptionSet userArgs, final ReportOptions data) {

final List<String> elements = new ArrayList<>();
Expand Down Expand Up @@ -588,5 +595,9 @@ public void printHelp() {
}
}

private boolean booleanValue(ArgumentAcceptingOptionSpec<Boolean> spec, OptionSet userArgs) {
return (userArgs.has(spec) && !userArgs.hasArgument(spec))
|| spec.value(userArgs);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.pitest.mutationtest.config.ConfigOption;
import org.pitest.mutationtest.config.ExecutionMode;
import org.pitest.mutationtest.config.PluginServices;
import org.pitest.mutationtest.config.ReportOptions;
import org.pitest.mutationtest.engine.gregor.GregorMutationEngine;
Expand Down Expand Up @@ -703,6 +704,34 @@ public void parsesOutputEncoding() {
assertThat(actual.getOutputEncoding()).isEqualTo(StandardCharsets.US_ASCII);
}

@Test
public void defaultsToNormalExecution() {
final ReportOptions actual = parseAddingRequiredArgs("");
assertThat(actual.mode()).isEqualTo(ExecutionMode.NORMAL);
}

@Test
public void parsesShortFormDryRun() {
final ReportOptions actual = parseAddingRequiredArgs(
"--dryRun");
assertThat(actual.mode()).isEqualTo(ExecutionMode.DRY_RUN);
}

@Test
public void parsesLongFormDryRunFalse() {
ReportOptions actual = parseAddingRequiredArgs(
"--dryRun=false");
assertThat(actual.mode()).isEqualTo(ExecutionMode.NORMAL);
}

@Test
public void parsesLongFormDryRunTrue() {
ReportOptions actual = parseAddingRequiredArgs(
"--dryRun=true");
assertThat(actual.mode()).isEqualTo(ExecutionMode.DRY_RUN);
}


private String getNonCanonicalGregorEngineClassPath() {
final String gregorEngineClassPath = GregorMutationEngine.class
.getProtectionDomain().getCodeSource().getLocation().getFile();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,16 @@
public interface History {

void initialize();

default Predicate<ClassName> limitTests(List<MutationDetails> mutants) {
return limitTests();
}

@Deprecated
default Predicate<ClassName> limitTests() {
return c -> true;
}

void processCoverage(CoverageDatabase coverageData);

List<MutationResult> analyse(List<MutationDetails> mutationsForClasses);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.pitest.mutationtest.build;

import org.pitest.mutationtest.DetectionStatus;
import org.pitest.mutationtest.MutationMetaData;
import org.pitest.mutationtest.MutationResult;
import org.pitest.mutationtest.MutationStatusTestPair;
import org.pitest.mutationtest.engine.MutationDetails;
import org.pitest.util.Log;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class DryRunUnit implements MutationAnalysisUnit {
private static final Logger LOG = Log.getLogger();

private final Collection<MutationDetails> mutations;

public DryRunUnit(final Collection<MutationDetails> mutations) {
this.mutations = mutations;
}

@Override
public MutationMetaData call() throws Exception {
LOG.fine("Not analysing " + this.mutations.size()
+ " mutations as in dry run");
List<MutationResult> results = mutations.stream()
.map(m -> new MutationResult(m, noAnalysis()))
.collect(Collectors.toList());
return new MutationMetaData(results);

}

private MutationStatusTestPair noAnalysis() {
return MutationStatusTestPair.notAnalysed(0, DetectionStatus.NOT_STARTED, Collections.emptyList());
}

@Override
public int priority() {
return Integer.MAX_VALUE;
}

@Override
public Collection<MutationDetails> mutants() {
return mutations;
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package org.pitest.mutationtest.build;

import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.pitest.mutationtest.MutationMetaData;
import org.pitest.mutationtest.MutationResult;
import org.pitest.mutationtest.engine.MutationDetails;
import org.pitest.util.Log;

public class KnownStatusMutationTestUnit implements MutationAnalysisUnit {
Expand All @@ -30,4 +33,11 @@ public int priority() {
return Integer.MAX_VALUE;
}

@Override
public Collection<MutationDetails> mutants() {
return mutations.stream()
.map(MutationResult::getDetails)
.collect(Collectors.toList());
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.pitest.mutationtest.build;

import java.util.Collection;
import java.util.concurrent.Callable;

import org.pitest.mutationtest.MutationMetaData;
import org.pitest.mutationtest.engine.MutationDetails;

/**
* A unit of mutation analysis
Expand All @@ -11,4 +13,5 @@ public interface MutationAnalysisUnit extends Callable<MutationMetaData> {

int priority();

Collection<MutationDetails> mutants();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.pitest.mutationtest.History;
import org.pitest.mutationtest.DetectionStatus;
import org.pitest.mutationtest.MutationResult;
import org.pitest.mutationtest.config.ExecutionMode;
import org.pitest.mutationtest.engine.MutationDetails;
import org.pitest.mutationtest.engine.MutationIdentifier;

Expand All @@ -31,16 +32,19 @@

public class MutationTestBuilder {

private final ExecutionMode mode;
private final MutationSource mutationSource;
private final History analyser;
private final WorkerFactory workerFactory;
private final MutationGrouper grouper;

public MutationTestBuilder(final WorkerFactory workerFactory,
final History analyser,
final MutationSource mutationSource,
final MutationGrouper grouper) {
public MutationTestBuilder(ExecutionMode mode,
WorkerFactory workerFactory,
History analyser,
MutationSource mutationSource,
MutationGrouper grouper) {

this.mode = mode;
this.mutationSource = mutationSource;
this.analyser = analyser;
this.workerFactory = workerFactory;
Expand Down Expand Up @@ -109,7 +113,10 @@ private MutationAnalysisUnit makePreAnalysedUnit(
}

private MutationAnalysisUnit makeUnanalysedUnit(
final Collection<MutationDetails> needAnalysis) {
Collection<MutationDetails> needAnalysis) {
if (mode == ExecutionMode.DRY_RUN) {
return new DryRunUnit(needAnalysis);
}
return new MutationTestUnit(needAnalysis, this.workerFactory);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public int priority() {
return this.availableMutations.size();
}

@Override
public Collection<MutationDetails> mutants() {
return availableMutations;
}

private void runTestsInSeperateProcess(final MutationStatusMap mutations)
throws IOException, InterruptedException {
while (mutations.hasUnrunMutations()) {
Expand Down
Loading

0 comments on commit 175105c

Please sign in to comment.