Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Number and Temporal type validations #10

Merged
merged 4 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ private static <P> void assertThatValidationIsCompliantForEachProperty(
// Check if there are any violations
assertThat(violations)
.withFailMessage(
"More than one property failed to validate during mutation. The supplied parameter is possibly contains invalid values.")
"More than one property failed to validate during mutation. The supplied parameter possibly contains invalid values."
)
.hasSizeLessThan(2);

assertThat(violations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.NonNull;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
Expand All @@ -16,6 +17,12 @@ public class BiggerThanValueSource implements ValueSource {
private static final Random RANDOM = new Random();

static {
TYPE_SOURCES.put(Byte.class, BiggerThanValueSource::getByteStream);
TYPE_SOURCES.put(byte.class, BiggerThanValueSource::getByteStream);

TYPE_SOURCES.put(Short.class, BiggerThanValueSource::getShortStream);
TYPE_SOURCES.put(short.class, BiggerThanValueSource::getShortStream);

TYPE_SOURCES.put(Integer.class, BiggerThanValueSource::getIntegerStream);
TYPE_SOURCES.put(int.class, BiggerThanValueSource::getIntegerStream);

Expand All @@ -28,11 +35,12 @@ public class BiggerThanValueSource implements ValueSource {
TYPE_SOURCES.put(Double.class, BiggerThanValueSource::getDoubleStream);
TYPE_SOURCES.put(double.class, BiggerThanValueSource::getDoubleStream);

TYPE_SOURCES.put(BigInteger.class, BiggerThanValueSource::getBigIntegerStream);
TYPE_SOURCES.put(BigDecimal.class, BiggerThanValueSource::getBigDecimalStream);
TYPE_SOURCES.put(ScaledBigDecimal.class, BiggerThanValueSource::getScaledBigDecimalStream);
}

@SuppressWarnings("unchecked")
@SuppressWarnings("unused")
public static void registerType(Class<?> type, Function<Object[], Stream<?>> source) {
TYPE_SOURCES.put(type, source);
}
Expand All @@ -48,14 +56,38 @@ public <T> Stream<T> values(Class<T> propertyClass, Object... args) {
throw new IllegalArgumentException("Property class not supported!");
}

@NonNull
private static Stream<Byte> getByteStream(Object[] args) {
var minValue = (byte) (Long.valueOf((long) args[0]).byteValue() + 1);
var maxValue = Byte.MAX_VALUE;

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.ints(1, minValue, maxValue)
.mapToObj(value -> Byte.valueOf((byte) value))
);
}

@NonNull
private static Stream<Short> getShortStream(Object[] args) {
var minValue = (short) (Long.valueOf((long) args[0]).shortValue() + 1);
var maxValue = Short.MAX_VALUE;

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.ints(1, minValue, maxValue)
.mapToObj(value -> Short.valueOf((short) value))
);
}

@NonNull
private static Stream<Integer> getIntegerStream(Object[] args) {
var minValue = Long.valueOf((long) args[0]).intValue() + 1;
var maxValue = Integer.MAX_VALUE;

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.ints(minValue, maxValue).limit(1).boxed()
RANDOM.ints(1, minValue, maxValue).boxed()
);
}

Expand All @@ -66,7 +98,7 @@ private static Stream<Long> getLongStream(Object[] args) {

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.longs(minValue, maxValue).limit(1).boxed()
RANDOM.longs(1, minValue, maxValue).boxed()
);
}

Expand All @@ -77,7 +109,7 @@ private static Stream<Float> getFloatStream(Object[] args) {

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.doubles(minValue, maxValue).limit(1).boxed().map(
RANDOM.doubles(1, minValue, maxValue).boxed().map(
Double::floatValue
)
);
Expand All @@ -90,18 +122,20 @@ private static Stream<Double> getDoubleStream(Object[] args) {

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.doubles(minValue, maxValue).limit(1).boxed()
RANDOM.doubles(1, minValue, maxValue).boxed()
);
}

