From 21450d9a9276403674989e57255114d76dad0a66 Mon Sep 17 00:00:00 2001 From: Henry Coles Date: Mon, 18 Sep 2023 11:17:27 +0100 Subject: [PATCH] record history before result interceptor manipulation --- .../CompoundMutationResultInterceptor.java | 10 ++++- .../MutationResultInterceptor.java | 4 ++ .../mutationtest/config/SettingsFactory.java | 3 +- .../incremental/HistoryListener.java | 6 +-- .../incremental/HistoryResultInterceptor.java | 33 ++++++++++++++ .../mutationtest/tooling/EntryPoint.java | 3 +- ...CompoundMutationResultInterceptorTest.java | 15 ++++--- .../incremental/HistoryListenerTest.java | 14 ++---- .../HistoryResultInterceptorTest.java | 43 +++++++++++++++++++ 9 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 pitest-entry/src/main/java/org/pitest/mutationtest/incremental/HistoryResultInterceptor.java create mode 100644 pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryResultInterceptorTest.java diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/CompoundMutationResultInterceptor.java b/pitest-entry/src/main/java/org/pitest/mutationtest/CompoundMutationResultInterceptor.java index a2172880f..004316678 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/CompoundMutationResultInterceptor.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/CompoundMutationResultInterceptor.java @@ -1,6 +1,7 @@ package org.pitest.mutationtest; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -9,7 +10,14 @@ public class CompoundMutationResultInterceptor implements MutationResultIntercep private final List interceptors; public CompoundMutationResultInterceptor(List interceptors) { - this.interceptors = interceptors; + this.interceptors = interceptors.stream() + .sorted(Comparator.comparing(MutationResultInterceptor::priority)) + .collect(Collectors.toList()); + } + + public CompoundMutationResultInterceptor add(MutationResultInterceptor extra) { + interceptors.add(0, extra); + return this; } @Override diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResultInterceptor.java b/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResultInterceptor.java index 5896f3b16..907d2a3c4 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResultInterceptor.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResultInterceptor.java @@ -29,4 +29,8 @@ default Collection remaining() { default String description() { return ""; } + + default int priority() { + return 10; + } } diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/config/SettingsFactory.java b/pitest-entry/src/main/java/org/pitest/mutationtest/config/SettingsFactory.java index 9249697df..37442b37c 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/config/SettingsFactory.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/config/SettingsFactory.java @@ -14,7 +14,6 @@ import org.pitest.functional.FCollection; import org.pitest.mutationtest.CompoundMutationResultInterceptor; import org.pitest.mutationtest.MutationEngineFactory; -import org.pitest.mutationtest.MutationResultInterceptor; import org.pitest.mutationtest.MutationResultListenerFactory; import org.pitest.mutationtest.build.CompoundInterceptorFactory; import org.pitest.mutationtest.build.DefaultMutationGrouperFactory; @@ -190,7 +189,7 @@ public BuildVerifierFactory createVerifier() { return new CompoundBuildVerifierFactory(this.plugins.findVerifiers()); } - public MutationResultInterceptor getResultInterceptor() { + public CompoundMutationResultInterceptor getResultInterceptor() { return new CompoundMutationResultInterceptor(this.plugins.findMutationResultInterceptor()); } diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/HistoryListener.java b/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/HistoryListener.java index 249318151..c6d6a03d1 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/HistoryListener.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/HistoryListener.java @@ -2,7 +2,6 @@ import org.pitest.mutationtest.ClassMutationResults; import org.pitest.mutationtest.History; -import org.pitest.mutationtest.MutationResult; import org.pitest.mutationtest.MutationResultListener; public class HistoryListener implements MutationResultListener { @@ -20,10 +19,7 @@ public void runStart() { @Override public void handleMutationResult(final ClassMutationResults metaData) { - for (final MutationResult each : metaData.getMutations()) { - this.historyStore.recordResult(each); - } - + // results are collected in an interceptor to ensure we have unmodified mutants } @Override diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/HistoryResultInterceptor.java b/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/HistoryResultInterceptor.java new file mode 100644 index 000000000..74e0c4af8 --- /dev/null +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/incremental/HistoryResultInterceptor.java @@ -0,0 +1,33 @@ +package org.pitest.mutationtest.incremental; + +import org.pitest.mutationtest.ClassMutationResults; +import org.pitest.mutationtest.History; +import org.pitest.mutationtest.MutationResultInterceptor; + +import java.util.Collection; + +/** + * Records results for history before other interceptors are applied. Artificially + * added via hacky hard coding. + */ +public class HistoryResultInterceptor implements MutationResultInterceptor { + + private final History history; + + public HistoryResultInterceptor(History historyStore) { + this.history = historyStore; + } + + @Override + public Collection modify(Collection results) { + results.stream() + .flatMap(c -> c.getMutations().stream()) + .forEach(this.history::recordResult); + return results; + } + + @Override + public int priority() { + return 0; + } +} diff --git a/pitest-entry/src/main/java/org/pitest/mutationtest/tooling/EntryPoint.java b/pitest-entry/src/main/java/org/pitest/mutationtest/tooling/EntryPoint.java index f5eb1602f..856628e40 100644 --- a/pitest-entry/src/main/java/org/pitest/mutationtest/tooling/EntryPoint.java +++ b/pitest-entry/src/main/java/org/pitest/mutationtest/tooling/EntryPoint.java @@ -9,6 +9,7 @@ import org.pitest.coverage.execute.DefaultCoverageGenerator; import org.pitest.mutationtest.History; import org.pitest.mutationtest.HistoryFactory; +import org.pitest.mutationtest.incremental.HistoryResultInterceptor; import org.pitest.mutationtest.MutationResultListenerFactory; import org.pitest.mutationtest.config.PluginServices; import org.pitest.mutationtest.config.ReportOptions; @@ -120,7 +121,7 @@ public AnalysisResult execute(File baseDir, ReportOptions data, final History history = pickHistoryStore(code, data, maybeWriter, historyFactory); final MutationStrategies strategies = new MutationStrategies( - settings.createEngine(), history, coverageDatabase, reportFactory, settings.getResultInterceptor(), + settings.createEngine(), history, coverageDatabase, reportFactory, settings.getResultInterceptor().add(new HistoryResultInterceptor(history)), settings.createCoverageTransformer(code), reportOutput, settings.createVerifier().create(code)); diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/CompoundMutationResultInterceptorTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/CompoundMutationResultInterceptorTest.java index a0e19f0ca..f4246f74a 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/CompoundMutationResultInterceptorTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/CompoundMutationResultInterceptorTest.java @@ -4,7 +4,6 @@ import org.pitest.mutationtest.report.MutationTestResultMother; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -16,9 +15,9 @@ public class CompoundMutationResultInterceptorTest { @Test - public void chainsChildCallsToModify() { - MutationResultInterceptor a = appendToDesc("foo"); - MutationResultInterceptor b = appendToDesc("bar"); + public void chainsChildCallsToModifyByPriority() { + MutationResultInterceptor a = appendToDesc("bar", 1); + MutationResultInterceptor b = appendToDesc("foo", 0); CompoundMutationResultInterceptor underTest = new CompoundMutationResultInterceptor(asList(a,b)); @@ -28,6 +27,7 @@ public void chainsChildCallsToModify() { .allMatch(m -> m.getDetails().getDescription().endsWith("foobar")); } + @Test public void combinesRemainingResults() { MutationResultInterceptor a = hasResult(aMutationTestResult().withMutationDetails(aMutationDetail().withDescription("a"))); @@ -59,7 +59,7 @@ private static List someClassResults() { return asList(MutationTestResultMother.createClassResults(aMutationTestResult().build(2))); } - private MutationResultInterceptor appendToDesc(final String foo) { + private MutationResultInterceptor appendToDesc(final String foo, final int priority) { return new MutationResultInterceptor() { @Override public Collection modify(Collection results) { @@ -68,6 +68,11 @@ public Collection modify(Collection .collect(Collectors.toList()); } + @Override + public int priority() { + return priority; + } + private MutationResult appendToDesc(MutationResult result, String toAppend) { return new MutationResult(result.getDetails().withDescription(result.getDetails().getDescription() + toAppend) , result.getStatusTestPair()); diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryListenerTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryListenerTest.java index 20e86583d..4db5610e5 100644 --- a/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryListenerTest.java +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryListenerTest.java @@ -27,18 +27,10 @@ public void setUp() { } @Test - public void shouldRecordMutationResults() { - final MutationResult mr = makeResult(); - final ClassMutationResults metaData = MutationTestResultMother - .createClassResults(mr); - this.testee.handleMutationResult(metaData); - verify(this.store).recordResult(mr); + public void closesTheAttachedHistory() { + this.testee.runEnd(); + verify(this.store).close(); } - private MutationResult makeResult() { - return new MutationResult( - MutationTestResultMother.createDetails(), MutationStatusTestPair.notAnalysed(0, - DetectionStatus.KILLED)); - } } diff --git a/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryResultInterceptorTest.java b/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryResultInterceptorTest.java new file mode 100644 index 000000000..ddfb231eb --- /dev/null +++ b/pitest-entry/src/test/java/org/pitest/mutationtest/incremental/HistoryResultInterceptorTest.java @@ -0,0 +1,43 @@ +package org.pitest.mutationtest.incremental; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.pitest.mutationtest.ClassMutationResults; +import org.pitest.mutationtest.DetectionStatus; +import org.pitest.mutationtest.History; +import org.pitest.mutationtest.MutationResult; +import org.pitest.mutationtest.MutationStatusTestPair; +import org.pitest.mutationtest.report.MutationTestResultMother; + +import java.util.Collection; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; + +public class HistoryResultInterceptorTest { + private History store = Mockito.mock(History.class); + private HistoryResultInterceptor testee = new HistoryResultInterceptor(this.store); + + @Test + public void recordsMutationResults() { + final MutationResult mr = makeResult(); + final ClassMutationResults metaData = MutationTestResultMother + .createClassResults(mr); + Collection mutants = asList(metaData); + Collection actual = this.testee.modify(mutants); + verify(this.store).recordResult(mr); + assertThat(actual).isSameAs(mutants); + } + + + private MutationResult makeResult() { + return new MutationResult( + MutationTestResultMother.createDetails(), MutationStatusTestPair.notAnalysed(0, + DetectionStatus.KILLED)); + } + +} \ No newline at end of file