Skip to content

Commit

Permalink
move javassist support into transformation plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
hcoles committed Sep 4, 2024
1 parent 0547280 commit 3b70694
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,16 @@
import org.pitest.classinfo.ClassName;
import org.pitest.classpath.ClassloaderByteArraySource;
import org.pitest.coverage.CoverageTransformer;
import org.pitest.functional.prelude.Prelude;
import org.pitest.help.PitHelpError;
import org.pitest.mutationtest.config.ClientPluginServices;
import org.pitest.mutationtest.config.MinionSettings;
import org.pitest.mutationtest.environment.TransformationPlugin;
import org.pitest.mutationtest.mocksupport.BendJavassistToMyWillTransformer;
import org.pitest.mutationtest.mocksupport.JavassistInputStreamInterceptorAdapater;
import org.pitest.testapi.Configuration;
import org.pitest.testapi.ExecutedInDiscovery;
import org.pitest.testapi.TestUnit;
import org.pitest.testapi.TestUnitExecutionListener;
import org.pitest.testapi.execute.FindTestUnits;
import org.pitest.util.ExitCode;
import org.pitest.util.Glob;
import org.pitest.util.Log;
import org.pitest.util.SafeDataInputStream;
import sun.pitest.CodeCoverageStore;
Expand All @@ -55,7 +51,7 @@ public class CoverageMinion {

public static void main(final String[] args) {

enablePowerMockSupport();
enableTransformations();

ExitCode exitCode = ExitCode.OK;
Socket s = null;
Expand All @@ -82,8 +78,6 @@ public static void main(final String[] args) {
HotSwapAgent.addTransformer(new CoverageTransformer(
convertToJVMClassFilter(paramsFromParent.getFilter())));

enableTransformations();

final List<TestUnit> tus = getTestsFromParent(dis, paramsFromParent, invokeQueue);

LOG.info(() -> tus.size() + " tests discovered");
Expand Down Expand Up @@ -129,7 +123,7 @@ public static void main(final String[] args) {
private static void enableTransformations() {
ClientPluginServices plugins = ClientPluginServices.makeForContextLoader();
for (TransformationPlugin each : plugins.findTransformations()) {
HotSwapAgent.addTransformer(each.makeTransformer());
HotSwapAgent.addTransformer(each.makeCoverageTransformer());
}
}

Expand All @@ -140,13 +134,6 @@ private static List<TestUnit> removeTestsExecutedDuringDiscovery(List<TestUnit>
return toExecute;
}

private static void enablePowerMockSupport() {
// Bwahahahahahahaha
HotSwapAgent.addTransformer(new BendJavassistToMyWillTransformer(Prelude
.or(new Glob("javassist/*")),
JavassistInputStreamInterceptorAdapater.inputStreamAdapterSupplier(JavassistCoverageInterceptor.class)));
}

private static Predicate<String> convertToJVMClassFilter(
final Predicate<String> child) {
return a -> child.test(a.replace("/", "."));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import java.lang.instrument.ClassFileTransformer;

public interface TransformationPlugin extends ClientClasspathPlugin {

ClassFileTransformer makeTransformer();
ClassFileTransformer makeCoverageTransformer();
ClassFileTransformer makeMutationTransformer();

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,17 @@
import org.pitest.classinfo.ClassByteArraySource;
import org.pitest.classinfo.ClassName;
import org.pitest.classpath.ClassloaderByteArraySource;
import org.pitest.functional.prelude.Prelude;
import org.pitest.mutationtest.EngineArguments;
import org.pitest.mutationtest.environment.ResetEnvironment;
import org.pitest.mutationtest.config.ClientPluginServices;
import org.pitest.mutationtest.config.MinionSettings;
import org.pitest.mutationtest.config.TestPluginArguments;
import org.pitest.mutationtest.engine.MutationEngine;
import org.pitest.mutationtest.environment.TransformationPlugin;
import org.pitest.mutationtest.mocksupport.BendJavassistToMyWillTransformer;
import org.pitest.mutationtest.mocksupport.JavassistInputStreamInterceptorAdapater;
import org.pitest.mutationtest.mocksupport.JavassistInterceptor;
import org.pitest.testapi.Configuration;
import org.pitest.testapi.TestUnit;
import org.pitest.testapi.execute.FindTestUnits;
import org.pitest.util.ExitCode;
import org.pitest.util.Glob;
import org.pitest.util.IsolationUtils;
import org.pitest.util.Log;
import org.pitest.util.SafeDataInputStream;
Expand Down Expand Up @@ -130,10 +125,8 @@ private Configuration createTestPlugin(TestPluginArguments pitConfig) {
public static void main(final String[] args) {
LOG.fine(() -> "minion started");

enablePowerMockSupport();
HotSwapAgent.addTransformer(new CatchNewClassLoadersTransformer());

enableTransformations();
HotSwapAgent.addTransformer(new CatchNewClassLoadersTransformer());

final int port = Integer.parseInt(args[0]);

Expand Down Expand Up @@ -165,21 +158,18 @@ public static void main(final String[] args) {
private static List<TestUnit> findTestsForTestClasses(
final ClassLoader loader, final Collection<ClassName> testClasses,
final Configuration pitConfig) {
final Collection<Class<?>> tcs = testClasses.stream().flatMap(ClassName.nameToClass(loader)).collect(Collectors.toList());

final Collection<Class<?>> tcs = testClasses.stream()
.flatMap(ClassName.nameToClass(loader))
.collect(Collectors.toList());
final FindTestUnits finder = new FindTestUnits(pitConfig);
return finder.findTestUnitsForAllSuppliedClasses(tcs);
}

private static void enablePowerMockSupport() {
// Bwahahahahahahaha
HotSwapAgent.addTransformer(new BendJavassistToMyWillTransformer(Prelude
.or(new Glob("javassist/*")), JavassistInputStreamInterceptorAdapater.inputStreamAdapterSupplier(JavassistInterceptor.class)));
}

private static void enableTransformations() {
ClientPluginServices plugins = ClientPluginServices.makeForContextLoader();
for (TransformationPlugin each : plugins.findTransformations()) {
HotSwapAgent.addTransformer(each.makeTransformer());
HotSwapAgent.addTransformer(each.makeMutationTransformer());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.pitest.mutationtest.engine.Mutater;
import org.pitest.mutationtest.engine.MutationDetails;
import org.pitest.mutationtest.engine.MutationIdentifier;
import org.pitest.mutationtest.mocksupport.JavassistInterceptor;
import org.pitest.testapi.Description;
import org.pitest.testapi.TestResult;
import org.pitest.testapi.TestUnit;
Expand Down Expand Up @@ -62,6 +61,7 @@ public class MutationTestWorker {

private final ResetEnvironment reset;


public MutationTestWorker(HotSwap hotswap,
Mutater mutater,
ClassLoader loader,
Expand Down Expand Up @@ -91,17 +91,13 @@ protected void run(final Collection<MutationDetails> range, final Reporter r,

}

private void processMutation(final Reporter r,
final TimeOutDecoratedTestSource testSource,
final MutationDetails mutationDetails) {
private void processMutation(Reporter r,
TimeOutDecoratedTestSource testSource,
MutationDetails mutationDetails) {

final MutationIdentifier mutationId = mutationDetails.getId();
final Mutant mutatedClass = this.mutater.getMutation(mutationId);

// For the benefit of mocking frameworks such as PowerMock
// mess with the internals of Javassist so our mutated class
// bytes are returned
JavassistInterceptor.setMutant(mutatedClass);
reset.resetFor(mutatedClass);

if (DEBUG) {
Expand All @@ -126,8 +122,8 @@ private MutationStatusTestPair handleMutation(
final List<TestUnit> relevantTests) {
final MutationStatusTestPair mutationDetected;
if ((relevantTests == null) || relevantTests.isEmpty()) {
LOG.info(() -> "No test coverage for mutation " + mutationId + " in "
+ mutatedClass.getDetails().getMethod());
LOG.log(Level.WARNING, "No test coverage for mutation " + mutationId + " in " + mutatedClass.getDetails().getMethod()
+ ". This should have been detected in the outer process so treating as an error");
mutationDetected = MutationStatusTestPair.notAnalysed(0, DetectionStatus.RUN_ERROR, Collections.emptyList());
} else {
mutationDetected = handleCoveredMutation(mutationId, mutatedClass,
Expand All @@ -142,7 +138,7 @@ private MutationStatusTestPair handleCoveredMutation(
final List<TestUnit> relevantTests) {
final MutationStatusTestPair mutationDetected;
if (DEBUG) {
LOG.fine("" + relevantTests.size() + " relevant test for "
LOG.fine(relevantTests.size() + " relevant test for "
+ mutatedClass.getDetails().getMethod());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@
import org.objectweb.asm.Opcodes;
import org.pitest.bytecode.ASMVersion;

public class JavassistInputStreamInterceptorAdapater extends ClassVisitor {
public class JavassistInputStreamInterceptorAdapter extends ClassVisitor {

private final String interceptorClass;

public JavassistInputStreamInterceptorAdapater(final ClassVisitor arg0, Class<?> interceptor) {
public JavassistInputStreamInterceptorAdapter(final ClassVisitor arg0, Class<?> interceptor) {
super(ASMVersion.ASM_VERSION, arg0);
this.interceptorClass = classToName(interceptor);
}

public static Function<ClassWriter, ClassVisitor> inputStreamAdapterSupplier(final Class<?> interceptor) {
return a -> new JavassistInputStreamInterceptorAdapater(a, interceptor);
return a -> new JavassistInputStreamInterceptorAdapter(a, interceptor);
}


Expand All @@ -59,8 +59,8 @@ class JavassistInputStreamInterceptorMethodVisitor extends MethodVisitor {
}

@Override
public void visitMethodInsn(final int opcode, final String owner,
final String name, final String desc, boolean itf) {
public void visitMethodInsn(int opcode, String owner,
String name, String desc, boolean itf) {
if ((opcode == Opcodes.INVOKEINTERFACE)
&& owner.equals("javassist/ClassPath") && name.equals("openClassfile")) {
this.mv.visitMethodInsn(Opcodes.INVOKESTATIC, this.interceptorClass, name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static InputStream openClassfile(final Object classPath, // NO_UCD
final String name) {

if (isMutatedClass(name)) {
return new ByteArrayInputStream(
return new ByteArrayInputStream(
mutant.getBytes());
} else {
return returnNormalBytes(classPath, name);
Expand All @@ -58,7 +58,7 @@ private static boolean isMutatedClass(final String name) {
.equals(ClassName.fromString(name));
}

public static void setMutant(final Mutant newMutant) {
static void setMutant(final Mutant newMutant) {
mutant = newMutant;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.pitest.mutationtest.mocksupport;

import org.pitest.coverage.execute.JavassistCoverageInterceptor;
import org.pitest.functional.prelude.Prelude;
import org.pitest.mutationtest.environment.TransformationPlugin;
import org.pitest.util.Glob;

import java.lang.instrument.ClassFileTransformer;

public class JavassistTransformation implements TransformationPlugin {

@Override
public ClassFileTransformer makeCoverageTransformer() {
return new BendJavassistToMyWillTransformer(Prelude
.or(new Glob("javassist/*")),
JavassistInputStreamInterceptorAdapter.inputStreamAdapterSupplier(JavassistCoverageInterceptor.class));
}

@Override
public ClassFileTransformer makeMutationTransformer() {
return new BendJavassistToMyWillTransformer(Prelude
.or(new Glob("javassist/*")),
JavassistInputStreamInterceptorAdapter.inputStreamAdapterSupplier(JavassistInterceptor.class));
}

@Override
public String description() {
return "Support for mocking frameworks using javassist";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.pitest.mutationtest.mocksupport;

import org.pitest.mutationtest.environment.EnvironmentResetPlugin;
import org.pitest.mutationtest.environment.ResetEnvironment;

public class ResetJavassistEnvironment implements EnvironmentResetPlugin {
@Override
public ResetEnvironment make() {
return JavassistInterceptor::setMutant;
}

@Override
public String description() {
return "Reset environment for javassist";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.pitest.mutationtest.mocksupport.ResetJavassistEnvironment
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.pitest.mutationtest.mocksupport.JavassistTransformation
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class BendJavassistToMyWillTransformerTest {
@Before
public void setUp() {
MockitoAnnotations.openMocks(this);
this.testee = new BendJavassistToMyWillTransformer(this.filter, JavassistInputStreamInterceptorAdapater.inputStreamAdapterSupplier(JavassistInterceptor.class));
this.testee = new BendJavassistToMyWillTransformer(this.filter, JavassistInputStreamInterceptorAdapter.inputStreamAdapterSupplier(JavassistInterceptor.class));
final ClassloaderByteArraySource source = new ClassloaderByteArraySource(
IsolationUtils.getContextClassLoader());
this.bytes = source.getBytes("java.lang.String").get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class JavassistInputStreamInterceptorAdapaterTest {
public class JavassistInputStreamInterceptorAdapterTest {

private JavassistInputStreamInterceptorMethodVisitor testee;

Expand Down

0 comments on commit 3b70694

Please sign in to comment.