-
Notifications
You must be signed in to change notification settings - Fork 354
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Capture all classloaders loading mutant
- Loading branch information
Henry Coles
committed
Jul 29, 2022
1 parent
72735bc
commit 75056c8
Showing
13 changed files
with
149 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
pitest-entry/src/test/java/com/example/classloaders/MuteeInOtherClassloader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.example.classloaders; | ||
|
||
import java.util.function.IntSupplier; | ||
|
||
public class MuteeInOtherClassloader implements IntSupplier { | ||
|
||
@Override | ||
public int getAsInt() { | ||
pointless(); | ||
System.out.println("Can't kill me"); | ||
return 42; | ||
} | ||
|
||
public void pointless() { | ||
System.out.println("Can't kill me either"); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
pitest-entry/src/test/java/com/example/classloaders/MuteeInOtherClassloaderPooledTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.example.classloaders; | ||
|
||
import org.junit.Test; | ||
import org.pitest.classpath.ClassPath; | ||
import org.pitest.mutationtest.execute.DefaultPITClassloader; | ||
|
||
import java.util.function.IntSupplier; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
public class MuteeInOtherClassloaderPooledTest { | ||
|
||
// will persist between mutants | ||
static DefaultPITClassloader otherLoader = new DefaultPITClassloader(new ClassPath(), null); | ||
|
||
@Test | ||
public void returns42() throws Exception { | ||
Class<?> clz = otherLoader.loadClass(MuteeInOtherClassloader.class.getName()); | ||
IntSupplier underTest = (IntSupplier) clz.getConstructor().newInstance(); | ||
assertEquals(42, underTest.getAsInt()); | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
pitest-entry/src/test/java/com/example/classloaders/MuteeInOtherClassloaderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.example.classloaders; | ||
|
||
import org.junit.Test; | ||
import org.pitest.classpath.ClassPath; | ||
import org.pitest.mutationtest.execute.DefaultPITClassloader; | ||
|
||
import java.util.function.IntSupplier; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
public class MuteeInOtherClassloaderTest { | ||
|
||
@Test | ||
public void returns42() throws Exception { | ||
DefaultPITClassloader otherLoader = new DefaultPITClassloader(new ClassPath(), null); | ||
Class<?> clz = otherLoader.loadClass(MuteeInOtherClassloader.class.getName()); | ||
IntSupplier underTest = (IntSupplier) clz.getConstructor().newInstance(); | ||
assertEquals(42, underTest.getAsInt()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -206,6 +206,8 @@ | |
<artifactId>equalsverifier</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
|
||
</dependencies> | ||
|
||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 15 additions & 45 deletions
60
pitest/src/main/java/org/pitest/mutationtest/execute/HotSwap.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,32 @@ | ||
package org.pitest.mutationtest.execute; | ||
|
||
import org.pitest.boot.HotSwapAgent; | ||
import org.pitest.classinfo.ClassByteArraySource; | ||
import org.pitest.classinfo.ClassName; | ||
import org.pitest.functional.F3; | ||
import org.pitest.util.Unchecked; | ||
|
||
class HotSwap implements F3<ClassName, ClassLoader, byte[], Boolean> { | ||
/** | ||
* Since pitest 1.9.4 there is an implicit assumption that pitest will never mutate | ||
* more than once class within the same jvm. If this assumption is ever broken, mutants | ||
* from the previous class would remain active and invalidate results. | ||
*/ | ||
class HotSwap { | ||
|
||
private final ClassByteArraySource byteSource; | ||
private byte[] lastClassPreMutation; | ||
private ClassName lastMutatedClass; | ||
private ClassLoader lastUsedLoader; | ||
|
||
HotSwap(final ClassByteArraySource byteSource) { | ||
this.byteSource = byteSource; | ||
} | ||
|
||
@Override | ||
public Boolean apply(final ClassName clazzName, final ClassLoader loader, | ||
final byte[] b) { | ||
public Boolean insertClass(final ClassName clazzName, ClassLoader loader, final byte[] mutantBytes) { | ||
try { | ||
// Some frameworks (eg quarkus) run tests in non delegating | ||
// classloaders. Need to make sure these are transformed too | ||
CatchNewClassLoadersTransformer.setMutant(clazzName.asInternalName(), mutantBytes); | ||
|
||
System.out.println("Hotswap loader " + loader); | ||
|
||
restoreLastClass(this.byteSource, clazzName, loader); | ||
this.lastUsedLoader = loader; | ||
// trigger loading for the current loader | ||
Class<?> clazz = Class.forName(clazzName.asJavaName(), false, loader); | ||
return HotSwapAgent.hotSwap(clazz, b); | ||
} catch (final ClassNotFoundException e) { | ||
throw Unchecked.translateCheckedException(e); | ||
} | ||
|
||
} | ||
|
||
private void restoreLastClass(final ClassByteArraySource byteSource, | ||
final ClassName clazzName, final ClassLoader loader) | ||
throws ClassNotFoundException { | ||
if ((this.lastMutatedClass != null) | ||
&& !this.lastMutatedClass.equals(clazzName)) { | ||
restoreForLoader(this.lastUsedLoader); | ||
restoreForLoader(loader); | ||
} | ||
// will still need to explicitly swap it... not clear why the transformed does not do this | ||
return HotSwapAgent.hotSwap(clazz, mutantBytes); | ||
|
||
if ((this.lastMutatedClass == null) | ||
|| !this.lastMutatedClass.equals(clazzName)) { | ||
this.lastClassPreMutation = byteSource.getBytes(clazzName.asJavaName()) | ||
.get(); | ||
} catch (final ClassNotFoundException e) { | ||
throw Unchecked.translateCheckedException(e); | ||
} | ||
|
||
this.lastMutatedClass = clazzName; | ||
} | ||
|
||
private void restoreForLoader(ClassLoader loader) | ||
throws ClassNotFoundException { | ||
final Class<?> clazz = Class.forName(this.lastMutatedClass.asJavaName(), false, | ||
loader); | ||
HotSwapAgent.hotSwap(clazz, this.lastClassPreMutation); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.