From f181737c2baeab7ba64095249b4b2a3ba03671d2 Mon Sep 17 00:00:00 2001 From: Henry Coles Date: Thu, 5 Jan 2023 14:49:54 +0000 Subject: [PATCH] do not mutate fall through switch cases --- README.md | 4 ++ .../experimental/RemoveSwitchMutator.java | 6 +- .../experimental/RemoveSwitchMutatorTest.java | 55 +++++++++++++++++++ .../verifier/mutants/MutatorVerifier.java | 4 +- 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7fe479fb9..0cdabaee8 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ Read all about it at http://pitest.org ## Releases +## 1.10.5 (unreleased) + +* #1138 Do not mutate redundant fall through to default switch cases + ## 1.10.4 * #1134 Add `excludedRunners` parameter to command line interface and Ant diff --git a/pitest/src/main/java/org/pitest/mutationtest/engine/gregor/mutators/experimental/RemoveSwitchMutator.java b/pitest/src/main/java/org/pitest/mutationtest/engine/gregor/mutators/experimental/RemoveSwitchMutator.java index 4624af8a3..3f5a3ed4c 100644 --- a/pitest/src/main/java/org/pitest/mutationtest/engine/gregor/mutators/experimental/RemoveSwitchMutator.java +++ b/pitest/src/main/java/org/pitest/mutationtest/engine/gregor/mutators/experimental/RemoveSwitchMutator.java @@ -16,7 +16,7 @@ * default label. We change each label to the default label, thus removing it */ public class RemoveSwitchMutator implements MethodMutatorFactory { - // EXPERIMENTAL_REMOVE_SWITCH_MUTATOR; + private static final String REMOVE_SWITCH_MUTATOR_NAME = "EXPERIMENTAL_REMOVE_SWITCH_MUTATOR_"; private static final int GENERATE_FROM_INCLUDING = 0; private static final int GENERATE_UPTO_EXCLUDING = 100; @@ -69,7 +69,7 @@ private final class RemoveSwitchMethodVisitor extends MethodVisitor { @Override public void visitTableSwitchInsn(final int min, final int max, final Label defaultLabel, final Label... labels) { - if ((labels.length > RemoveSwitchMutator.this.key) && shouldMutate(value(min,max))) { + if ((labels.length > RemoveSwitchMutator.this.key) && labels[key] != defaultLabel && shouldMutate(value(min,max))) { final Label[] newLabels = labels.clone(); newLabels[RemoveSwitchMutator.this.key] = defaultLabel; super.visitTableSwitchInsn(min, max, defaultLabel, newLabels); @@ -81,7 +81,7 @@ public void visitTableSwitchInsn(final int min, final int max, @Override public void visitLookupSwitchInsn(final Label defaultLabel, final int[] ints, final Label[] labels) { - if ((labels.length > RemoveSwitchMutator.this.key) && shouldMutate(ints[key])) { + if ((labels.length > RemoveSwitchMutator.this.key) && labels[key] != defaultLabel && shouldMutate(ints[key])) { final Label[] newLabels = labels.clone(); newLabels[RemoveSwitchMutator.this.key] = defaultLabel; super.visitLookupSwitchInsn(defaultLabel, ints, newLabels); diff --git a/pitest/src/test/java/org/pitest/mutationtest/engine/gregor/mutators/experimental/RemoveSwitchMutatorTest.java b/pitest/src/test/java/org/pitest/mutationtest/engine/gregor/mutators/experimental/RemoveSwitchMutatorTest.java index 23224d453..fd2fca531 100644 --- a/pitest/src/test/java/org/pitest/mutationtest/engine/gregor/mutators/experimental/RemoveSwitchMutatorTest.java +++ b/pitest/src/test/java/org/pitest/mutationtest/engine/gregor/mutators/experimental/RemoveSwitchMutatorTest.java @@ -255,4 +255,59 @@ public void shouldNotTouchIt() { v.forClass(HasFewerLabelsWithDefault.class) .noMutantsCreated(); } + + + private static class FallThroughLookupSwitch implements IntFunction { + + @Override + public Integer apply(int value) { + int i = 0; + switch (value) { + case 1: + i = 1; + break; + case 200: + i = 4; + break; + case 300: + case 400: + default: + i = 0; + } + return i; + } + } + + @Test + public void doesNotReplaceLookupSwitchCasesThatFallThroughToDefault() { + v.forClass(FallThroughLookupSwitch.class) + .noMutantsCreated(); + } + + private static class FallThroughTableSwitch implements Function { + + @Override + public Integer apply(TimeUnit value) { + switch (value) { + case NANOSECONDS: + return 1; + case MICROSECONDS: + return 2; + case MILLISECONDS: + case SECONDS: + default: + return -1; + } + } + } + + @Test + public void doesNotReplaceTableSwitchCasesThatFallThroughToDefault() { + v.forClass(FallThroughTableSwitch.class) + .noMutantsCreated(); + } + + } + + diff --git a/pitest/src/test/java/org/pitest/verifier/mutants/MutatorVerifier.java b/pitest/src/test/java/org/pitest/verifier/mutants/MutatorVerifier.java index 8f73bf5ff..37dd6510f 100644 --- a/pitest/src/test/java/org/pitest/verifier/mutants/MutatorVerifier.java +++ b/pitest/src/test/java/org/pitest/verifier/mutants/MutatorVerifier.java @@ -51,7 +51,9 @@ public void createsNMutants(int n) { } public void noMutantsCreated() { - assertThat(findMutations()).isEmpty(); + assertThat(findMutations()) + .as(() -> "Expecting no mutants to be generated for " + printClass(clazz)) + .isEmpty(); } public final StringAssert firstMutantDescription() {