Skip to content

Commit

Permalink
jqno#201 Fixes bug in interplay with abstract methods and lazy initia…
Browse files Browse the repository at this point in the history
…lization
  • Loading branch information
jqno committed Jul 29, 2018
1 parent c69caa0 commit 29954fe
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ private void safelyCheckSuperProperties(ObjectAccessor<T> referenceAccessor) {
try {
checkSuperProperties(reference, equalSuper, shallowCopy);
}
catch (AbstractMethodError ignored) {
// In this case, we'll assume all super properties hold.
catch (AbstractMethodError | NullPointerException ignored) {
// In these cases, we'll assume all super properties hold.
// The problems we test for, can never occur anyway if you can't instantiate a super instance.
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,25 @@ private void handle(String testedMethodName, Field field, Runnable r) {
catch (NullPointerException e) {
npeThrown(testedMethodName, field, e);
}
catch (AbstractMethodError e) {
abstractMethodErrorThrown(testedMethodName, field, e);
}
catch (Exception e) {
exceptionThrown(testedMethodName, field, e);
}
}

private void npeThrown(String method, Field field, Exception e) {
private void npeThrown(String method, Field field, NullPointerException e) {
fail(Formatter.of("Non-nullity: %% throws NullPointerException on field %%.", method, field.getName()), e);
}

private void abstractMethodErrorThrown(String method, Field field, AbstractMethodError e) {
fail(Formatter.of(
"Abstract delegation: %% throws AbstractMethodError when field %% is null.\n" +
"Suppress Warning.NULL_FIELDS to disable this check.",
method, field.getName()), e);
}

private void exceptionThrown(String method, Field field, Exception e) {
fail(Formatter.of("%% throws %% when field %% is null.", method, e.getClass().getSimpleName(), field.getName()), e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@ public void succeed_whenEqualsThrowsNull_givenClassIsAbstractAndWarningIsSuppres
.verify();
}

@Test
public void fail_whenAbstractImplementationThrowsNpe() {
expectFailure("Abstract delegation: equals throws AbstractMethodError when field object is null");
EqualsVerifier.forClass(NullThrowingLazyObjectContainer.class)
.suppress(Warning.NONFINAL_FIELDS)
.withIgnoredFields("objectFactory")
.verify();
}

@Test
public void succeed_whenAbstractImplementationThrowsNpe_givenWarningIsSuppressed() {
EqualsVerifier.forClass(NullThrowingLazyObjectContainer.class)
.suppress(Warning.NULL_FIELDS, Warning.NONFINAL_FIELDS)
.withIgnoredFields("objectFactory")
.verify();
}

abstract static class AbstractFinalMethodsPoint {
private final int x;
private final int y;
Expand Down Expand Up @@ -113,4 +130,43 @@ public final boolean equals(Object obj) {

@Override public final int hashCode() { return defaultHashCode(this); }
}

interface Supplier<T> {
T get();
}

abstract static class AbstractLazyObjectContainer {
private Object object;

private Object getObject() {
if (object == null) {
object = createObject();
}
return object;
}

protected abstract Object createObject();

@Override
public boolean equals(final Object obj) {
if (!(obj instanceof AbstractLazyObjectContainer)) {
return false;
}
AbstractLazyObjectContainer other = (AbstractLazyObjectContainer)obj;
return getObject().equals(other.getObject());
}

@Override public int hashCode() { return getObject().hashCode(); }
}

static final class NullThrowingLazyObjectContainer extends AbstractLazyObjectContainer {
private final Supplier<Object> objectFactory;

protected NullThrowingLazyObjectContainer(Supplier<Object> flourFactory) { this.objectFactory = flourFactory; }

@Override
protected Object createObject() {
return objectFactory.get();
}
}
}

0 comments on commit 29954fe

Please sign in to comment.