Skip to content

Commit

Permalink
Add a test method that reproduces an infinite recursion.
Browse files Browse the repository at this point in the history
The test method currently confirms that the bug exists. We plan to fix the bug and change the test so it confirms that the bug _doesn't_ exist.

RELNOTES=n/a
PiperOrigin-RevId: 542546415
  • Loading branch information
eamonnmcmanus authored and Google Java Core Libraries committed Jun 22, 2023
1 parent c3f22dc commit 39743a8
Showing 1 changed file with 52 additions and 2 deletions.
54 changes: 52 additions & 2 deletions common/src/test/java/com/google/auto/common/MoreElementsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static com.google.common.truth.Truth.assertWithMessage;
import static java.util.Objects.requireNonNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

Expand Down Expand Up @@ -233,8 +234,7 @@ private void isAnnotationPresentAsserts(

@Test
public void getAnnotationMirror() {
TypeElement element =
elements.getTypeElement(AnnotatedAnnotation.class.getCanonicalName());
TypeElement element = elements.getTypeElement(AnnotatedAnnotation.class.getCanonicalName());

// Test Class API
getAnnotationMirrorAsserts(
Expand Down Expand Up @@ -361,6 +361,56 @@ public void getLocalAndInheritedMethods() {
.inOrder();
}

@Test
public void getLocalAndInheritedMethods_recursiveTypeVariableBound() {
Types types = compilation.getTypes();
TypeElement builderElement =
elements.getTypeElement(FakeProto.Builder.class.getCanonicalName());
// TODO: b/287060583 - this should not trigger infinite recursion
assertThrows(
StackOverflowError.class,
() -> {
Object unused = MoreElements.getLocalAndInheritedMethods(builderElement, types, elements);
});
}

// The classes that follow mimic the proto classes that triggered the bug that
// getLocalAndInheritedMethods_recursiveTypeVariableBound is testing for. They include raw type
// usages, because the corresponding real proto API classes do.

static class FakeProto extends AbstractMessage {
static class Builder
extends AbstractMessage.Builder<Builder> {
@Override
@SuppressWarnings("rawtypes")
Builder internalMergeFrom(AbstractMessageLite other) {
return this;
}
}
}

@SuppressWarnings("rawtypes")
static class AbstractMessage extends AbstractMessageLite {
static class Builder<B extends Builder<B>> extends AbstractMessageLite.Builder {
@Override
@SuppressWarnings("unchecked")
B internalMergeFrom(AbstractMessageLite other) {
return (B) this;
}
}

}

static class AbstractMessageLite<
M extends AbstractMessageLite<M, B>, B extends AbstractMessageLite.Builder<M, B>> {
static class Builder<M extends AbstractMessageLite<M, B>, B extends Builder<M, B>> {
@SuppressWarnings("unchecked")
B internalMergeFrom(M other) {
return (B) this;
}
}
}

@Test
public void getAllMethods() {
Types types = compilation.getTypes();
Expand Down

0 comments on commit 39743a8

Please sign in to comment.