diff --git a/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/SealedTypesRecursionTest.java b/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/SealedTypesRecursionTest.java index 0dcc334a2..e1adf31da 100644 --- a/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/SealedTypesRecursionTest.java +++ b/equalsverifier-17/src/test/java/nl/jqno/equalsverifier/integration/extended_contract/SealedTypesRecursionTest.java @@ -8,7 +8,7 @@ class SealedTypesRecursionTest { @Test - public void testEV() { + public void dontThrowStackOverflowError_whenOnlyPermittedSubclassInSealedInterfaceRefersBackToContainer() { // A container with a field of a sealed interface. // The sealed interface permits only 1 type, which refers back to the container. ExpectedException @@ -22,6 +22,21 @@ public void testEV() { ); } + @Test + public void dontThrowStackOverflowError_whenOnlyPermittedRecordInSealedInterfaceRefersBackToContainer() { + // A container with a field of a sealed interface. + // The sealed interface permits only 1 type, which is a record that refers back to the container. + ExpectedException + .when(() -> EqualsVerifier.forClass(SealedRecordContainer.class).verify()) + .assertFailure() + .assertMessageContains( + "Recursive datastructure", + "Add prefab values for one of the following types", + "SealedRecordContainer", + "SealedRecordInterface" + ); + } + static final class SealedContainer { public final SealedInterface sealed; @@ -75,4 +90,35 @@ public boolean equals(Object obj) { return Objects.equals(container, other.container); } } + + static final class SealedRecordContainer { + + public final SealedRecordInterface sealed; + + public SealedRecordContainer(SealedRecordInterface sealed) { + this.sealed = sealed; + } + + @Override + public int hashCode() { + return Objects.hash(sealed); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof SealedRecordContainer)) { + return false; + } + SealedRecordContainer other = (SealedRecordContainer) obj; + return Objects.equals(sealed, other.sealed); + } + } + + sealed interface SealedRecordInterface permits OnlyPermittedRecordImplementation {} + + static final record OnlyPermittedRecordImplementation(SealedRecordContainer container) + implements SealedRecordInterface {} }