Skip to content

Commit

Permalink
Ignore bridge methods when scanning for annotated methods.
Browse files Browse the repository at this point in the history
  • Loading branch information
kcooney committed Jan 17, 2017
1 parent b19ff58 commit 5c3287d
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 11 deletions.
5 changes: 5 additions & 0 deletions src/main/java/org/junit/runners/model/FrameworkField.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public boolean isShadowedBy(FrameworkField otherMember) {
return otherMember.getName().equals(getName());
}

@Override
boolean isBridgeMethod() {
return false;
}

@Override
protected int getModifiers() {
return field.getModifiers();
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/org/junit/runners/model/FrameworkMember.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,29 @@ public abstract class FrameworkMember<T extends FrameworkMember<T>> implements
Annotatable {
abstract boolean isShadowedBy(T otherMember);

boolean isShadowedBy(List<T> members) {
for (T each : members) {
if (isShadowedBy(each)) {
return true;
T handlePossibleBridgeMethod(List<T> members) {
for (int i = members.size() - 1; i >=0; i--) {
T otherMember = members.get(i);
if (isShadowedBy(otherMember)) {
if (otherMember.isBridgeMethod()) {
/*
* We need to return the previously-encountered bridge method
* because JUnit won't be able to call the parent method,
* because the parent class isn't public.
*/
members.remove(i);
return otherMember;
}
// We found a shadowed member that isn't a bridge method. Ignore it.
return null;
}
}
return false;
// No shadow or bridge method found. The caller should add *this* member.
return (T) this;
}

abstract boolean isBridgeMethod();

protected abstract int getModifiers();

/**
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/org/junit/runners/model/FrameworkMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ public boolean isShadowedBy(FrameworkMethod other) {
return true;
}

@Override
boolean isBridgeMethod() {
return method.isBridge();
}

@Override
public boolean equals(Object obj) {
if (!FrameworkMethod.class.isInstance(obj)) {
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/junit/runners/model/TestClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ protected static <T extends FrameworkMember<T>> void addToAnnotationLists(T memb
for (Annotation each : member.getAnnotations()) {
Class<? extends Annotation> type = each.annotationType();
List<T> members = getAnnotatedMembers(map, type, true);
if (member.isShadowedBy(members)) {
T methodToAdd = member.handlePossibleBridgeMethod(members);
if (methodToAdd == null) {
return;
}
if (runsTopToBottom(type)) {
Expand Down
97 changes: 92 additions & 5 deletions src/test/java/org/junit/tests/running/methods/AnnotationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.experimental.results.PrintableResult.testResult;
import static org.junit.experimental.results.ResultMatchers.isSuccessful;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;

Expand All @@ -13,7 +16,11 @@
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.results.PrintableResult;
import org.junit.rules.ExternalResource;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
Expand Down Expand Up @@ -454,28 +461,69 @@ public void testOrderingOfInheritance() throws Exception {
}

static public class SuperShadowing {
@Rule
public TestRule rule() {
return new ExternalResource() {
@Override
protected void before() throws Throwable {
log += "super.rule().before() ";
}

@Override
protected void after() {
log += "super.rule().after() ";
}
};
}

@Before
public void before() {
log += "Before super ";
log += "super.before() ";
}

@After
public void after() {
log += "After super ";
log += "super.after() ";
}
}

static public class SubShadowing extends SuperShadowing {
@Override
@Rule
public TestRule rule() {
return new ExternalResource() {
@Override
protected void before() throws Throwable {
log += "sub.rule().before() ";
}

@Override
protected void after() {
log += "sub.rule().after() ";
}
};
}

@Override
@Before
public void before() {
log += "Before sub ";
log += "sub.before() ";
}

@Before
public void anotherBefore() {
log += "sub.anotherBefore() ";
}

@Override
@After
public void after() {
log += "After sub ";
log += "sub.after() ";
}

@After
public void anotherAfter() {
log += "sub.anotherAfter() ";
}

@Test
Expand All @@ -488,7 +536,46 @@ public void testShadowing() throws Exception {
log = "";
JUnitCore core = new JUnitCore();
core.run(SubShadowing.class);
assertEquals("Before sub Test After sub ", log);
assertEquals(
"sub.rule().before() sub.anotherBefore() sub.before() "
+ "Test "
+ "sub.anotherAfter() sub.after() sub.rule().after() ",
log);
}

static public class SubBridge extends SuperBridge {
@Before
public void anotherBefore() {
log += "sub.anotherBefore() ";
}

@Test
public void test() {
log += "Test ";
}

@After
public void anotherAfter() {
log += "sub.anotherAfter() ";
}
}

// Temporarily disable this test. Compiler not generating bridge methods for some odd reason.
public void testBridge() throws Exception {
Method method = SubBridge.class.getMethod("before");
if (!method.isBridge()) {
// For some reason the compiler isn't generating bridge methods
return;
}

log = "";
PrintableResult testResult = testResult(SubBridge.class);
assertThat(testResult, isSuccessful());
assertEquals(
"super.rule().before() super.before() sub.anotherBefore() "
+ "Test "
+ "sub.anotherAfter() super.after() super.rule().after() ",
log);
}

static public class SuperTest {
Expand Down
35 changes: 35 additions & 0 deletions src/test/java/org/junit/tests/running/methods/SuperBridge.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.junit.tests.running.methods;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.ExternalResource;
import org.junit.rules.TestRule;

/** Sample test class to test handling of bridge methods. */
abstract class SuperBridge {
@Rule
public TestRule rule() {
return new ExternalResource() {
@Override
protected void before() throws Throwable {
AnnotationTest.log += "super.rule().before() ";
}

@Override
protected void after() {
AnnotationTest.log += "super.rule().after() ";
}
};
}

@Before
public void before() {
AnnotationTest.log += "super.before() ";
}

@After
public void after() {
AnnotationTest.log += "super.after() ";
}
}

0 comments on commit 5c3287d

Please sign in to comment.