Skip to content

Commit

Permalink
jqno#199 Support empty enums
Browse files Browse the repository at this point in the history
  • Loading branch information
jqno committed Jul 30, 2018
1 parent bc30b81 commit 0f9a148
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ private void assertFieldShouldBeIgnored(boolean equalToItself, boolean equalsCha
boolean fieldIsEligible = !referenceAccessor.fieldIsStatic() &&
!referenceAccessor.fieldIsTransient() &&
!classAccessor.fieldHasAnnotation(referenceAccessor.getField(), SupportedAnnotations.TRANSIENT) &&
!referenceAccessor.fieldIsSingleValueEnum();
!referenceAccessor.fieldIsEmptyOrSingleValueEnum();

if (allFieldsShouldBeUsed && fieldIsEligible) {
assertTrue(Formatter.of("Significant fields: equals does not use %%.", fieldName), equalToItself);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ public <T> T giveOther(TypeTag tag, T value) {
}

Tuple<T> tuple = giveTuple(tag);
if (tuple.getRed() == null) {
return null;
}
if (type.isArray() && arraysAreDeeplyEqual(tuple.getRed(), value)) {
return tuple.getBlack();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package nl.jqno.equalsverifier.internal.prefabvalues.factories;

import nl.jqno.equalsverifier.internal.exceptions.ReflectionException;
import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues;
import nl.jqno.equalsverifier.internal.prefabvalues.Tuple;
import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag;
Expand Down Expand Up @@ -45,7 +44,7 @@ private Tuple<T> giveEnumInstances(TypeTag tag) {

switch (enumConstants.length) {
case 0:
throw new ReflectionException("Enum " + type.getSimpleName() + " has no elements");
return new Tuple<>(null, null, null);
case 1:
return new Tuple<>(enumConstants[0], enumConstants[0], enumConstants[0]);
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ public boolean fieldIsTransient() {
/**
* Returns whether the field is an enum with a single value.
*/
public boolean fieldIsSingleValueEnum() {
public boolean fieldIsEmptyOrSingleValueEnum() {
Class<?> type = field.getType();
return type.isEnum() && type.getEnumConstants().length == 1;
return type.isEnum() && type.getEnumConstants().length <= 1;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ public void succeed_whenClassIsAnEnum() {
.verify();
}

@Test
public void succeed_whenClassHasAnEmptyEnumButIgnoresIt() {
EqualsVerifier.forClass(EmptyEnumContainer.class)
.verify();
}

@Test
public void succeed_whenClassHasASingletonEnumButIgnoresIt() {
EqualsVerifier.forClass(SingletonContainer.class)
Expand Down Expand Up @@ -54,6 +60,31 @@ enum Enum {

enum Singleton { INSTANCE }

enum Empty {}

static final class EmptyEnumContainer {
private final int i;

@SuppressWarnings("unused")
private final Empty empty;

public EmptyEnumContainer(int i, Empty empty) { this.i = i; this.empty = empty; }

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

@Override
public int hashCode() {
return i;
}
}

static final class SingletonContainer {
private final int i;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package nl.jqno.equalsverifier.internal.prefabvalues;

import nl.jqno.equalsverifier.internal.exceptions.RecursionException;
import nl.jqno.equalsverifier.internal.exceptions.ReflectionException;
import nl.jqno.equalsverifier.testhelpers.PrefabValuesFactory;
import nl.jqno.equalsverifier.testhelpers.types.Point;
import nl.jqno.equalsverifier.testhelpers.types.RecursiveTypeHelper.*;
Expand All @@ -21,6 +20,7 @@ public class PrefabValuesCreatorTest {
private static final TypeTag POINT_TAG = new TypeTag(Point.class);
private static final TypeTag ENUM_TAG = new TypeTag(Enum.class);
private static final TypeTag ONE_ELT_ENUM_TAG = new TypeTag(OneElementEnum.class);
private static final TypeTag EMPTY_ENUM_TAG = new TypeTag(EmptyEnum.class);
private static final TypeTag NODE_TAG = new TypeTag(Node.class);
private static final TypeTag NODE_ARRAY_TAG = new TypeTag(NodeArray.class);
private static final TypeTag TWOSTEP_NODE_A_TAG = new TypeTag(TwoStepNodeA.class);
Expand Down Expand Up @@ -66,9 +66,8 @@ public void createOneElementEnum() {

@Test
public void createEmptyEnum() {
thrown.expect(ReflectionException.class);
thrown.expectMessage("Enum EmptyEnum has no elements");
prefabValues.giveRed(new TypeTag(EmptyEnum.class));
assertNull(prefabValues.giveRed(EMPTY_ENUM_TAG));
assertNull(prefabValues.giveBlack(EMPTY_ENUM_TAG));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package nl.jqno.equalsverifier.internal.prefabvalues.factories;

import nl.jqno.equalsverifier.internal.exceptions.RecursionException;
import nl.jqno.equalsverifier.internal.exceptions.ReflectionException;
import nl.jqno.equalsverifier.internal.prefabvalues.PrefabValues;
import nl.jqno.equalsverifier.internal.prefabvalues.Tuple;
import nl.jqno.equalsverifier.internal.prefabvalues.TypeTag;
Expand Down Expand Up @@ -42,9 +41,8 @@ public void setUp() {
}

@Test
public void dontGiveEmptyEnum() {
thrown.expect(ReflectionException.class);
new FallbackFactory<>().createValues(new TypeTag(EmptyEnum.class), prefabValues, typeStack);
public void giveNullInsteadOfEmptyEnum() {
assertCorrectTuple(EmptyEnum.class, null, null);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,21 +117,28 @@ public void isTransient() {
public void isNotEnum() {
PrimitiveContainer foo = new PrimitiveContainer();
FieldAccessor fieldAccessor = getAccessorFor(foo, FIELD_NAME);
assertFalse(fieldAccessor.fieldIsSingleValueEnum());
assertFalse(fieldAccessor.fieldIsEmptyOrSingleValueEnum());
}

@Test
public void isEnumButNotSingleValue() {
EnumContainer foo = new EnumContainer();
FieldAccessor fieldAccessor = getAccessorFor(foo, "twoElementEnum");
assertFalse(fieldAccessor.fieldIsSingleValueEnum());
assertFalse(fieldAccessor.fieldIsEmptyOrSingleValueEnum());
}

@Test
public void isSingleValueEnum() {
EnumContainer foo = new EnumContainer();
FieldAccessor fieldAccessor = getAccessorFor(foo, "oneElementEnum");
assertTrue(fieldAccessor.fieldIsSingleValueEnum());
assertTrue(fieldAccessor.fieldIsEmptyOrSingleValueEnum());
}

@Test
public void isEmptyEnum() {
EnumContainer foo = new EnumContainer();
FieldAccessor fieldAccessor = getAccessorFor(foo, "emptyEnum");
assertTrue(fieldAccessor.fieldIsEmptyOrSingleValueEnum());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ public enum EmptyEnum {}

@SuppressWarnings("unused")
public static final class EnumContainer {
private EmptyEnum emptyEnum;
private OneElementEnum oneElementEnum;
private TwoElementEnum twoElementEnum;
}
Expand Down

0 comments on commit 0f9a148

Please sign in to comment.