Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

do not treat lines in bridges and synthetic methods as code lines #1124

Merged
merged 1 commit into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Read all about it at http://pitest.org

## Releases

## 1.10.1 (unreleased)

* #1124 Fix bug introduced in 1.10.0 where bridge methods treated as valid lines of code

## 1.10.0

* #1067 Improved Quarkus and Roboelectric support
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
Expand Down Expand Up @@ -83,20 +84,28 @@ public ClassNode rawNode() {
}

public Set<Integer> codeLineNumbers() {
return methods().stream()
return realMethods()
.flatMap(m -> m.instructions().stream()
.filter(n -> n instanceof LineNumberNode)
.map(n -> ((LineNumberNode) n).line))
.collect(Collectors.toSet());
}

public int numberOfCodeLines() {
return (int) methods().stream()
return (int) realMethods()
.flatMap(m -> m.instructions().stream()
.filter(n -> n instanceof LineNumberNode))
.count();
}

/**
* Methods, excluding bridges and synthetics
*/
public Stream<MethodTree> realMethods() {
return methods().stream()
.filter(m -> !m.isSynthetic() && !m.isBridge());
}

public boolean isAbstract() {
return (this.rawNode.access & Opcodes.ACC_ABSTRACT) != 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public boolean isSynthetic() {
return (this.rawNode.access & Opcodes.ACC_SYNTHETIC) != 0;
}

public boolean isBridge() {
return (this.rawNode.access & Opcodes.ACC_BRIDGE) != 0;
}

public boolean isPrivate() {
return (this.rawNode.access & Opcodes.ACC_PRIVATE) != 0;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package org.pitest.bytecode.analysis;

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

import java.util.function.Function;
import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;

import org.junit.Test;
import org.pitest.classinfo.ClassByteArraySource;
Expand Down Expand Up @@ -57,7 +56,27 @@ public void shouldNotDetectCodeLineAtClassDeclarationsWhenClassHasNoDefaultConst
@Test
public void shouldNotRecordLineNumbersFromSyntheticBridgeMethods() {
ClassTree underTest = ClassTree.fromBytes(bytesFor(Bridge.HasBridgeMethod.class));
assertThat(underTest.codeLineNumbers()).doesNotContain(1);
assertThat(underTest.codeLineNumbers()).doesNotContain(24);
}

@Test
public void shouldNotIncludeBridgeMethodsInCodeLineCount() {
ClassTree underTest = ClassTree.fromBytes(bytesFor(Bridge.HasBridgeMethod.class));
assertThat(underTest.numberOfCodeLines()).isEqualTo(3);
}

@Test
public void realMethodsDoesNotIncludeBridgeMethods() {
ClassTree underTest = ClassTree.fromBytes(bytesFor(Bridge.HasBridgeMethod.class));
assertThat(underTest.realMethods()).hasSize(underTest.methods().size() - 1);
}

@Test
public void realMethodsDoesNotIncludeSynthetics() {
ClassTree underTest = ClassTree.fromBytes(bytesFor(ParseMe.class));
MethodTree method = underTest.methods().get(0);
method.rawNode().access |= ACC_SYNTHETIC;
assertThat(underTest.realMethods()).doesNotContain(method);
}

byte[] bytesFor(Class<?> clazz) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public T getT() {
}

public static class HasBridgeMethod extends A<String> {

HasBridgeMethod() {
// so we don't have an autogenerated init also on line 24
}

@Override
public String getT() {
return null;
Expand Down