Skip to content

Commit

Permalink
Make bean validation handlers aware of custom registries
Browse files Browse the repository at this point in the history
Resolves #401
  • Loading branch information
fmbenhassine committed Oct 31, 2020
1 parent 265ab09 commit 8ee6f78
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import javax.validation.constraints.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -49,20 +48,19 @@ public class BeanValidationRandomizerRegistry implements RandomizerRegistry {
@Override
public void init(EasyRandomParameters parameters) {
long seed = parameters.getSeed();
Charset charset = parameters.getCharset();
annotationHandlers.put(AssertFalse.class, new AssertFalseAnnotationHandler());
annotationHandlers.put(AssertTrue.class, new AssertTrueAnnotationHandler());
annotationHandlers.put(Null.class, new NullAnnotationHandler());
annotationHandlers.put(Future.class, new FutureAnnotationHandler(seed));
annotationHandlers.put(FutureOrPresent.class, new FutureOrPresentAnnotationHandler(seed));
annotationHandlers.put(Past.class, new PastAnnotationHandler(seed));
annotationHandlers.put(PastOrPresent.class, new PastOrPresentAnnotationHandler(seed));
annotationHandlers.put(Future.class, new FutureAnnotationHandler(parameters));
annotationHandlers.put(FutureOrPresent.class, new FutureOrPresentAnnotationHandler(parameters));
annotationHandlers.put(Past.class, new PastAnnotationHandler(parameters));
annotationHandlers.put(PastOrPresent.class, new PastOrPresentAnnotationHandler(parameters));
annotationHandlers.put(Min.class, new MinMaxAnnotationHandler(seed));
annotationHandlers.put(Max.class, new MinMaxAnnotationHandler(seed));
annotationHandlers.put(DecimalMin.class, new DecimalMinMaxAnnotationHandler(seed));
annotationHandlers.put(DecimalMax.class, new DecimalMinMaxAnnotationHandler(seed));
annotationHandlers.put(Pattern.class, new PatternAnnotationHandler(seed));
annotationHandlers.put(Size.class, new SizeAnnotationHandler(seed, charset));
annotationHandlers.put(Size.class, new SizeAnnotationHandler(parameters));
annotationHandlers.put(Positive.class, new PositiveAnnotationHandler(seed));
annotationHandlers.put(PositiveOrZero.class, new PositiveOrZeroAnnotationHandler(seed));
annotationHandlers.put(Negative.class, new NegativeAnnotationHandler(seed));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,21 @@

class FutureAnnotationHandler implements BeanValidationAnnotationHandler {

private final long seed;
private EasyRandom easyRandom;
private EasyRandomParameters parameters;

FutureAnnotationHandler(long seed) {
this.seed = seed;
FutureAnnotationHandler(EasyRandomParameters parameters) {
this.parameters = parameters.copy();
}

@Override
public Randomizer<?> getRandomizer(Field field) {
if (easyRandom == null) {
LocalDate now = LocalDate.now();
EasyRandomParameters parameters = new EasyRandomParameters()
.seed(seed)
.dateRange(
now.plus(1, ChronoUnit.DAYS),
now.plusYears(EasyRandomParameters.DEFAULT_DATE_RANGE)
);
parameters.setDateRange(new EasyRandomParameters.Range<>(
now.plus(1, ChronoUnit.DAYS),
now.plusYears(EasyRandomParameters.DEFAULT_DATE_RANGE)
));
easyRandom = new EasyRandom(parameters);
}
return () -> easyRandom.nextObject(field.getType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,20 @@

class FutureOrPresentAnnotationHandler implements BeanValidationAnnotationHandler {

private final long seed;
private EasyRandom easyRandom;
private EasyRandomParameters parameters;

FutureOrPresentAnnotationHandler(long seed) {
this.seed = seed;
FutureOrPresentAnnotationHandler(EasyRandomParameters parameters) {
this.parameters = parameters.copy();
}

@Override
public Randomizer<?> getRandomizer(Field field) {
if (easyRandom == null) {
LocalDate now = LocalDate.now();
EasyRandomParameters parameters = new EasyRandomParameters()
.seed(seed)
.dateRange(now, now.plusYears(EasyRandomParameters.DEFAULT_DATE_RANGE));
parameters.setDateRange(new EasyRandomParameters.Range<>(
now, now.plusYears(EasyRandomParameters.DEFAULT_DATE_RANGE))
);
easyRandom = new EasyRandom(parameters);
}
return () -> easyRandom.nextObject(field.getType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,21 @@

class PastAnnotationHandler implements BeanValidationAnnotationHandler {

private final long seed;
private EasyRandom easyRandom;
private EasyRandomParameters parameters;

PastAnnotationHandler(long seed) {
this.seed = seed;
PastAnnotationHandler(EasyRandomParameters parameters) {
this.parameters = parameters.copy();
}

@Override
public Randomizer<?> getRandomizer(Field field) {
if (easyRandom == null) {
LocalDate now = LocalDate.now();
EasyRandomParameters parameters = new EasyRandomParameters()
.seed(seed)
.dateRange(
now.minusYears(EasyRandomParameters.DEFAULT_DATE_RANGE),
now.minus(1, ChronoUnit.DAYS)
);
parameters.setDateRange(new EasyRandomParameters.Range<>(
now.minusYears(EasyRandomParameters.DEFAULT_DATE_RANGE),
now.minus(1, ChronoUnit.DAYS)
));
easyRandom = new EasyRandom(parameters);
}
return () -> easyRandom.nextObject(field.getType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,19 @@

class PastOrPresentAnnotationHandler implements BeanValidationAnnotationHandler {

private final long seed;
private EasyRandom easyRandom;
private EasyRandomParameters parameters;

PastOrPresentAnnotationHandler(long seed) {
this.seed = seed;
PastOrPresentAnnotationHandler(EasyRandomParameters parameters) {
this.parameters = parameters.copy();
}

@Override
public Randomizer<?> getRandomizer(Field field) {
if (easyRandom == null) {
LocalDate now = LocalDate.now();
EasyRandomParameters parameters = new EasyRandomParameters()
.seed(seed)
.dateRange(now.minusYears(EasyRandomParameters.DEFAULT_DATE_RANGE), now);
parameters.setDateRange(new EasyRandomParameters.Range<>(
now.minusYears(EasyRandomParameters.DEFAULT_DATE_RANGE), now));
easyRandom = new EasyRandom(parameters);
}
return () -> easyRandom.nextObject(field.getType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;
Expand All @@ -45,13 +44,11 @@

class SizeAnnotationHandler implements BeanValidationAnnotationHandler {

private long seed;
private Charset charset;
private EasyRandom easyRandom;
private EasyRandomParameters parameters;

SizeAnnotationHandler(long seed, Charset charset) {
this.seed = seed;
this.charset = charset;
SizeAnnotationHandler(EasyRandomParameters parameters) {
this.parameters = parameters.copy();
}

@Override
Expand All @@ -64,23 +61,20 @@ public Randomizer<?> getRandomizer(Field field) {
final int min = sizeAnnotation.min();
final int max = sizeAnnotation.max() == Integer.MAX_VALUE ? 255 : sizeAnnotation.max();
if (easyRandom == null) {
EasyRandomParameters parameters = new EasyRandomParameters()
.seed(this.seed)
.charset(this.charset)
.collectionSizeRange(min, max)
.stringLengthRange(min, max);
parameters.setCollectionSizeRange(new EasyRandomParameters.Range<>(min, max));
parameters.setStringLengthRange(new EasyRandomParameters.Range<>(min, max));
easyRandom = new EasyRandom(parameters);
}

if (fieldType.equals(String.class)) {
return new StringRandomizer(charset, min, max, easyRandom.nextLong());
return new StringRandomizer(parameters.getCharset(), min, max, easyRandom.nextLong());
}

// FIXME: There should be away to reuse code from ArrayPopulator/CollectionPopulator/MapPopulator *without* making them public

if (isArrayType(fieldType)) {
return (Randomizer<Object>) () -> {
int randomSize = new IntegerRangeRandomizer(min, max, seed).getRandomValue();
int randomSize = new IntegerRangeRandomizer(min, max, parameters.getSeed()).getRandomValue();
Object result = Array.newInstance(field.getType().getComponentType(), randomSize);
for (int i = 0; i < randomSize; i++) {
Object randomElement = easyRandom.nextObject(fieldType.getComponentType());
Expand All @@ -92,7 +86,7 @@ public Randomizer<?> getRandomizer(Field field) {

if (isCollectionType(fieldType)) {
return (Randomizer<Object>) () -> {
int randomSize = new IntegerRangeRandomizer(min, max, seed).getRandomValue();
int randomSize = new IntegerRangeRandomizer(min, max, parameters.getSeed()).getRandomValue();
Type fieldGenericType = field.getGenericType();
Collection collection;

Expand All @@ -117,7 +111,7 @@ public Randomizer<?> getRandomizer(Field field) {
}
if (isMapType(fieldType)) {
return (Randomizer<Object>) () -> {
int randomSize = new IntegerRangeRandomizer(min, max, seed).getRandomValue();
int randomSize = new IntegerRangeRandomizer(min, max, parameters.getSeed()).getRandomValue();
Type fieldGenericType = field.getGenericType();
Map<Object, Object> map;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,27 @@

import org.jeasy.random.EasyRandom;
import org.jeasy.random.EasyRandomParameters;
import org.jeasy.random.randomizers.range.BigDecimalRangeRandomizer;
import org.jeasy.random.randomizers.range.IntegerRangeRandomizer;
import org.jeasy.random.randomizers.registry.CustomRandomizerRegistry;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -236,7 +246,7 @@ void generatedBeanShouldBeValidUsingBeanValidationAPI() {
}

@Test
void customRegistryTest() {
void customBeanValidationRegistryTest() {
// given
class Salary {
@Digits(integer = 2, fraction = 2) // OSS developer salary.. :-)
Expand All @@ -255,4 +265,52 @@ class Salary {
assertThat(salary.amount).isLessThanOrEqualTo(new BigDecimal("99.99"));
}

@Test
void customRegistryTest() {
// given
class Amount {
@NotNull
@Digits(integer = 12, fraction = 3)
protected BigDecimal amount;
}
class DiscountEffect {
@Digits(integer = 6, fraction = 4)
protected BigDecimal percentage;
protected Amount amount;
@Digits(integer = 12, fraction = 3)
protected BigDecimal quantity;
@NotNull
@DecimalMax("65535")
@DecimalMin("1")
protected Integer size;
}
class Discount {
@NotNull
@Size(min = 1)
@Valid
protected List<DiscountEffect> discountEffects;
}

CustomRandomizerRegistry registry = new CustomRandomizerRegistry();
registry.registerRandomizer(BigDecimal.class, new BigDecimalRangeRandomizer(new Double(5d), new Double(10d), Integer.valueOf(3)));
registry.registerRandomizer(Integer.class, new IntegerRangeRandomizer(5, 10));
EasyRandomParameters parameters = new EasyRandomParameters()
.randomizerRegistry(registry);
EasyRandom easyRandom = new EasyRandom(parameters);

// when
Discount discount = easyRandom.nextObject(Discount.class);

// then
assertThat(discount.discountEffects)
.isNotEmpty()
.allSatisfy(discountEffect -> {
assertThat(discountEffect).isNotNull();
assertThat(discountEffect.percentage).isBetween(new BigDecimal("5.000"), new BigDecimal("10.000"));
assertThat(discountEffect.quantity).isBetween(new BigDecimal("5.000"), new BigDecimal("10.000"));
assertThat(discountEffect.amount.amount).isBetween(new BigDecimal("5.000"), new BigDecimal("10.000"));
assertThat(discountEffect.size).isBetween(5, 10);
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -591,4 +591,33 @@ public void setMax(T max) {
this.max = max;
}
}

/**
* Return a shallow copy of randomization parameters.
* @return a shallow copy of randomization parameters.
*/
public EasyRandomParameters copy() {
EasyRandomParameters copy = new EasyRandomParameters();
copy.setSeed(this.getSeed());
copy.setObjectPoolSize(this.getObjectPoolSize());
copy.setRandomizationDepth(this.getRandomizationDepth());
copy.setCharset(this.getCharset());
copy.setScanClasspathForConcreteTypes(this.isScanClasspathForConcreteTypes());
copy.setOverrideDefaultInitialization(this.isOverrideDefaultInitialization());
copy.setIgnoreRandomizationErrors(this.isIgnoreRandomizationErrors());
copy.setBypassSetters(this.isBypassSetters());
copy.setCollectionSizeRange(this.getCollectionSizeRange());
copy.setStringLengthRange(this.getStringLengthRange());
copy.setDateRange(this.getDateRange());
copy.setTimeRange(this.getTimeRange());
copy.setExclusionPolicy(this.getExclusionPolicy());
copy.setObjectFactory(this.getObjectFactory());
copy.setRandomizerProvider(this.getRandomizerProvider());
copy.customRandomizerRegistry = this.getCustomRandomizerRegistry();
copy.exclusionRandomizerRegistry = this.getExclusionRandomizerRegistry();
copy.userRegistries = this.getUserRegistries();
copy.fieldExclusionPredicates = this.getFieldExclusionPredicates();
copy.typeExclusionPredicates = this.getTypeExclusionPredicates();
return copy;
}
}

0 comments on commit 8ee6f78

Please sign in to comment.