Skip to content

Commit

Permalink
Let ValueProvider return an Optional
Browse files Browse the repository at this point in the history
  • Loading branch information
jqno committed Dec 4, 2024
1 parent d1c00ba commit 411284c
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private void checkAbstractDelegationInFields() {

private <U> Tuple<U> safelyGetTuple(TypeTag tag) {
try {
return valueProvider.provide(tag);
return valueProvider.provideOrThrow(tag);
} catch (Exception ignored) {
// If it fails for some reason, any reason, just return null so we can skip the test.
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public MapEntryHashCodeRequirementChecker(Context<T> context) {
public void check() {
if (Map.Entry.class.isAssignableFrom(config.getType())) {
Map.Entry<?, ?> e = valueProvider
.<Map.Entry<?, ?>>provide(config.getTypeTag())
.<Map.Entry<?, ?>>provideOrThrow(config.getTypeTag())
.getRed();

int expectedHashCode = Objects.hashCode(e.getKey()) ^ Objects.hashCode(e.getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@
import java.util.function.Function;
import nl.jqno.equalsverifier.Warning;
import nl.jqno.equalsverifier.internal.exceptions.EqualsVerifierInternalBugException;
import nl.jqno.equalsverifier.internal.reflection.ClassProbe;
import nl.jqno.equalsverifier.internal.reflection.FieldProbe;
import nl.jqno.equalsverifier.internal.reflection.Instantiator;
import nl.jqno.equalsverifier.internal.reflection.Tuple;
import nl.jqno.equalsverifier.internal.reflection.TypeTag;
import nl.jqno.equalsverifier.internal.reflection.*;
import nl.jqno.equalsverifier.internal.reflection.annotations.AnnotationCache;
import nl.jqno.equalsverifier.internal.reflection.annotations.SupportedAnnotations;
import nl.jqno.equalsverifier.internal.reflection.instantiation.SubjectCreator;
Expand Down Expand Up @@ -67,8 +63,8 @@ public void execute(FieldProbe fieldProbe) {
classProbe.hasMethod(getterName)
);

Class<T> sub = throwingGetterCreator(getterName);
Tuple<T> tuple = valueProvider.<T>provide(new TypeTag(sub));
TypeTag sub = new TypeTag(throwingGetterCreator(getterName));
Tuple<T> tuple = valueProvider.<T>provideOrThrow(sub);
T red1 = tuple.getRed();
T red2 = tuple.getRedCopy();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private void checkValueReflexivity(FieldProbe probe) {
TypeTag tag = TypeTag.of(field, typeTag);
Tuple<?> tuple = prefabbedFields.contains(fieldName)
? fieldCache.get(fieldName)
: valueProvider.provide(tag);
: valueProvider.provideOrThrow(tag);

Object left = subjectCreator.withFieldSetTo(field, tuple.getRed());
Object right = subjectCreator.withFieldSetTo(field, tuple.getRedCopy());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public StringFieldCheck(
)
public void execute(FieldProbe fieldProbe) {
if (String.class.equals(fieldProbe.getType()) && !fieldProbe.isStatic()) {
String red = valueProvider.<String>provide(new TypeTag(String.class)).getRed();
TypeTag string = new TypeTag(String.class);
String red = valueProvider.<String>provideOrThrow(string).getRed();

final T reference;
final T copy;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package nl.jqno.equalsverifier.internal.exceptions;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import nl.jqno.equalsverifier.internal.reflection.TypeTag;

@SuppressFBWarnings(value = "SE_BAD_FIELD", justification = "EqualsVerifier doesn't serialize.")
public class NoValueException extends MessagingException {

private final TypeTag tag;

public NoValueException(TypeTag tag) {
super();
this.tag = tag;
}

@Override
public String getDescription() {
return "Could not find a value for " + tag + ". Please add prefab values for this type.";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ private Tuple<?> valuesFor(Field f) {
return fieldCache.get(fieldName);
}
try {
Tuple<?> tuple = valueProvider.provide(TypeTag.of(f, typeTag));
TypeTag fieldTag = TypeTag.of(f, typeTag);
Tuple<?> tuple = valueProvider.provideOrThrow(fieldTag);
fieldCache.put(fieldName, tuple);
return tuple;
} catch (ModuleException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package nl.jqno.equalsverifier.internal.reflection.instantiation;

import java.util.Optional;
import nl.jqno.equalsverifier.internal.exceptions.NoValueException;
import nl.jqno.equalsverifier.internal.reflection.Tuple;
import nl.jqno.equalsverifier.internal.reflection.TypeTag;

Expand All @@ -18,7 +20,22 @@ public interface ValueProvider {
*
* @param <T> The returned tuple will have this generic type.
* @param tag A description of the desired type, including generic parameters.
* @return A tuple of two different values of the given type.
* @return A tuple of two different values of the given type, or an empty Optional if none
* could be found.
*/
<T> Tuple<T> provide(TypeTag tag);
<T> Optional<Tuple<T>> provide(TypeTag tag);

/**
* Returns a tuple of prefabricated values of the specified type, or, if none exists, throws a
* NoValueException.
*
* @param <T> The returned tuple will have this generic type.
* @param tag A description of the desired type, including generic parameters.
* @return A tuple of two different values of the given type, or an empty Optional if none
* could be found.
* @throws NoValueException if no value could be found for the given tag.
*/
default <T> Tuple<T> provideOrThrow(TypeTag tag) {
return this.<T>provide(tag).orElseThrow(() -> new NoValueException(tag));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public VintageValueProvider(FactoryCache factoryCache, Objenesis objenesis) {

/** {@inheritDoc} */
@Override
public <T> Tuple<T> provide(TypeTag tag) {
return Rethrow.rethrow(() -> giveTuple(tag));
public <T> Optional<Tuple<T>> provide(TypeTag tag) {
return Rethrow.rethrow(() -> Optional.of(giveTuple(tag)));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package nl.jqno.equalsverifier.internal.exceptions;

import static org.junit.jupiter.api.Assertions.assertTrue;

import nl.jqno.equalsverifier.internal.reflection.TypeTag;
import org.junit.jupiter.api.Test;

public class NoValueExceptionTest {

@Test
public void description() {
TypeTag tag = new TypeTag(String.class);
NoValueException e = new NoValueException(tag);
assertTrue(e.getDescription().contains("String"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@

import java.lang.reflect.Field;
import java.util.Objects;
import java.util.Optional;
import nl.jqno.equalsverifier.internal.exceptions.NoValueException;
import nl.jqno.equalsverifier.internal.reflection.FieldCache;
import nl.jqno.equalsverifier.internal.reflection.Tuple;
import nl.jqno.equalsverifier.internal.reflection.TypeTag;
import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException;
import nl.jqno.equalsverifier.internal.util.Configuration;
import nl.jqno.equalsverifier.internal.util.ConfigurationHelper;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -49,9 +52,6 @@ public void setup() throws NoSuchFieldException {
fieldS = SomeClass.class.getDeclaredField("s");
}

@Test
public void sanity() {}

@Test
public void plain() {
expected = new SomeClass(I_RED, I_RED, S_RED);
Expand Down Expand Up @@ -194,16 +194,36 @@ public void copyIntoSubclass() {
assertEquals(SomeSub.class, actual.getClass());
}

@Test
public void noValueFound() {
sut = new SubjectCreator<>(config, new NoValueProvider(), fieldCache, objenesis);

ExpectedException
.when(() -> sut.plain())
.assertThrows(NoValueException.class)
.assertDescriptionContains("int");

assertEquals(expected, actual);
}

static class SubjectCreatorTestValueProvider implements ValueProvider {

public <T> Tuple<T> provide(TypeTag tag) {
public <T> Optional<Tuple<T>> provide(TypeTag tag) {
if (int.class.equals(tag.getType())) {
return Tuple.of(I_RED, I_BLUE, I_RED);
return Optional.of(Tuple.of(I_RED, I_BLUE, I_RED));
}
if (String.class.equals(tag.getType())) {
return Tuple.of(S_RED, S_BLUE, new String(S_RED));
return Optional.of(Tuple.of(S_RED, S_BLUE, new String(S_RED)));
}
throw new IllegalStateException();
return Optional.empty();
}
}

static class NoValueProvider implements ValueProvider {

@Override
public <T> Optional<Tuple<T>> provide(TypeTag tag) {
return Optional.empty();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.fail;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.*;
import nl.jqno.equalsverifier.internal.reflection.FactoryCache;
import nl.jqno.equalsverifier.internal.reflection.Tuple;
import nl.jqno.equalsverifier.internal.reflection.TypeTag;
Expand Down Expand Up @@ -48,8 +46,11 @@ public void sanityTestFactoryIncreasesStringLength() {

@Test
public void provide() {
Tuple<Point> actual = vp.provide(POINT_TAG);
assertEquals(Tuple.of(new Point(42, 42), new Point(1337, 1337), new Point(42, 42)), actual);
Optional<Tuple<Point>> actual = vp.provide(POINT_TAG);
assertEquals(
Tuple.of(new Point(42, 42), new Point(1337, 1337), new Point(42, 42)),
actual.get()
);
}

@Test
Expand Down

0 comments on commit 411284c

Please sign in to comment.