Skip to content

Commit

Permalink
Merge pull request #1311 from hcoles/feature/unmodifiable_fields
Browse files Browse the repository at this point in the history
Feature/unmodifiable fields
  • Loading branch information
hcoles authored Feb 16, 2024
2 parents 738fac2 + 0dcf263 commit 65d3364
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
import org.pitest.mutationtest.build.MutationInterceptorFactory;
import org.pitest.plugin.Feature;

public class ReturnUnmodifiableCollectionFactory implements MutationInterceptorFactory {
public class UnmodifiableCollectionFactory implements MutationInterceptorFactory {
@Override
public MutationInterceptor createInterceptor(InterceptorParameters params) {
return new ReturnUnmodifiableCollection();
return new UnmodifiableCollections();
}

@Override
Expand All @@ -20,6 +20,6 @@ public Feature provides() {

@Override
public String description() {
return "Filter mutations to defensive return wrappers such as unmodifiableCollection";
return "Filter mutations to defensive wrappers such as unmodifiableCollection on return or field write";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@
import static org.pitest.bytecode.analysis.InstructionMatchers.notAnInstruction;
import static org.pitest.bytecode.analysis.OpcodeMatchers.ARETURN;
import static org.pitest.bytecode.analysis.OpcodeMatchers.INVOKESTATIC;
import static org.pitest.bytecode.analysis.OpcodeMatchers.PUTFIELD;
import static org.pitest.sequence.Result.result;

public class ReturnUnmodifiableCollection extends RegionInterceptor {
public class UnmodifiableCollections extends RegionInterceptor {

static final Slot<AbstractInsnNode> MUTATED_INSTRUCTION = Slot.create(AbstractInsnNode.class);

static final SequenceMatcher<AbstractInsnNode> DEFENSIVE_RETURN = QueryStart
.any(AbstractInsnNode.class)
.then(INVOKESTATIC.and(methodCallTo(ClassName.fromClass(Collections.class), n -> n.startsWith("unmodifiable"))).and(store(MUTATED_INSTRUCTION.write())))
.then(ARETURN)
.then(ARETURN.or(PUTFIELD))
.zeroOrMore(QueryStart.match(anyInstruction()))
.compile(QueryParams.params(AbstractInsnNode.class)
.withIgnores(notAnInstruction().or(isA(LabelNode.class)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ org.pitest.mutationtest.build.intercept.equivalent.EquivalentReturnMutationFilte
org.pitest.mutationtest.build.intercept.exclude.FirstLineInterceptorFactory
org.pitest.mutationtest.build.intercept.equivalent.DivisionByMinusOneFilterFactory
org.pitest.mutationtest.build.intercept.lombok.LombokFilter
org.pitest.mutationtest.build.intercept.defensive.ReturnUnmodifiableCollectionFactory
org.pitest.mutationtest.build.intercept.defensive.UnmodifiableCollectionFactory


org.pitest.plugin.export.MutantExportFactory
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import static org.pitest.bytecode.analysis.OpcodeMatchers.INVOKESTATIC;


public class ReturnUnmodifiableCollectionFactoryTest {
private final MutationInterceptorFactory underTest = new ReturnUnmodifiableCollectionFactory();
public class UnmodifiableCollectionsFactoryTest {
private final MutationInterceptorFactory underTest = new UnmodifiableCollectionFactory();
InterceptorVerifier v = VerifierStart.forInterceptorFactory(underTest)
.usingMutator(new NullMutateEverything());

Expand Down Expand Up @@ -80,6 +80,14 @@ public void doesNotFilterOtherCode() {
.verify();
}

@Test
public void filtersUnmodifiableStoresToFields() {
v.forClass(StoresToFields.class)
.forCodeMatching(INVOKESTATIC.asPredicate())
.allMutantsAreFiltered()
.verify();
}

@Test
public void doesNotFilterOtherCallsToUnModifiableSet() {
v.forClass(HasUnmodifiableSetNonReturn.class)
Expand All @@ -89,6 +97,14 @@ public void doesNotFilterOtherCallsToUnModifiableSet() {
}
}

class StoresToFields {
final List<String> ls;

StoresToFields(List<String> mod) {
ls = Collections.unmodifiableList(mod);
}
}

class HasUnmodifiableSetReturn {
private final Set<String> s = new HashSet<>();

Expand Down Expand Up @@ -122,12 +138,10 @@ public Map<String,String> mutateMe(Map<String,String> m) {

class HasUnmodifiableSetNonReturn {
private final Set<String> s = new HashSet<>();
private Set<String> copy;


public Set<String> dontMutateME(int i) {
if (i != 1) {
copy = Collections.unmodifiableSet(s);
Set<String> copy = Collections.unmodifiableSet(s);
}

return s;
Expand Down

0 comments on commit 65d3364

Please sign in to comment.