Skip to content

Commit

Permalink
Avoid instrumenting synthetic methods
Browse files Browse the repository at this point in the history
Coverage was being generated for synthetic methods, artificially
inflating the number of covered lines for some kotlin classes. This
change prevents probes from being inserting into them, duplicating the
logic use elsewhere to ensure that lambda implementations still have
probes, despite their synthetic flag.
  • Loading branch information
hcoles committed Feb 22, 2023
1 parent 43b16ef commit 6f1033f
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 11 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ Read all about it at http://pitest.org

## Releases

## 1.11.0 (unreleased)
## 1.11.1

* #1156 Prevent synthetic lines being counted in coverage

## 1.11.0

* #1138 Do not mutate redundant fall through to default switch cases
* #1150 New extension points
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.pitest.classinfo;

import org.objectweb.asm.Opcodes;
import org.pitest.functional.F5;

/**
* Filters out synthetic and bridge methods, but allows synthetic
* lambdas. This logic is duplicated in org.pitest.bytecode.analysis.MethodTree
* when identifying code lines.
*/
public enum SyntheticMethodFilter implements
F5<Integer, String, String, String, String[], Boolean> {

INSTANCE;

@Override
public Boolean apply(final Integer access, final String name,
final String desc, final String signature, final String[] exceptions) {
return (!isSynthetic(access, name) && !isBridge(access));
}

private static boolean isSynthetic(final int access, String name) {
return (access & Opcodes.ACC_SYNTHETIC) != 0 && !name.startsWith("lambda$");
}

private static boolean isBridge(final Integer access) {
return (access & Opcodes.ACC_BRIDGE) != 0;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.pitest.classinfo.BridgeMethodFilter;
import org.pitest.classinfo.MethodFilteringAdapter;
import org.pitest.classinfo.SyntheticMethodFilter;
import org.pitest.coverage.analysis.CoverageAnalyser;
import sun.pitest.CodeCoverageStore;

Expand All @@ -43,7 +43,7 @@ public class CoverageClassVisitor extends MethodFilteringAdapter {
private boolean isInterface;

public CoverageClassVisitor(final int classId, final ClassWriter writer) {
super(writer, BridgeMethodFilter.INSTANCE);
super(writer, SyntheticMethodFilter.INSTANCE);
this.classId = classId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,14 @@ public void tearDown() {
}

@Test
public void shouldNotTransformClassesNotMatchingPredicate()
throws IllegalClassFormatException {
public void shouldNotTransformClassesNotMatchingPredicate() {
final CoverageTransformer testee = new CoverageTransformer(
False.<String> instance());
assertNull(testee.transform(null, "anything", null, null, null));
}

@Test
public void shouldTransformClasseMatchingPredicate()
throws IllegalClassFormatException {
public void shouldTransformClasseMatchingPredicate() {
final CoverageTransformer testee = new CoverageTransformer(
s -> true);
final byte[] bs = this.bytes.getBytes(String.class.getName()).get();
Expand All @@ -83,8 +81,7 @@ public void shouldGenerateValidClasses() throws IllegalClassFormatException {
assertValidClass(Math.class);
}

private void assertValidClass(final Class<?> clazz)
throws IllegalClassFormatException {
private void assertValidClass(final Class<?> clazz) {
final byte[] bs = transform(clazz);
// printClass(bs);
final StringWriter sw = new StringWriter();
Expand All @@ -105,8 +102,7 @@ protected void printClass(final byte[] bs) {
System.out)), ClassReader.EXPAND_FRAMES);
}

private byte[] transform(final Class<?> clazz)
throws IllegalClassFormatException {
private byte[] transform(final Class<?> clazz) {
final CoverageTransformer testee = new CoverageTransformer(
s -> true);
return testee.transform(this.loader, clazz.getName(), null,
Expand Down

0 comments on commit 6f1033f

Please sign in to comment.