From 3b706944832478a144ce32a43e4b83eec5a7b498 Mon Sep 17 00:00:00 2001 From: Henry Coles Date: Wed, 4 Sep 2024 12:42:37 +0100 Subject: [PATCH] move javassist support into transformation plugin --- .../coverage/execute/CoverageMinion.java | 17 ++--------- .../environment/TransformationPlugin.java | 4 +-- .../execute/MutationTestMinion.java | 22 ++++---------- .../execute/MutationTestWorker.java | 18 +++++------ ...vassistInputStreamInterceptorAdapter.java} | 10 +++---- .../mocksupport/JavassistInterceptor.java | 4 +-- .../mocksupport/JavassistTransformation.java | 30 +++++++++++++++++++ .../ResetJavassistEnvironment.java | 16 ++++++++++ ...iontest.environment.EnvironmentResetPlugin | 1 + ...ationtest.environment.TransformationPlugin | 1 + .../BendJavassistToMyWillTransformerTest.java | 2 +- ...istInputStreamInterceptorAdapterTest.java} | 2 +- 12 files changed, 74 insertions(+), 53 deletions(-) rename pitest/src/main/java/org/pitest/mutationtest/mocksupport/{JavassistInputStreamInterceptorAdapater.java => JavassistInputStreamInterceptorAdapter.java} (85%) create mode 100644 pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistTransformation.java create mode 100644 pitest/src/main/java/org/pitest/mutationtest/mocksupport/ResetJavassistEnvironment.java create mode 100644 pitest/src/main/resources/META-INF/services/org.pitest.mutationtest.environment.EnvironmentResetPlugin create mode 100644 pitest/src/main/resources/META-INF/services/org.pitest.mutationtest.environment.TransformationPlugin rename pitest/src/test/java/org/pitest/mutationtest/mocksupport/{JavassistInputStreamInterceptorAdapaterTest.java => JavassistInputStreamInterceptorAdapterTest.java} (96%) diff --git a/pitest/src/main/java/org/pitest/coverage/execute/CoverageMinion.java b/pitest/src/main/java/org/pitest/coverage/execute/CoverageMinion.java index 708e3eb57..f86dd7177 100644 --- a/pitest/src/main/java/org/pitest/coverage/execute/CoverageMinion.java +++ b/pitest/src/main/java/org/pitest/coverage/execute/CoverageMinion.java @@ -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; @@ -55,7 +51,7 @@ public class CoverageMinion { public static void main(final String[] args) { - enablePowerMockSupport(); + enableTransformations(); ExitCode exitCode = ExitCode.OK; Socket s = null; @@ -82,8 +78,6 @@ public static void main(final String[] args) { HotSwapAgent.addTransformer(new CoverageTransformer( convertToJVMClassFilter(paramsFromParent.getFilter()))); - enableTransformations(); - final List tus = getTestsFromParent(dis, paramsFromParent, invokeQueue); LOG.info(() -> tus.size() + " tests discovered"); @@ -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()); } } @@ -140,13 +134,6 @@ private static List removeTestsExecutedDuringDiscovery(List return toExecute; } - private static void enablePowerMockSupport() { - // Bwahahahahahahaha - HotSwapAgent.addTransformer(new BendJavassistToMyWillTransformer(Prelude - .or(new Glob("javassist/*")), - JavassistInputStreamInterceptorAdapater.inputStreamAdapterSupplier(JavassistCoverageInterceptor.class))); - } - private static Predicate convertToJVMClassFilter( final Predicate child) { return a -> child.test(a.replace("/", ".")); diff --git a/pitest/src/main/java/org/pitest/mutationtest/environment/TransformationPlugin.java b/pitest/src/main/java/org/pitest/mutationtest/environment/TransformationPlugin.java index 2dc9611a9..0b172cbdd 100644 --- a/pitest/src/main/java/org/pitest/mutationtest/environment/TransformationPlugin.java +++ b/pitest/src/main/java/org/pitest/mutationtest/environment/TransformationPlugin.java @@ -5,7 +5,7 @@ import java.lang.instrument.ClassFileTransformer; public interface TransformationPlugin extends ClientClasspathPlugin { - - ClassFileTransformer makeTransformer(); + ClassFileTransformer makeCoverageTransformer(); + ClassFileTransformer makeMutationTransformer(); } diff --git a/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestMinion.java b/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestMinion.java index 524f4c6a9..80ea4189f 100644 --- a/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestMinion.java +++ b/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestMinion.java @@ -19,7 +19,6 @@ 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; @@ -27,14 +26,10 @@ 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; @@ -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]); @@ -165,21 +158,18 @@ public static void main(final String[] args) { private static List findTestsForTestClasses( final ClassLoader loader, final Collection testClasses, final Configuration pitConfig) { - final Collection> tcs = testClasses.stream().flatMap(ClassName.nameToClass(loader)).collect(Collectors.toList()); + + final Collection> 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()); } } diff --git a/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java b/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java index 53b5cd9bd..6c8de32a5 100644 --- a/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java +++ b/pitest/src/main/java/org/pitest/mutationtest/execute/MutationTestWorker.java @@ -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; @@ -62,6 +61,7 @@ public class MutationTestWorker { private final ResetEnvironment reset; + public MutationTestWorker(HotSwap hotswap, Mutater mutater, ClassLoader loader, @@ -91,17 +91,13 @@ protected void run(final Collection 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) { @@ -126,8 +122,8 @@ private MutationStatusTestPair handleMutation( final List 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, @@ -142,7 +138,7 @@ private MutationStatusTestPair handleCoveredMutation( final List relevantTests) { final MutationStatusTestPair mutationDetected; if (DEBUG) { - LOG.fine("" + relevantTests.size() + " relevant test for " + LOG.fine(relevantTests.size() + " relevant test for " + mutatedClass.getDetails().getMethod()); } diff --git a/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapater.java b/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapter.java similarity index 85% rename from pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapater.java rename to pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapter.java index 7b89a684a..009cafc5a 100644 --- a/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapater.java +++ b/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapter.java @@ -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 inputStreamAdapterSupplier(final Class interceptor) { - return a -> new JavassistInputStreamInterceptorAdapater(a, interceptor); + return a -> new JavassistInputStreamInterceptorAdapter(a, interceptor); } @@ -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, diff --git a/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInterceptor.java b/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInterceptor.java index ad9746407..b11f2a216 100644 --- a/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInterceptor.java +++ b/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistInterceptor.java @@ -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); @@ -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; } } diff --git a/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistTransformation.java b/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistTransformation.java new file mode 100644 index 000000000..16211b9d3 --- /dev/null +++ b/pitest/src/main/java/org/pitest/mutationtest/mocksupport/JavassistTransformation.java @@ -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"; + } +} diff --git a/pitest/src/main/java/org/pitest/mutationtest/mocksupport/ResetJavassistEnvironment.java b/pitest/src/main/java/org/pitest/mutationtest/mocksupport/ResetJavassistEnvironment.java new file mode 100644 index 000000000..90f015068 --- /dev/null +++ b/pitest/src/main/java/org/pitest/mutationtest/mocksupport/ResetJavassistEnvironment.java @@ -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"; + } +} diff --git a/pitest/src/main/resources/META-INF/services/org.pitest.mutationtest.environment.EnvironmentResetPlugin b/pitest/src/main/resources/META-INF/services/org.pitest.mutationtest.environment.EnvironmentResetPlugin new file mode 100644 index 000000000..a665fe494 --- /dev/null +++ b/pitest/src/main/resources/META-INF/services/org.pitest.mutationtest.environment.EnvironmentResetPlugin @@ -0,0 +1 @@ +org.pitest.mutationtest.mocksupport.ResetJavassistEnvironment \ No newline at end of file diff --git a/pitest/src/main/resources/META-INF/services/org.pitest.mutationtest.environment.TransformationPlugin b/pitest/src/main/resources/META-INF/services/org.pitest.mutationtest.environment.TransformationPlugin new file mode 100644 index 000000000..4b62911ed --- /dev/null +++ b/pitest/src/main/resources/META-INF/services/org.pitest.mutationtest.environment.TransformationPlugin @@ -0,0 +1 @@ +org.pitest.mutationtest.mocksupport.JavassistTransformation \ No newline at end of file diff --git a/pitest/src/test/java/org/pitest/mutationtest/mocksupport/BendJavassistToMyWillTransformerTest.java b/pitest/src/test/java/org/pitest/mutationtest/mocksupport/BendJavassistToMyWillTransformerTest.java index 73ad62d22..863ef7fbb 100644 --- a/pitest/src/test/java/org/pitest/mutationtest/mocksupport/BendJavassistToMyWillTransformerTest.java +++ b/pitest/src/test/java/org/pitest/mutationtest/mocksupport/BendJavassistToMyWillTransformerTest.java @@ -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(); diff --git a/pitest/src/test/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapaterTest.java b/pitest/src/test/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapterTest.java similarity index 96% rename from pitest/src/test/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapaterTest.java rename to pitest/src/test/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapterTest.java index e9633b5a9..4f40dea45 100644 --- a/pitest/src/test/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapaterTest.java +++ b/pitest/src/test/java/org/pitest/mutationtest/mocksupport/JavassistInputStreamInterceptorAdapterTest.java @@ -9,7 +9,7 @@ import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; -public class JavassistInputStreamInterceptorAdapaterTest { +public class JavassistInputStreamInterceptorAdapterTest { private JavassistInputStreamInterceptorMethodVisitor testee;