Skip to content

Commit

Permalink
Merge pull request #1121 from hcoles/feature/remove_gregor_classinfo
Browse files Browse the repository at this point in the history
  • Loading branch information
hcoles authored Nov 29, 2022
2 parents 190f2e8 + b1cdbe8 commit 09b0b73
Show file tree
Hide file tree
Showing 20 changed files with 293 additions and 296 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.pitest.mutationtest.build.intercept.groovy;

import org.pitest.bytecode.analysis.ClassTree;
import org.pitest.mutationtest.build.InterceptorType;
import org.pitest.mutationtest.build.MutationInterceptor;
import org.pitest.mutationtest.engine.Mutater;
import org.pitest.mutationtest.engine.MutationDetails;

import java.util.Collection;
import java.util.Collections;

/**
* Prevents mutation of groovy code since we can't properly handle it
*/
public class GroovyFilter implements MutationInterceptor {

boolean isGroovyClass = false;

@Override
public Collection<MutationDetails> intercept(
Collection<MutationDetails> mutations, Mutater m) {
if (isGroovyClass) {
return Collections.emptyList();
}
return mutations;
}

@Override
public InterceptorType type() {
return InterceptorType.FILTER;
}

@Override
public void begin(ClassTree clazz) {
isGroovyClass = isGroovyClass(clazz);
}

@Override
public void end() {
isGroovyClass = false;
}

private boolean isGroovyClass(ClassTree clazz) {
return clazz.rawNode().interfaces != null && clazz.rawNode().interfaces.stream()
.anyMatch(a -> a.startsWith("groovy/lang/") || a.startsWith("org/codehaus/groovy/runtime"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.pitest.mutationtest.build.intercept.groovy;

import org.pitest.mutationtest.build.InterceptorParameters;
import org.pitest.mutationtest.build.MutationInterceptor;
import org.pitest.mutationtest.build.MutationInterceptorFactory;
import org.pitest.plugin.Feature;

public class GroovyFilterFactory implements MutationInterceptorFactory {

@Override
public String description() {
return "Groovy junk mutations filter";
}

@Override
public MutationInterceptor createInterceptor(InterceptorParameters params) {
return new GroovyFilter();
}

@Override
public Feature provides() {
return Feature.named("FGROOVY")
.withDescription("Filters out junk mutations in groovy code")
.withOnByDefault(true);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.pitest.mutationtest.build.intercept.javafeatures;

import org.pitest.bytecode.analysis.ClassTree;
import org.pitest.mutationtest.build.InterceptorType;
import org.pitest.mutationtest.build.MutationInterceptor;
import org.pitest.mutationtest.engine.Location;
import org.pitest.mutationtest.engine.Mutater;
import org.pitest.mutationtest.engine.MutationDetails;

import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
* Filters out mutations in Enum constructors, these are called only once
* per instance so are effectively static initializers.
*
* This overlaps with the StaticInitializerInterceptor, and could
* probably be removed. Left in place for now as it is computationally less
* expensive.
*
* Also filters mutants is the compiler generated valueOf and values methods.
*/
public class EnumFilter implements MutationInterceptor {

private boolean isEnum;
private ClassTree currentClass;

@Override
public InterceptorType type() {
return InterceptorType.FILTER;
}

@Override
public void begin(ClassTree clazz) {
this.isEnum = clazz.rawNode().superName.equals("java/lang/Enum");
this.currentClass = clazz;
}

@Override
public Collection<MutationDetails> intercept(
Collection<MutationDetails> mutations, Mutater m) {
if (isEnum) {
return mutations.stream()
.filter(makeMethodFilter(currentClass).negate())
.collect(Collectors.toList());
}
return mutations;

}

private Predicate<MutationDetails> makeMethodFilter(ClassTree currentClass) {
Location valueOf = Location.location(currentClass.name(), "valueOf", "(Ljava/lang/String;)L" + currentClass.name().asInternalName() + ";");
Location values = Location.location(currentClass.name(), "values", "()[L" + currentClass.name().asInternalName() + ";");

return m -> isInEnumConstructor(m) || m.getId().getLocation().equals(valueOf) || m.getId().getLocation().equals(values);
}

private boolean isInEnumConstructor(MutationDetails m) {
return m.getMethod().equals("<init>");
}

@Override
public void end() {
isEnum = false;
currentClass = null;
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@
import org.pitest.mutationtest.build.MutationInterceptorFactory;
import org.pitest.plugin.Feature;

public class EnumConstructorFilterFactory implements MutationInterceptorFactory {
public class EnumFilterFactory implements MutationInterceptorFactory {

@Override
public String description() {
return "Enum constructor filter";
return "Enum junk filter";
}

@Override
public MutationInterceptor createInterceptor(InterceptorParameters params) {
return new EnumConstructorFilter();
return new EnumFilter();
}

@Override
public Feature provides() {
return Feature.named("FENUM")
.withOnByDefault(true)
.withDescription("Filters mutations in enum constructors");
.withDescription("Filters junk mutations in enums");
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ org.pitest.mutationtest.build.intercept.javafeatures.InlinedFinallyBlockFilterFa
org.pitest.mutationtest.build.intercept.javafeatures.ImplicitNullCheckFilterFactory
org.pitest.mutationtest.build.intercept.javafeatures.MethodReferenceNullCheckFilterFactory
org.pitest.mutationtest.build.intercept.javafeatures.ForEachLoopFilterFactory
org.pitest.mutationtest.build.intercept.javafeatures.EnumConstructorFilterFactory
org.pitest.mutationtest.build.intercept.javafeatures.EnumFilterFactory
org.pitest.mutationtest.build.intercept.javafeatures.RecordFilterFactory
org.pitest.mutationtest.build.intercept.javafeatures.StringSwitchFilterFactory
org.pitest.mutationtest.build.intercept.javafeatures.AssertionsFilterFactory
Expand All @@ -17,6 +17,7 @@ org.pitest.mutationtest.build.intercept.timeout.InfiniteForLoopFilterFactory
org.pitest.mutationtest.build.intercept.timeout.InfiniteIteratorLoopFilterFactory
org.pitest.mutationtest.build.intercept.timeout.AvoidForLoopCountersFilterFactory
org.pitest.mutationtest.build.intercept.kotlin.KotlinFilterFactory
org.pitest.mutationtest.build.intercept.groovy.GroovyFilterFactory
org.pitest.mutationtest.filter.LimitNumberOfMutationsPerClassFilterFactory
org.pitest.mutationtest.build.intercept.equivalent.EqualsPerformanceShortcutFilterFactory
org.pitest.mutationtest.build.intercept.equivalent.EquivalentReturnMutationFilter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,35 @@

import org.junit.Test;
import org.pitest.mutationtest.build.InterceptorType;
import org.pitest.mutationtest.build.intercept.groovy.GroovyFilterFactory;
import org.pitest.verifier.interceptors.FactoryVerifier;

public class FirstLineInterceptorFactoryTest {

GroovyFilterFactory underTest = new GroovyFilterFactory();

@Test
public void isOnChain() {
FactoryVerifier.confirmFactory(new FirstLineInterceptorFactory())
FactoryVerifier.confirmFactory(underTest)
.isOnChain();
}

@Test
public void isOffByDefault() {
FactoryVerifier.confirmFactory(new FirstLineInterceptorFactory())
.isOffByDefault();
public void isOnByDefault() {
FactoryVerifier.confirmFactory(underTest)
.isOnByDefault();
}


@Test
public void featureIsCalledNoFirstLine() {
FactoryVerifier.confirmFactory(new FirstLineInterceptorFactory())
.featureName().isEqualTo("nofirstline");
public void featureIsCalledFGroovy() {
FactoryVerifier.confirmFactory(underTest)
.featureName().isEqualTo("fgroovy");
}

@Test
public void createsFilters() {
FactoryVerifier.confirmFactory(new FirstLineInterceptorFactory())
FactoryVerifier.confirmFactory(underTest)
.createsInterceptorsOfType(InterceptorType.FILTER);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.pitest.mutationtest.build.intercept.groovy;

import org.junit.Test;
import org.pitest.mutationtest.build.InterceptorType;
import org.pitest.mutationtest.build.intercept.exclude.FirstLineInterceptorFactory;
import org.pitest.mutationtest.build.intercept.staticinitializers.StaticInitializerInterceptorFactory;
import org.pitest.mutationtest.engine.gregor.mutators.NullMutateEverything;
import org.pitest.verifier.interceptors.FactoryVerifier;
import org.pitest.verifier.interceptors.InterceptorVerifier;
import org.pitest.verifier.interceptors.VerifierStart;

import static org.assertj.core.api.Assertions.assertThat;

public class GroovyFilterFactoryTest {
@Test
public void isOnChain() {
FactoryVerifier.confirmFactory(new FirstLineInterceptorFactory())
.isOnChain();
}

@Test
public void isOffByDefault() {
FactoryVerifier.confirmFactory(new FirstLineInterceptorFactory())
.isOffByDefault();
}


@Test
public void featureIsCalledNoFirstLine() {
FactoryVerifier.confirmFactory(new FirstLineInterceptorFactory())
.featureName().isEqualTo("nofirstline");
}

@Test
public void createsFilters() {
FactoryVerifier.confirmFactory(new FirstLineInterceptorFactory())
.createsInterceptorsOfType(InterceptorType.FILTER);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.pitest.mutationtest.build.intercept.groovy;

import com.example.coverage.execute.samples.exceptions.CoveredBeforeExceptionTestee;
import org.junit.Test;
import org.pitest.mutationtest.engine.gregor.config.Mutator;
import org.pitest.mutationtest.engine.gregor.mutators.NullMutateEverything;
import org.pitest.util.ResourceFolderByteArraySource;
import org.pitest.verifier.interceptors.InterceptorVerifier;
import org.pitest.verifier.interceptors.VerifierStart;
import org.pitest.verifier.mutants.MutatorVerifierStart;

public class GroovyFilterTest {

InterceptorVerifier v = VerifierStart.forInterceptorFactory(new GroovyFilterFactory())
.usingMutator(new NullMutateEverything());

@Test
public void doesNotFilterMutationsInJavaClasses() {
v.forClass(CoveredBeforeExceptionTestee.class)
.forAnyCode()
.mutantsAreGenerated()
.noMutantsAreFiltered()
.verify();
}

@Test
public void filtersMutantsInGroovyClasses() {
v.usingResourceFolder("groovy")
.forClass("SomeGroovyCode")
.forAnyCode()
.mutantsAreGenerated()
.allMutantsAreFiltered()
.verify();
}

@Test
public void filtersMutantsInGroovyClosures() {
v.usingResourceFolder("groovy")
.forClass("SomeGroovyCode$_mapToString_closure2")
.forAnyCode()
.mutantsAreGenerated()
.allMutantsAreFiltered()
.verify();
}
}
Loading

0 comments on commit 09b0b73

Please sign in to comment.