@NonNull
private static Stream<ScaledBigDecimal> getScaledBigDecimalStream(Object[] args) {
var minValue = Long.valueOf((long) args[0]).doubleValue() + 0.1d;
var maxValue = Double.MAX_VALUE;
private static Stream<BigInteger> getBigIntegerStream(Object[] args) {
var minValue = (long) args[0] + 1;
var maxValue = Long.MAX_VALUE;

return Stream.concat(
Stream.of(ScaledBigDecimal.valueOf(minValue), ScaledBigDecimal.valueOf(maxValue)),
RANDOM.doubles(minValue, maxValue).limit(1).boxed().map(ScaledBigDecimal::valueOf)
Stream.of(BigInteger.valueOf(minValue), BigInteger.valueOf(maxValue)),
RANDOM.longs(1, minValue, maxValue).boxed().map(
BigInteger::valueOf
)
);
}

Expand All @@ -112,7 +146,22 @@ private static Stream<BigDecimal> getBigDecimalStream(Object[] args) {

return Stream.concat(
Stream.of(BigDecimal.valueOf(minValue), BigDecimal.valueOf(maxValue)),
RANDOM.doubles(minValue, maxValue).limit(1).boxed().map(BigDecimal::valueOf)
RANDOM.doubles(1, minValue, maxValue).boxed().map(
BigDecimal::valueOf
)
);
}

@NonNull
private static Stream<ScaledBigDecimal> getScaledBigDecimalStream(Object[] args) {
var minValue = Long.valueOf((long) args[0]).doubleValue() + 0.1d;
var maxValue = Double.MAX_VALUE;

return Stream.concat(
Stream.of(ScaledBigDecimal.valueOf(minValue), ScaledBigDecimal.valueOf(maxValue)),
RANDOM.doubles(1, minValue, maxValue).boxed().map(
ScaledBigDecimal::valueOf
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@

import it.aboutbits.springboot.testing.validation.core.ValueSource;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.Year;
import java.time.YearMonth;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
Expand All @@ -14,10 +21,17 @@
public class FutureValueSource implements ValueSource {
private static final Map<Class<?>, Function<Object[], Stream<?>>> TYPE_SOURCES = new HashMap<>();

// https://jakarta.ee/specifications/bean-validation/3.0/apidocs/jakarta/validation/constraints/future
static {
TYPE_SOURCES.put(Instant.class, FutureValueSource::getInstantStream);
TYPE_SOURCES.put(LocalTime.class, FutureValueSource::getLocalTimeStream);
TYPE_SOURCES.put(LocalDate.class, FutureValueSource::getLocalDateStream);
TYPE_SOURCES.put(LocalDateTime.class, FutureValueSource::getLocalDatetimeStream);
TYPE_SOURCES.put(LocalDateTime.class, FutureValueSource::getLocalDateTimeStream);
TYPE_SOURCES.put(OffsetTime.class, FutureValueSource::getOffsetTimeStream);
TYPE_SOURCES.put(OffsetDateTime.class, FutureValueSource::getOffsetDateTimeStream);
TYPE_SOURCES.put(Year.class, FutureValueSource::getYearStream);
TYPE_SOURCES.put(YearMonth.class, FutureValueSource::getYearMonthStream);
TYPE_SOURCES.put(ZonedDateTime.class, FutureValueSource::getZonedDateTimeStream);
}

@SuppressWarnings("unused")
Expand All @@ -36,24 +50,66 @@ public <T> Stream<T> values(Class<T> propertyClass, Object... args) {
throw new IllegalArgumentException("Property class not supported!");
}

private static Stream<Instant> getInstantStream(Object[] args) {
var currentInstant = Instant.now();
var largestInstant = Instant.MAX;

return Stream.of(currentInstant.plusSeconds(1L), largestInstant);
}

private static Stream<LocalTime> getLocalTimeStream(Object[] args) {
var currentLocalTime = LocalTime.now();
var largestLocalTime = LocalTime.MAX;

return Stream.of(currentLocalTime.plusSeconds(1L), largestLocalTime);
}

private static Stream<LocalDate> getLocalDateStream(Object[] args) {
var currentDate = LocalDate.now();
var largestDate = LocalDate.MAX;

return Stream.of(currentDate.plusDays(1), largestDate);
return Stream.of(currentDate.plusDays(1L), largestDate);
}

private static Stream<LocalDateTime> getLocalDatetimeStream(Object[] args) {
private static Stream<LocalDateTime> getLocalDateTimeStream(Object[] args) {
var currentDateTime = LocalDateTime.now();
var largestDateTime = LocalDateTime.MAX;

return Stream.of(currentDateTime.plusSeconds(1), largestDateTime);
return Stream.of(currentDateTime.plusSeconds(1L), largestDateTime);
}

private static Stream<OffsetTime> getOffsetTimeStream(Object[] args) {
var currentOffsetTime = OffsetTime.now(ZoneOffset.UTC);
var largestOffsetTime = OffsetTime.MAX;

return Stream.of(currentOffsetTime.plusSeconds(1L), largestOffsetTime);
}

private static Stream<OffsetDateTime> getOffsetDateTimeStream(Object[] args) {
var currentOffsetDateTime = OffsetDateTime.now(ZoneOffset.UTC);
var largestOffsetDateTime = OffsetDateTime.MAX;

return Stream.of(currentOffsetDateTime.plusSeconds(1), largestOffsetDateTime);
return Stream.of(currentOffsetDateTime.plusSeconds(1L), largestOffsetDateTime);
}

private static Stream<Year> getYearStream(Object[] args) {
var currentYear = Year.now();
var largestYear = Year.of(Year.MAX_VALUE);

return Stream.of(currentYear.plusYears(1L), largestYear);
}

private static Stream<YearMonth> getYearMonthStream(Object[] args) {
var currentYearMonth = YearMonth.now();
var largestYearMonth = YearMonth.of(Year.MAX_VALUE, Month.DECEMBER);

return Stream.of(currentYearMonth.plusMonths(1L), largestYearMonth);
}

private static Stream<ZonedDateTime> getZonedDateTimeStream(Object[] args) {
var currentZonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);
var largestZonedDateTime = LocalDateTime.MAX.atZone(ZoneOffset.MIN);

return Stream.of(currentZonedDateTime.plusSeconds(1L), largestZonedDateTime);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.NonNull;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
Expand All @@ -17,6 +18,12 @@ public class LessThanValueSource implements ValueSource {
private static final Random RANDOM = new Random();

static {
TYPE_SOURCES.put(Byte.class, LessThanValueSource::getByteStream);
TYPE_SOURCES.put(byte.class, LessThanValueSource::getByteStream);

TYPE_SOURCES.put(Short.class, LessThanValueSource::getShortStream);
TYPE_SOURCES.put(short.class, LessThanValueSource::getShortStream);

TYPE_SOURCES.put(Integer.class, LessThanValueSource::getIntegerStream);
TYPE_SOURCES.put(int.class, LessThanValueSource::getIntegerStream);

Expand All @@ -29,6 +36,7 @@ public class LessThanValueSource implements ValueSource {
TYPE_SOURCES.put(Double.class, LessThanValueSource::getDoubleStream);
TYPE_SOURCES.put(double.class, LessThanValueSource::getDoubleStream);

TYPE_SOURCES.put(BigInteger.class, LessThanValueSource::getBigIntegerStream);
TYPE_SOURCES.put(BigDecimal.class, LessThanValueSource::getBigDecimalStream);
TYPE_SOURCES.put(ScaledBigDecimal.class, LessThanValueSource::getScaledBigDecimalStream);
}
Expand All @@ -49,14 +57,38 @@ public <T> Stream<T> values(Class<T> propertyClass, Object... args) {
throw new IllegalArgumentException("Property class not supported!");
}

@NonNull
private static Stream<Byte> getByteStream(Object[] args) {
var minValue = Byte.MIN_VALUE;
var maxValue = (byte) (Long.valueOf((long) args[0]).byteValue() - 1);

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.ints(1, minValue, maxValue)
.mapToObj(value -> Byte.valueOf((byte) value))
);
}

@NonNull
private static Stream<Short> getShortStream(Object[] args) {
var minValue = Short.MIN_VALUE;
var maxValue = (short) (Long.valueOf((long) args[0]).shortValue() - 1);

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.ints(1, minValue, maxValue)
.mapToObj(value -> Short.valueOf((short) value))
);
}

@NonNull
private static Stream<Integer> getIntegerStream(Object[] args) {
var minValue = Integer.MIN_VALUE;
var maxValue = Long.valueOf((long) args[0]).intValue() - 1;

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.ints(minValue, maxValue).limit(1).boxed()
RANDOM.ints(1, minValue, maxValue).boxed()
);
}

Expand All @@ -67,7 +99,7 @@ private static Stream<Long> getLongStream(Object[] args) {

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.longs(minValue, maxValue).limit(1).boxed()
RANDOM.longs(1, minValue, maxValue).boxed()
);
}

Expand All @@ -78,7 +110,7 @@ private static Stream<Float> getFloatStream(Object[] args) {

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.doubles(1).map(d -> minValue + (maxValue - minValue) * d).boxed().map(
RANDOM.doubles(1, minValue, maxValue).boxed().map(
Double::floatValue
)
);
Expand All @@ -91,7 +123,20 @@ private static Stream<Double> getDoubleStream(Object[] args) {

return Stream.concat(
Stream.of(minValue, maxValue),
RANDOM.doubles(1).map(d -> minValue + (maxValue - minValue) * d).boxed()
RANDOM.doubles(1, minValue, maxValue).boxed()
);
}

@NonNull
private static Stream<BigInteger> getBigIntegerStream(Object[] args) {
var minValue = Long.MIN_VALUE;
var maxValue = (long) args[0] - 1;

return Stream.concat(
Stream.of(BigInteger.valueOf(minValue), BigInteger.valueOf(maxValue)),
RANDOM.longs(1, minValue, maxValue).boxed().map(
BigInteger::valueOf
)
);
}

Expand All @@ -102,7 +147,9 @@ private static Stream<BigDecimal> getBigDecimalStream(Object[] args) {

return Stream.concat(
Stream.of(BigDecimal.valueOf(minValue), BigDecimal.valueOf(maxValue)),
RANDOM.doubles(1).map(d -> minValue + (maxValue - minValue) * d).boxed().map(BigDecimal::valueOf)
RANDOM.doubles(1, minValue, maxValue).boxed().map(
BigDecimal::valueOf
)
);
}

Expand All @@ -113,7 +160,9 @@ private static Stream<ScaledBigDecimal> getScaledBigDecimalStream(Object[] args)

return Stream.concat(
Stream.of(ScaledBigDecimal.valueOf(minValue), ScaledBigDecimal.valueOf(maxValue)),
RANDOM.doubles(1).map(d -> minValue + (maxValue - minValue) * d).boxed().map(ScaledBigDecimal::valueOf)
RANDOM.doubles(1, minValue, maxValue).boxed().map(
ScaledBigDecimal::valueOf
)
);
}
}
Loading