Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/dry run support #1369

Merged
merged 3 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading