From 2dcd754888892c4ff769ee171ea0824aaa1e3832 Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Mon, 23 Dec 2024 15:22:39 +0900 Subject: [PATCH 01/13] Introduce repeatable annotation value collection for fields --- .../generator/ArbitraryGeneratorContext.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java index 69ae5f7ce..df7781a9e 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java @@ -18,12 +18,15 @@ package com.navercorp.fixturemonkey.api.generator; -import static java.util.stream.Collectors.toMap; +import static java.util.stream.Collectors.*; import java.lang.annotation.Annotation; +import java.lang.annotation.Repeatable; import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; @@ -107,6 +110,30 @@ public Optional findAnnotation(Class annotationClas return this.getResolvedProperty().getAnnotation(annotationClass); } + public List findAnnotations(Class annotationClass) { + List results = this.getResolvedProperty().getAnnotations().stream() + .filter(it -> annotationClass.isAssignableFrom(it.annotationType())) + .map(annotationClass::cast).collect(toList()); + + Repeatable repeatable = annotationClass.getAnnotation(Repeatable.class); + if (repeatable != null) { + Class containerClass = repeatable.value(); + this.getResolvedProperty().getAnnotations().stream() + .filter(it -> containerClass.isAssignableFrom(it.annotationType())) + .findFirst() + .ifPresent(container -> { + try { + Method valueMethod = container.annotationType().getDeclaredMethod("value"); + T[] values = (T[])valueMethod.invoke(container); + results.addAll(Arrays.asList(values)); + } catch (Exception ignored) { + } + }); + } + + return results; + } + public List getChildren() { return Collections.unmodifiableList(this.children); } From 396ef8f163f30ea3de5c9b14df534775cf89f0ff Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Mon, 23 Dec 2024 15:23:25 +0900 Subject: [PATCH 02/13] Enhance decimal validation constraints handling with accurate behavior --- .../JakartaValidationConstraintGenerator.java | 220 +++++++----------- .../JakartaValidationFixtureMonkeyTest.java | 6 +- .../spec/BigDecimalIntrospectorSpec.java | 8 + .../JavaxValidationConstraintGenerator.java | 220 +++++++----------- .../JavaxValidationFixtureMonkeyTest.java | 6 +- .../spec/BigDecimalIntrospectorSpec.java | 8 + 6 files changed, 190 insertions(+), 278 deletions(-) diff --git a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java index cdbc76a86..d46ad91b2 100644 --- a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java +++ b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java @@ -292,178 +292,126 @@ public JavaIntegerConstraint generateIntegerConstraint(ArbitraryGeneratorContext @Override @Nullable public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext context) { - BigDecimal positiveMin = null; - Boolean positiveMinInclusive = null; - BigDecimal positiveMax = null; - Boolean positiveMaxInclusive = null; - BigDecimal negativeMin = null; - Boolean negativeMinInclusive = null; - BigDecimal negativeMax = null; - boolean negativeMaxInclusive = false; + BigDecimal min = null; + Boolean minInclusive = null; + BigDecimal max = null; + Boolean maxInclusive = null; Integer scale = null; - Optional digits = context.findAnnotation(Digits.class); - if (digits.isPresent()) { - BigDecimal value = BigDecimal.ONE; - int integer = digits.get().integer(); - if (integer > 1) { - value = BigDecimal.TEN.pow(integer - 1); + for (Min minAnn : context.findAnnotations(Min.class)) { + BigDecimal newMin = BigDecimal.valueOf(minAnn.value()); + if (min == null || newMin.compareTo(min) > 0) { + min = newMin; + minInclusive = true; } - positiveMax = value.multiply(BigDecimal.TEN).subtract(BigDecimal.ONE); - positiveMin = value; - negativeMax = positiveMin.negate(); - negativeMin = positiveMax.negate(); - positiveMinInclusive = false; - negativeMinInclusive = false; - scale = digits.get().fraction(); } - Optional minAnnotation = context.findAnnotation(Min.class); - if (minAnnotation.isPresent()) { - BigDecimal minValue = minAnnotation.map(Min::value).map(BigDecimal::valueOf).get(); - if (minValue.compareTo(BigDecimal.ZERO) >= 0) { - if (positiveMin == null) { - positiveMin = minValue; - } else { - positiveMin = positiveMin.min(minValue); - } - negativeMax = null; - negativeMin = null; - } else { - if (negativeMin == null) { - negativeMin = minValue; - } else { - negativeMin = negativeMin.min(minValue); - } - negativeMinInclusive = true; + for (DecimalMin decimalMin : context.findAnnotations(DecimalMin.class)) { + BigDecimal newMin = new BigDecimal(decimalMin.value()); + if (min == null || newMin.compareTo(min) > 0 || + (newMin.compareTo(min) == 0 && !decimalMin.inclusive() && minInclusive)) { + min = newMin; + minInclusive = decimalMin.inclusive(); } } - Optional decimalMinAnnotation = context.findAnnotation(DecimalMin.class); - if (decimalMinAnnotation.isPresent()) { - BigDecimal decimalMin = new BigDecimal( - decimalMinAnnotation - .get() - .value() - ); - - if (decimalMin.compareTo(BigDecimal.ZERO) >= 0) { - if (positiveMin == null) { - positiveMin = decimalMin; - } else { - positiveMin = positiveMin.min(decimalMin); - } - if (!decimalMinAnnotation.map(DecimalMin::inclusive).get()) { - positiveMinInclusive = false; - } - negativeMax = null; - negativeMin = null; - } else { - if (negativeMin == null) { - negativeMin = decimalMin; - } else { - negativeMin = negativeMin.min(negativeMin); - } - if (!decimalMinAnnotation.map(DecimalMin::inclusive).get()) { - negativeMinInclusive = false; - } + for (Max maxAnn : context.findAnnotations(Max.class)) { + BigDecimal newMax = BigDecimal.valueOf(maxAnn.value()); + if (max == null || newMax.compareTo(max) < 0) { + max = newMax; + maxInclusive = true; } } - Optional maxAnnotation = context.findAnnotation(Max.class); - if (maxAnnotation.isPresent()) { - BigDecimal maxValue = maxAnnotation.map(Max::value).map(BigDecimal::valueOf).get(); - if (maxValue.compareTo(BigDecimal.ZERO) > 0) { - if (positiveMax == null) { - positiveMax = maxValue; - } else { - positiveMax = positiveMax.max(maxValue); - } - } else { - if (negativeMax == null) { - negativeMax = maxValue; - } else { - negativeMax = negativeMax.max(maxValue); - } + for (DecimalMax decimalMax : context.findAnnotations(DecimalMax.class)) { + BigDecimal newMax = new BigDecimal(decimalMax.value()); + if (max == null || newMax.compareTo(max) < 0 || + (newMax.compareTo(max) == 0 && !decimalMax.inclusive() && maxInclusive)) { + max = newMax; + maxInclusive = decimalMax.inclusive(); } } - Optional decimalMaxAnnotation = context.findAnnotation(DecimalMax.class); - if (decimalMaxAnnotation.isPresent()) { - BigDecimal decimalMax = new BigDecimal( - decimalMaxAnnotation - .get() - .value() - ); - - if (decimalMax.compareTo(BigDecimal.ZERO) > 0) { - if (positiveMax == null) { - positiveMax = decimalMax; - } else { - positiveMax = positiveMax.max(decimalMax); - } - positiveMaxInclusive = decimalMaxAnnotation.map(DecimalMax::inclusive).get(); - } else { - if (negativeMax == null) { - negativeMax = decimalMax; - } else { - negativeMax = negativeMax.max(decimalMax); - } - negativeMaxInclusive = decimalMaxAnnotation.map(DecimalMax::inclusive).get(); - } - - if (!decimalMaxAnnotation.map(DecimalMax::inclusive).get()) { - positiveMaxInclusive = false; + if (context.findAnnotation(Positive.class).isPresent()) { + if (min == null || BigDecimal.ZERO.compareTo(min) > 0 || + (BigDecimal.ZERO.compareTo(min) == 0 && minInclusive)) { + min = BigDecimal.ZERO; + minInclusive = false; } + } - if (positiveMax == null) { - positiveMax = decimalMax; - } else if (positiveMax.compareTo(decimalMax) > 0) { - positiveMax = decimalMax; + if (context.findAnnotation(PositiveOrZero.class).isPresent()) { + if (min == null || BigDecimal.ZERO.compareTo(min) > 0) { + min = BigDecimal.ZERO; + minInclusive = true; } } if (context.findAnnotation(Negative.class).isPresent()) { - if (negativeMax == null || negativeMax.compareTo(BigDecimal.ZERO) > 0) { - negativeMax = BigDecimal.ZERO; - negativeMaxInclusive = false; + if (max == null || BigDecimal.ZERO.compareTo(max) < 0 || + (BigDecimal.ZERO.compareTo(max) == 0 && maxInclusive)) { + max = BigDecimal.ZERO; + maxInclusive = false; } } if (context.findAnnotation(NegativeOrZero.class).isPresent()) { - if (negativeMax == null || negativeMax.compareTo(BigDecimal.ZERO) > 0) { - negativeMax = BigDecimal.ZERO; - negativeMaxInclusive = true; + if (max == null || BigDecimal.ZERO.compareTo(max) < 0) { + max = BigDecimal.ZERO; + maxInclusive = true; } } - if (context.findAnnotation(Positive.class).isPresent()) { - if (positiveMin == null || positiveMin.compareTo(BigDecimal.ZERO) < 0) { - positiveMin = BigDecimal.ZERO; - positiveMinInclusive = false; + Optional digitsAnn = context.findAnnotation(Digits.class); + if (digitsAnn.isPresent()) { + Digits digits = digitsAnn.get(); + int integerDigits = digits.integer(); + int fractionDigits = digits.fraction(); + + StringBuilder maxBuilder = new StringBuilder(); + for (int i = 0; i < integerDigits; i++) { + maxBuilder.append('9'); } - } + if (fractionDigits > 0) { + maxBuilder.append('.'); + for (int i = 0; i < fractionDigits; i++) { + maxBuilder.append('9'); + } + } + BigDecimal digitsMax = new BigDecimal(maxBuilder.toString()); + BigDecimal digitsMin = digitsMax.negate(); - if (context.findAnnotation(PositiveOrZero.class).isPresent()) { - if (positiveMin == null || positiveMin.compareTo(BigDecimal.ZERO) < 0) { - positiveMin = BigDecimal.ZERO; - positiveMinInclusive = true; + if (max == null || digitsMax.compareTo(max) < 0) { + max = digitsMax; + maxInclusive = true; + } + if (min == null || digitsMin.compareTo(min) > 0) { + min = digitsMin; + minInclusive = true; } + + scale = digits.fraction(); } - if (positiveMin == null && positiveMax == null && negativeMin == null && negativeMax == null && scale == null) { + if (min == null && max == null) { return null; } + boolean isPositiveMin = min != null && min.compareTo(BigDecimal.ZERO) >= 0; + boolean isPositiveMax = max != null && max.compareTo(BigDecimal.ZERO) >= 0; + boolean isNegativeMin = min != null && min.compareTo(BigDecimal.ZERO) < 0; + boolean isNegativeMax = max != null && max.compareTo(BigDecimal.ZERO) < 0; + return new JavaDecimalConstraint( - positiveMin, - positiveMinInclusive, - positiveMax, - positiveMaxInclusive, - negativeMin, - negativeMinInclusive, - negativeMax, - negativeMaxInclusive, + isPositiveMin ? min : null, + isPositiveMin ? minInclusive : null, + isPositiveMax ? max : null, + isPositiveMax ? maxInclusive : null, + + isNegativeMin ? min : null, + isNegativeMin ? minInclusive : null, + isNegativeMax ? max : null, + isNegativeMax ? maxInclusive : null, scale ); } diff --git a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java index c5697c96a..1a0e26552 100644 --- a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java +++ b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java @@ -18,9 +18,7 @@ package com.navercorp.fixturemonkey.jakarta.validation; -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenNoException; -import static org.assertj.core.api.BDDAssertions.thenThrownBy; +import static org.assertj.core.api.BDDAssertions.*; import java.math.BigDecimal; import java.math.BigInteger; @@ -81,6 +79,8 @@ void sampleBigDecimal() { then(actual.getNegativeOrZero()).isLessThanOrEqualTo(BigDecimal.ZERO); then(actual.getPositive()).isPositive(); then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(BigDecimal.ZERO); + then(actual.getDecimalEqual()).isEqualByComparingTo(BigDecimal.valueOf(100.1)); + then(actual.getIntegerEqual()).isEqualByComparingTo(BigDecimal.valueOf(100)); } @Property(tries = 100) diff --git a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/spec/BigDecimalIntrospectorSpec.java b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/spec/BigDecimalIntrospectorSpec.java index 496be13fc..3827edfc3 100644 --- a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/spec/BigDecimalIntrospectorSpec.java +++ b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/spec/BigDecimalIntrospectorSpec.java @@ -51,4 +51,12 @@ public class BigDecimalIntrospectorSpec { @PositiveOrZero private BigDecimal positiveOrZero; + + @DecimalMin(value = "100.1") + @DecimalMax(value = "100.1") + private BigDecimal decimalEqual; + + @Max(value = 100) + @Min(value = 100) + private BigDecimal integerEqual; } diff --git a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java index 289267ad7..cfd5c4284 100644 --- a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java +++ b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java @@ -291,178 +291,126 @@ public JavaIntegerConstraint generateIntegerConstraint(ArbitraryGeneratorContext @Override @Nullable public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext context) { - BigDecimal positiveMin = null; - Boolean positiveMinInclusive = null; - BigDecimal positiveMax = null; - Boolean positiveMaxInclusive = null; - BigDecimal negativeMin = null; - Boolean negativeMinInclusive = null; - BigDecimal negativeMax = null; - boolean negativeMaxInclusive = false; + BigDecimal min = null; + Boolean minInclusive = null; + BigDecimal max = null; + Boolean maxInclusive = null; Integer scale = null; - Optional digits = context.findAnnotation(Digits.class); - if (digits.isPresent()) { - BigDecimal value = BigDecimal.ONE; - int integer = digits.get().integer(); - if (integer > 1) { - value = BigDecimal.TEN.pow(integer - 1); + for (Min minAnn : context.findAnnotations(Min.class)) { + BigDecimal newMin = BigDecimal.valueOf(minAnn.value()); + if (min == null || newMin.compareTo(min) > 0) { + min = newMin; + minInclusive = true; } - positiveMax = value.multiply(BigDecimal.TEN).subtract(BigDecimal.ONE); - positiveMin = value; - negativeMax = positiveMin.negate(); - negativeMin = positiveMax.negate(); - positiveMinInclusive = false; - negativeMinInclusive = false; - scale = digits.get().fraction(); } - Optional minAnnotation = context.findAnnotation(Min.class); - if (minAnnotation.isPresent()) { - BigDecimal minValue = minAnnotation.map(Min::value).map(BigDecimal::valueOf).get(); - if (minValue.compareTo(BigDecimal.ZERO) >= 0) { - if (positiveMin == null) { - positiveMin = minValue; - } else { - positiveMin = positiveMin.min(minValue); - } - negativeMax = null; - negativeMin = null; - } else { - if (negativeMin == null) { - negativeMin = minValue; - } else { - negativeMin = negativeMin.min(minValue); - } - negativeMinInclusive = true; + for (DecimalMin decimalMin : context.findAnnotations(DecimalMin.class)) { + BigDecimal newMin = new BigDecimal(decimalMin.value()); + if (min == null || newMin.compareTo(min) > 0 || + (newMin.compareTo(min) == 0 && !decimalMin.inclusive() && minInclusive)) { + min = newMin; + minInclusive = decimalMin.inclusive(); } } - Optional decimalMinAnnotation = context.findAnnotation(DecimalMin.class); - if (decimalMinAnnotation.isPresent()) { - BigDecimal decimalMin = new BigDecimal( - decimalMinAnnotation - .get() - .value() - ); - - if (decimalMin.compareTo(BigDecimal.ZERO) >= 0) { - if (positiveMin == null) { - positiveMin = decimalMin; - } else { - positiveMin = positiveMin.min(decimalMin); - } - if (!decimalMinAnnotation.map(DecimalMin::inclusive).get()) { - positiveMinInclusive = false; - } - negativeMax = null; - negativeMin = null; - } else { - if (negativeMin == null) { - negativeMin = decimalMin; - } else { - negativeMin = negativeMin.min(negativeMin); - } - if (!decimalMinAnnotation.map(DecimalMin::inclusive).get()) { - negativeMinInclusive = false; - } + for (Max maxAnn : context.findAnnotations(Max.class)) { + BigDecimal newMax = BigDecimal.valueOf(maxAnn.value()); + if (max == null || newMax.compareTo(max) < 0) { + max = newMax; + maxInclusive = true; } } - Optional maxAnnotation = context.findAnnotation(Max.class); - if (maxAnnotation.isPresent()) { - BigDecimal maxValue = maxAnnotation.map(Max::value).map(BigDecimal::valueOf).get(); - if (maxValue.compareTo(BigDecimal.ZERO) > 0) { - if (positiveMax == null) { - positiveMax = maxValue; - } else { - positiveMax = positiveMax.max(maxValue); - } - } else { - if (negativeMax == null) { - negativeMax = maxValue; - } else { - negativeMax = negativeMax.max(maxValue); - } + for (DecimalMax decimalMax : context.findAnnotations(DecimalMax.class)) { + BigDecimal newMax = new BigDecimal(decimalMax.value()); + if (max == null || newMax.compareTo(max) < 0 || + (newMax.compareTo(max) == 0 && !decimalMax.inclusive() && maxInclusive)) { + max = newMax; + maxInclusive = decimalMax.inclusive(); } } - Optional decimalMaxAnnotation = context.findAnnotation(DecimalMax.class); - if (decimalMaxAnnotation.isPresent()) { - BigDecimal decimalMax = new BigDecimal( - decimalMaxAnnotation - .get() - .value() - ); - - if (decimalMax.compareTo(BigDecimal.ZERO) > 0) { - if (positiveMax == null) { - positiveMax = decimalMax; - } else { - positiveMax = positiveMax.max(decimalMax); - } - positiveMaxInclusive = decimalMaxAnnotation.map(DecimalMax::inclusive).get(); - } else { - if (negativeMax == null) { - negativeMax = decimalMax; - } else { - negativeMax = negativeMax.max(decimalMax); - } - negativeMaxInclusive = decimalMaxAnnotation.map(DecimalMax::inclusive).get(); - } - - if (!decimalMaxAnnotation.map(DecimalMax::inclusive).get()) { - positiveMaxInclusive = false; + if (context.findAnnotation(Positive.class).isPresent()) { + if (min == null || BigDecimal.ZERO.compareTo(min) > 0 || + (BigDecimal.ZERO.compareTo(min) == 0 && minInclusive)) { + min = BigDecimal.ZERO; + minInclusive = false; } + } - if (positiveMax == null) { - positiveMax = decimalMax; - } else if (positiveMax.compareTo(decimalMax) > 0) { - positiveMax = decimalMax; + if (context.findAnnotation(PositiveOrZero.class).isPresent()) { + if (min == null || BigDecimal.ZERO.compareTo(min) > 0) { + min = BigDecimal.ZERO; + minInclusive = true; } } if (context.findAnnotation(Negative.class).isPresent()) { - if (negativeMax == null || negativeMax.compareTo(BigDecimal.ZERO) > 0) { - negativeMax = BigDecimal.ZERO; - negativeMaxInclusive = false; + if (max == null || BigDecimal.ZERO.compareTo(max) < 0 || + (BigDecimal.ZERO.compareTo(max) == 0 && maxInclusive)) { + max = BigDecimal.ZERO; + maxInclusive = false; } } if (context.findAnnotation(NegativeOrZero.class).isPresent()) { - if (negativeMax == null || negativeMax.compareTo(BigDecimal.ZERO) > 0) { - negativeMax = BigDecimal.ZERO; - negativeMaxInclusive = true; + if (max == null || BigDecimal.ZERO.compareTo(max) < 0) { + max = BigDecimal.ZERO; + maxInclusive = true; } } - if (context.findAnnotation(Positive.class).isPresent()) { - if (positiveMin == null || positiveMin.compareTo(BigDecimal.ZERO) < 0) { - positiveMin = BigDecimal.ZERO; - positiveMinInclusive = false; + Optional digitsAnn = context.findAnnotation(Digits.class); + if (digitsAnn.isPresent()) { + Digits digits = digitsAnn.get(); + int integerDigits = digits.integer(); + int fractionDigits = digits.fraction(); + + StringBuilder maxBuilder = new StringBuilder(); + for (int i = 0; i < integerDigits; i++) { + maxBuilder.append('9'); } - } + if (fractionDigits > 0) { + maxBuilder.append('.'); + for (int i = 0; i < fractionDigits; i++) { + maxBuilder.append('9'); + } + } + BigDecimal digitsMax = new BigDecimal(maxBuilder.toString()); + BigDecimal digitsMin = digitsMax.negate(); - if (context.findAnnotation(PositiveOrZero.class).isPresent()) { - if (positiveMin == null || positiveMin.compareTo(BigDecimal.ZERO) < 0) { - positiveMin = BigDecimal.ZERO; - positiveMinInclusive = true; + if (max == null || digitsMax.compareTo(max) < 0) { + max = digitsMax; + maxInclusive = true; + } + if (min == null || digitsMin.compareTo(min) > 0) { + min = digitsMin; + minInclusive = true; } + + scale = digits.fraction(); } - if (positiveMin == null && positiveMax == null && negativeMin == null && negativeMax == null && scale == null) { + if (min == null && max == null) { return null; } + boolean isPositiveMin = min != null && min.compareTo(BigDecimal.ZERO) >= 0; + boolean isPositiveMax = max != null && max.compareTo(BigDecimal.ZERO) >= 0; + boolean isNegativeMin = min != null && min.compareTo(BigDecimal.ZERO) < 0; + boolean isNegativeMax = max != null && max.compareTo(BigDecimal.ZERO) < 0; + return new JavaDecimalConstraint( - positiveMin, - positiveMinInclusive, - positiveMax, - positiveMaxInclusive, - negativeMin, - negativeMinInclusive, - negativeMax, - negativeMaxInclusive, + isPositiveMin ? min : null, + isPositiveMin ? minInclusive : null, + isPositiveMax ? max : null, + isPositiveMax ? maxInclusive : null, + + isNegativeMin ? min : null, + isNegativeMin ? minInclusive : null, + isNegativeMax ? max : null, + isNegativeMax ? maxInclusive : null, scale ); } diff --git a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java index 8e3cb7124..028ccd32f 100644 --- a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java +++ b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java @@ -18,9 +18,7 @@ package com.navercorp.fixturemonkey.javax.validation; -import static org.assertj.core.api.BDDAssertions.then; -import static org.assertj.core.api.BDDAssertions.thenNoException; -import static org.assertj.core.api.BDDAssertions.thenThrownBy; +import static org.assertj.core.api.BDDAssertions.*; import java.math.BigDecimal; import java.math.BigInteger; @@ -81,6 +79,8 @@ void sampleBigDecimal() { then(actual.getNegativeOrZero()).isLessThanOrEqualTo(BigDecimal.ZERO); then(actual.getPositive()).isPositive(); then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(BigDecimal.ZERO); + then(actual.getDecimalEqual()).isEqualByComparingTo(BigDecimal.valueOf(100.1)); + then(actual.getIntegerEqual()).isEqualByComparingTo(BigDecimal.valueOf(100)); } @Property(tries = 100) diff --git a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/spec/BigDecimalIntrospectorSpec.java b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/spec/BigDecimalIntrospectorSpec.java index aeefc7d06..bc714cade 100644 --- a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/spec/BigDecimalIntrospectorSpec.java +++ b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/spec/BigDecimalIntrospectorSpec.java @@ -52,4 +52,12 @@ public class BigDecimalIntrospectorSpec { @PositiveOrZero private BigDecimal positiveOrZero; + + @DecimalMax(value = "100.1") + @DecimalMin(value = "100.1") + private BigDecimal decimalEqual; + + @Max(value = 100) + @Min(value = 100) + private BigDecimal integerEqual; } From 9598de3a50f71453b3eb3459c43cb2c63b042fa8 Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Mon, 23 Dec 2024 15:52:23 +0900 Subject: [PATCH 03/13] Fix operator line wrapping in validation constraint generators --- .../JakartaValidationConstraintGenerator.java | 16 ++++++++-------- .../JavaxValidationConstraintGenerator.java | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java index d46ad91b2..df8589ec7 100644 --- a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java +++ b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java @@ -308,8 +308,8 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext for (DecimalMin decimalMin : context.findAnnotations(DecimalMin.class)) { BigDecimal newMin = new BigDecimal(decimalMin.value()); - if (min == null || newMin.compareTo(min) > 0 || - (newMin.compareTo(min) == 0 && !decimalMin.inclusive() && minInclusive)) { + if (min == null || newMin.compareTo(min) > 0 + || (newMin.compareTo(min) == 0 && !decimalMin.inclusive() && minInclusive)) { min = newMin; minInclusive = decimalMin.inclusive(); } @@ -325,16 +325,16 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext for (DecimalMax decimalMax : context.findAnnotations(DecimalMax.class)) { BigDecimal newMax = new BigDecimal(decimalMax.value()); - if (max == null || newMax.compareTo(max) < 0 || - (newMax.compareTo(max) == 0 && !decimalMax.inclusive() && maxInclusive)) { + if (max == null || newMax.compareTo(max) < 0 + || (newMax.compareTo(max) == 0 && !decimalMax.inclusive() && maxInclusive)) { max = newMax; maxInclusive = decimalMax.inclusive(); } } if (context.findAnnotation(Positive.class).isPresent()) { - if (min == null || BigDecimal.ZERO.compareTo(min) > 0 || - (BigDecimal.ZERO.compareTo(min) == 0 && minInclusive)) { + if (min == null || BigDecimal.ZERO.compareTo(min) > 0 + || (BigDecimal.ZERO.compareTo(min) == 0 && minInclusive)) { min = BigDecimal.ZERO; minInclusive = false; } @@ -348,8 +348,8 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext } if (context.findAnnotation(Negative.class).isPresent()) { - if (max == null || BigDecimal.ZERO.compareTo(max) < 0 || - (BigDecimal.ZERO.compareTo(max) == 0 && maxInclusive)) { + if (max == null || BigDecimal.ZERO.compareTo(max) < 0 + || (BigDecimal.ZERO.compareTo(max) == 0 && maxInclusive)) { max = BigDecimal.ZERO; maxInclusive = false; } diff --git a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java index cfd5c4284..972774b3e 100644 --- a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java +++ b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java @@ -307,8 +307,8 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext for (DecimalMin decimalMin : context.findAnnotations(DecimalMin.class)) { BigDecimal newMin = new BigDecimal(decimalMin.value()); - if (min == null || newMin.compareTo(min) > 0 || - (newMin.compareTo(min) == 0 && !decimalMin.inclusive() && minInclusive)) { + if (min == null || newMin.compareTo(min) > 0 + || (newMin.compareTo(min) == 0 && !decimalMin.inclusive() && minInclusive)) { min = newMin; minInclusive = decimalMin.inclusive(); } @@ -324,16 +324,16 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext for (DecimalMax decimalMax : context.findAnnotations(DecimalMax.class)) { BigDecimal newMax = new BigDecimal(decimalMax.value()); - if (max == null || newMax.compareTo(max) < 0 || - (newMax.compareTo(max) == 0 && !decimalMax.inclusive() && maxInclusive)) { + if (max == null || newMax.compareTo(max) < 0 + || (newMax.compareTo(max) == 0 && !decimalMax.inclusive() && maxInclusive)) { max = newMax; maxInclusive = decimalMax.inclusive(); } } if (context.findAnnotation(Positive.class).isPresent()) { - if (min == null || BigDecimal.ZERO.compareTo(min) > 0 || - (BigDecimal.ZERO.compareTo(min) == 0 && minInclusive)) { + if (min == null || BigDecimal.ZERO.compareTo(min) > 0 + || (BigDecimal.ZERO.compareTo(min) == 0 && minInclusive)) { min = BigDecimal.ZERO; minInclusive = false; } @@ -347,8 +347,8 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext } if (context.findAnnotation(Negative.class).isPresent()) { - if (max == null || BigDecimal.ZERO.compareTo(max) < 0 || - (BigDecimal.ZERO.compareTo(max) == 0 && maxInclusive)) { + if (max == null || BigDecimal.ZERO.compareTo(max) < 0 + || (BigDecimal.ZERO.compareTo(max) == 0 && maxInclusive)) { max = BigDecimal.ZERO; maxInclusive = false; } From 952364b4fa839b2f4f1814e4f16f8345566ec775 Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Mon, 23 Dec 2024 16:05:51 +0900 Subject: [PATCH 04/13] Fix wildcard import in ArbitraryGeneratorContext --- .../fixturemonkey/api/generator/ArbitraryGeneratorContext.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java index df7781a9e..577baf228 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java @@ -18,7 +18,8 @@ package com.navercorp.fixturemonkey.api.generator; -import static java.util.stream.Collectors.*; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; import java.lang.annotation.Annotation; import java.lang.annotation.Repeatable; From eb987a5612c3d7564e59c36d27abb3403e495e3e Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Mon, 23 Dec 2024 16:11:31 +0900 Subject: [PATCH 05/13] Fix wildcard import in ValidationFixtureMonkeyTest --- .../validation/JakartaValidationFixtureMonkeyTest.java | 4 +++- .../javax/validation/JavaxValidationFixtureMonkeyTest.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java index 1a0e26552..865f680d4 100644 --- a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java +++ b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java @@ -18,7 +18,9 @@ package com.navercorp.fixturemonkey.jakarta.validation; -import static org.assertj.core.api.BDDAssertions.*; +import static org.assertj.core.api.BDDAssertions.then; +import static org.assertj.core.api.BDDAssertions.thenNoException; +import static org.assertj.core.api.BDDAssertions.thenThrownBy; import java.math.BigDecimal; import java.math.BigInteger; diff --git a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java index 028ccd32f..93f4fd08c 100644 --- a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java +++ b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java @@ -18,7 +18,9 @@ package com.navercorp.fixturemonkey.javax.validation; -import static org.assertj.core.api.BDDAssertions.*; +import static org.assertj.core.api.BDDAssertions.then; +import static org.assertj.core.api.BDDAssertions.thenNoException; +import static org.assertj.core.api.BDDAssertions.thenThrownBy; import java.math.BigDecimal; import java.math.BigInteger; From 68b8ccfec5b9899fb1e98bbc97312522e7b41a50 Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Mon, 20 Jan 2025 23:27:01 +0900 Subject: [PATCH 06/13] Remove unnecessary tests --- .../validation/JakartaValidationFixtureMonkeyTest.java | 2 -- .../validation/spec/BigDecimalIntrospectorSpec.java | 8 -------- .../validation/JavaxValidationFixtureMonkeyTest.java | 2 -- .../javax/validation/spec/BigDecimalIntrospectorSpec.java | 8 -------- 4 files changed, 20 deletions(-) diff --git a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java index 865f680d4..c5697c96a 100644 --- a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java +++ b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/JakartaValidationFixtureMonkeyTest.java @@ -81,8 +81,6 @@ void sampleBigDecimal() { then(actual.getNegativeOrZero()).isLessThanOrEqualTo(BigDecimal.ZERO); then(actual.getPositive()).isPositive(); then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(BigDecimal.ZERO); - then(actual.getDecimalEqual()).isEqualByComparingTo(BigDecimal.valueOf(100.1)); - then(actual.getIntegerEqual()).isEqualByComparingTo(BigDecimal.valueOf(100)); } @Property(tries = 100) diff --git a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/spec/BigDecimalIntrospectorSpec.java b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/spec/BigDecimalIntrospectorSpec.java index 3827edfc3..496be13fc 100644 --- a/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/spec/BigDecimalIntrospectorSpec.java +++ b/fixture-monkey-jakarta-validation/src/test/java/com/navercorp/fixturemonkey/jakarta/validation/spec/BigDecimalIntrospectorSpec.java @@ -51,12 +51,4 @@ public class BigDecimalIntrospectorSpec { @PositiveOrZero private BigDecimal positiveOrZero; - - @DecimalMin(value = "100.1") - @DecimalMax(value = "100.1") - private BigDecimal decimalEqual; - - @Max(value = 100) - @Min(value = 100) - private BigDecimal integerEqual; } diff --git a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java index 93f4fd08c..8e3cb7124 100644 --- a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java +++ b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/JavaxValidationFixtureMonkeyTest.java @@ -81,8 +81,6 @@ void sampleBigDecimal() { then(actual.getNegativeOrZero()).isLessThanOrEqualTo(BigDecimal.ZERO); then(actual.getPositive()).isPositive(); then(actual.getPositiveOrZero()).isGreaterThanOrEqualTo(BigDecimal.ZERO); - then(actual.getDecimalEqual()).isEqualByComparingTo(BigDecimal.valueOf(100.1)); - then(actual.getIntegerEqual()).isEqualByComparingTo(BigDecimal.valueOf(100)); } @Property(tries = 100) diff --git a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/spec/BigDecimalIntrospectorSpec.java b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/spec/BigDecimalIntrospectorSpec.java index bc714cade..aeefc7d06 100644 --- a/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/spec/BigDecimalIntrospectorSpec.java +++ b/fixture-monkey-javax-validation/src/test/java/com/navercorp/fixturemonkey/javax/validation/spec/BigDecimalIntrospectorSpec.java @@ -52,12 +52,4 @@ public class BigDecimalIntrospectorSpec { @PositiveOrZero private BigDecimal positiveOrZero; - - @DecimalMax(value = "100.1") - @DecimalMin(value = "100.1") - private BigDecimal decimalEqual; - - @Max(value = 100) - @Min(value = 100) - private BigDecimal integerEqual; } From 33be8044ea8a7b0cceb3f9058822320380dabe67 Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Mon, 20 Jan 2025 23:44:25 +0900 Subject: [PATCH 07/13] Remove findAnnotations --- .../generator/ArbitraryGeneratorContext.java | 24 ----------- .../JakartaValidationConstraintGenerator.java | 42 ++++++++++--------- .../JavaxValidationConstraintGenerator.java | 42 ++++++++++--------- 3 files changed, 44 insertions(+), 64 deletions(-) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java index 577baf228..bdb84fb85 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java @@ -111,30 +111,6 @@ public Optional findAnnotation(Class annotationClas return this.getResolvedProperty().getAnnotation(annotationClass); } - public List findAnnotations(Class annotationClass) { - List results = this.getResolvedProperty().getAnnotations().stream() - .filter(it -> annotationClass.isAssignableFrom(it.annotationType())) - .map(annotationClass::cast).collect(toList()); - - Repeatable repeatable = annotationClass.getAnnotation(Repeatable.class); - if (repeatable != null) { - Class containerClass = repeatable.value(); - this.getResolvedProperty().getAnnotations().stream() - .filter(it -> containerClass.isAssignableFrom(it.annotationType())) - .findFirst() - .ifPresent(container -> { - try { - Method valueMethod = container.annotationType().getDeclaredMethod("value"); - T[] values = (T[])valueMethod.invoke(container); - results.addAll(Arrays.asList(values)); - } catch (Exception ignored) { - } - }); - } - - return results; - } - public List getChildren() { return Collections.unmodifiableList(this.children); } diff --git a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java index df8589ec7..a17086f03 100644 --- a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java +++ b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java @@ -298,37 +298,39 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext Boolean maxInclusive = null; Integer scale = null; - for (Min minAnn : context.findAnnotations(Min.class)) { - BigDecimal newMin = BigDecimal.valueOf(minAnn.value()); - if (min == null || newMin.compareTo(min) > 0) { - min = newMin; - minInclusive = true; - } + Optional minAnnotation = context.findAnnotation(Min.class); + if (minAnnotation.isPresent()) { + min = BigDecimal.valueOf(minAnnotation.get().value()); + minInclusive = true; } - for (DecimalMin decimalMin : context.findAnnotations(DecimalMin.class)) { - BigDecimal newMin = new BigDecimal(decimalMin.value()); + Optional decimalMinAnnotation = context.findAnnotation(DecimalMin.class); + if (decimalMinAnnotation.isPresent()) { + BigDecimal newMin = new BigDecimal(decimalMinAnnotation.get().value()); + if (min == null || newMin.compareTo(min) > 0 - || (newMin.compareTo(min) == 0 && !decimalMin.inclusive() && minInclusive)) { + || (newMin.compareTo(min) == 0 && !decimalMinAnnotation.get().inclusive())) { + min = newMin; - minInclusive = decimalMin.inclusive(); + minInclusive = decimalMinAnnotation.get().inclusive(); } } - for (Max maxAnn : context.findAnnotations(Max.class)) { - BigDecimal newMax = BigDecimal.valueOf(maxAnn.value()); - if (max == null || newMax.compareTo(max) < 0) { - max = newMax; - maxInclusive = true; - } + Optional maxAnnotation = context.findAnnotation(Max.class); + if (maxAnnotation.isPresent()) { + max = BigDecimal.valueOf(maxAnnotation.get().value()); + maxInclusive = true; } - for (DecimalMax decimalMax : context.findAnnotations(DecimalMax.class)) { - BigDecimal newMax = new BigDecimal(decimalMax.value()); + Optional decimalMaxAnnotation = context.findAnnotation(DecimalMax.class); + if (decimalMaxAnnotation.isPresent()) { + BigDecimal newMax = new BigDecimal(decimalMaxAnnotation.get().value()); + if (max == null || newMax.compareTo(max) < 0 - || (newMax.compareTo(max) == 0 && !decimalMax.inclusive() && maxInclusive)) { + || (newMax.compareTo(max) == 0 && !decimalMaxAnnotation.get().inclusive())) { + max = newMax; - maxInclusive = decimalMax.inclusive(); + maxInclusive = decimalMaxAnnotation.get().inclusive(); } } diff --git a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java index 972774b3e..c14a867bc 100644 --- a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java +++ b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java @@ -297,37 +297,39 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext Boolean maxInclusive = null; Integer scale = null; - for (Min minAnn : context.findAnnotations(Min.class)) { - BigDecimal newMin = BigDecimal.valueOf(minAnn.value()); - if (min == null || newMin.compareTo(min) > 0) { - min = newMin; - minInclusive = true; - } + Optional minAnnotation = context.findAnnotation(Min.class); + if (minAnnotation.isPresent()) { + min = BigDecimal.valueOf(minAnnotation.get().value()); + minInclusive = true; } - for (DecimalMin decimalMin : context.findAnnotations(DecimalMin.class)) { - BigDecimal newMin = new BigDecimal(decimalMin.value()); + Optional decimalMinAnnotation = context.findAnnotation(DecimalMin.class); + if (decimalMinAnnotation.isPresent()) { + BigDecimal newMin = new BigDecimal(decimalMinAnnotation.get().value()); + if (min == null || newMin.compareTo(min) > 0 - || (newMin.compareTo(min) == 0 && !decimalMin.inclusive() && minInclusive)) { + || (newMin.compareTo(min) == 0 && !decimalMinAnnotation.get().inclusive())) { + min = newMin; - minInclusive = decimalMin.inclusive(); + minInclusive = decimalMinAnnotation.get().inclusive(); } } - for (Max maxAnn : context.findAnnotations(Max.class)) { - BigDecimal newMax = BigDecimal.valueOf(maxAnn.value()); - if (max == null || newMax.compareTo(max) < 0) { - max = newMax; - maxInclusive = true; - } + Optional maxAnnotation = context.findAnnotation(Max.class); + if (maxAnnotation.isPresent()) { + max = BigDecimal.valueOf(maxAnnotation.get().value()); + maxInclusive = true; } - for (DecimalMax decimalMax : context.findAnnotations(DecimalMax.class)) { - BigDecimal newMax = new BigDecimal(decimalMax.value()); + Optional decimalMaxAnnotation = context.findAnnotation(DecimalMax.class); + if (decimalMaxAnnotation.isPresent()) { + BigDecimal newMax = new BigDecimal(decimalMaxAnnotation.get().value()); + if (max == null || newMax.compareTo(max) < 0 - || (newMax.compareTo(max) == 0 && !decimalMax.inclusive() && maxInclusive)) { + || (newMax.compareTo(max) == 0 && !decimalMaxAnnotation.get().inclusive())) { + max = newMax; - maxInclusive = decimalMax.inclusive(); + maxInclusive = decimalMaxAnnotation.get().inclusive(); } } From d5d232e31b50a1c5939595583125a12636089086 Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Sun, 26 Jan 2025 03:39:25 +0900 Subject: [PATCH 08/13] fix: fix error related to `@Negative` --- .../JakartaValidationConstraintGenerator.java | 32 +++++++++++++++++-- .../JavaxValidationConstraintGenerator.java | 29 ++++++++++++++++- .../tests/kotlin/KotestInJunitTest.kt | 10 +++--- 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java index a17086f03..35c329567 100644 --- a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java +++ b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java @@ -328,7 +328,7 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext if (max == null || newMax.compareTo(max) < 0 || (newMax.compareTo(max) == 0 && !decimalMaxAnnotation.get().inclusive())) { - + max = newMax; maxInclusive = decimalMaxAnnotation.get().inclusive(); } @@ -404,18 +404,46 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext boolean isNegativeMin = min != null && min.compareTo(BigDecimal.ZERO) < 0; boolean isNegativeMax = max != null && max.compareTo(BigDecimal.ZERO) < 0; + if (isPositiveMax && max.equals(BigDecimal.ZERO)) { + return new JavaDecimalConstraint( + null, + null, + null, + null, + isNegativeMin ? min : null, + isNegativeMin ? minInclusive : null, + BigDecimal.ZERO, + isNegativeMax ? maxInclusive : null, + scale + ); + } + + if (isNegativeMin && isPositiveMax) { + return new JavaDecimalConstraint( + BigDecimal.ZERO, + true, + max, + maxInclusive, + min, + minInclusive, + BigDecimal.ZERO, + false, + scale + ); + } + return new JavaDecimalConstraint( isPositiveMin ? min : null, isPositiveMin ? minInclusive : null, isPositiveMax ? max : null, isPositiveMax ? maxInclusive : null, - isNegativeMin ? min : null, isNegativeMin ? minInclusive : null, isNegativeMax ? max : null, isNegativeMax ? maxInclusive : null, scale ); + } @Override diff --git a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java index c14a867bc..5835a624a 100644 --- a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java +++ b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java @@ -403,12 +403,39 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext boolean isNegativeMin = min != null && min.compareTo(BigDecimal.ZERO) < 0; boolean isNegativeMax = max != null && max.compareTo(BigDecimal.ZERO) < 0; + if (isPositiveMax && max.equals(BigDecimal.ZERO)) { + return new JavaDecimalConstraint( + null, + null, + null, + null, + isNegativeMin ? min : null, + isNegativeMin ? minInclusive : null, + BigDecimal.ZERO, + isNegativeMax ? maxInclusive : null, + scale + ); + } + + if (isNegativeMin && isPositiveMax) { + return new JavaDecimalConstraint( + BigDecimal.ZERO, + true, + max, + maxInclusive, + min, + minInclusive, + BigDecimal.ZERO, + false, + scale + ); + } + return new JavaDecimalConstraint( isPositiveMin ? min : null, isPositiveMin ? minInclusive : null, isPositiveMax ? max : null, isPositiveMax ? maxInclusive : null, - isNegativeMin ? min : null, isNegativeMin ? minInclusive : null, isNegativeMax ? max : null, diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt index 5c3803740..9912471a6 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt @@ -306,7 +306,7 @@ class KotestInJunitTest { val actual = SUT.giveMeOne().value - then(actual).matches { it in 10.0..99.0 || it in -100.0..-10.0 } + then(actual).matches { it in -99.0..99.0 } } @RepeatedTest(TEST_COUNT) @@ -387,7 +387,7 @@ class KotestInJunitTest { val actual = SUT.giveMeOne().value - then(actual).matches { it in 10.0..99.0 || it in -100.0..-10.0 } + then(actual).matches { it in -99.0..99.0 } } @RepeatedTest(TEST_COUNT) @@ -631,8 +631,7 @@ class KotestInJunitTest { val actual = SUT.giveMeOne().value then(actual).matches { - it in BigInteger.valueOf(10L)..BigInteger.valueOf(99L) || - it in BigInteger.valueOf(-99L)..BigInteger.valueOf(-10L) + it in BigInteger.valueOf(-99L)..BigInteger.valueOf(99L) } } @@ -715,8 +714,7 @@ class KotestInJunitTest { val actual = SUT.giveMeOne().value then(actual).matches { - it in BigDecimal.valueOf(10L)..BigDecimal.valueOf(99) || - it in BigDecimal.valueOf(-100)..BigDecimal.valueOf(-10) + it in BigDecimal.valueOf(-99)..BigDecimal.valueOf(99) } } From fabf1234733933a24c3a4869938c11d175023110 Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Sun, 26 Jan 2025 03:46:42 +0900 Subject: [PATCH 09/13] chore: remove unused import --- .../api/generator/ArbitraryGeneratorContext.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java index bdb84fb85..69ae5f7ce 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ArbitraryGeneratorContext.java @@ -18,16 +18,12 @@ package com.navercorp.fixturemonkey.api.generator; -import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import java.lang.annotation.Annotation; -import java.lang.annotation.Repeatable; import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; From 9324aa765372d9d48d2d492f1302bc1b9bfc4dc3 Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Fri, 7 Feb 2025 23:27:55 +0900 Subject: [PATCH 10/13] refactor: simplify decimal constraints and improve Java arbitrary generator handling --- .../api/constraint/JavaDecimalConstraint.java | 80 ++------ .../generator/ValidateArbitraryGenerator.java | 50 +---- .../api/jqwik/JqwikJavaArbitraryResolver.java | 194 ++++++------------ .../api/plugin/SimpleValueJqwikPlugin.java | 6 +- .../JakartaValidationConstraintGenerator.java | 46 +---- .../JavaxValidationConstraintGenerator.java | 45 +--- .../kotest/KotestArbitraryGeneratorSet.kt | 170 ++++----------- .../tests/kotlin/KotestInJunitTest.kt | 111 ++++++++++ 8 files changed, 249 insertions(+), 453 deletions(-) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/constraint/JavaDecimalConstraint.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/constraint/JavaDecimalConstraint.java index 5a816ceac..c41152eea 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/constraint/JavaDecimalConstraint.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/constraint/JavaDecimalConstraint.java @@ -28,92 +28,52 @@ @API(since = "0.6.8", status = Status.MAINTAINED) public final class JavaDecimalConstraint { @Nullable - private final BigDecimal positiveMin; + private final BigDecimal min; @Nullable - private final Boolean positiveMinInclusive; + private final Boolean minInclusive; @Nullable - private final BigDecimal positiveMax; + private final BigDecimal max; @Nullable - private final Boolean positiveMaxInclusive; - - @Nullable - private final BigDecimal negativeMin; - - @Nullable - private final Boolean negativeMinInclusive; - - @Nullable - private final BigDecimal negativeMax; - - @Nullable - private final Boolean negativeMaxInclusive; + private final Boolean maxInclusive; @Nullable private final Integer scale; public JavaDecimalConstraint( - @Nullable BigDecimal positiveMin, - @Nullable Boolean positiveMinInclusive, - @Nullable BigDecimal positiveMax, - @Nullable Boolean positiveMaxInclusive, - @Nullable BigDecimal negativeMin, - @Nullable Boolean negativeMinInclusive, - @Nullable BigDecimal negativeMax, - @Nullable Boolean negativeMaxInclusive, + @Nullable BigDecimal min, + @Nullable Boolean minInclusive, + @Nullable BigDecimal max, + @Nullable Boolean maxInclusive, @Nullable Integer scale ) { - this.positiveMin = positiveMin; - this.positiveMinInclusive = positiveMinInclusive; - this.positiveMax = positiveMax; - this.positiveMaxInclusive = positiveMaxInclusive; - this.negativeMin = negativeMin; - this.negativeMinInclusive = negativeMinInclusive; - this.negativeMax = negativeMax; - this.negativeMaxInclusive = negativeMaxInclusive; + this.min = min; + this.minInclusive = minInclusive; + this.max = max; + this.maxInclusive = maxInclusive; this.scale = scale; } @Nullable - public BigDecimal getPositiveMin() { - return positiveMin; - } - - @Nullable - public Boolean getPositiveMinInclusive() { - return positiveMinInclusive; - } - - @Nullable - public BigDecimal getPositiveMax() { - return positiveMax; - } - - @Nullable - public Boolean getPositiveMaxInclusive() { - return positiveMaxInclusive; - } - - @Nullable - public BigDecimal getNegativeMin() { - return negativeMin; + public BigDecimal getMin() { + return min; } @Nullable - public Boolean getNegativeMinInclusive() { - return negativeMinInclusive; + public Boolean getMinInclusive() { + return minInclusive; } @Nullable - public BigDecimal getNegativeMax() { - return negativeMax; + public BigDecimal getMax() { + return max; } @Nullable - public Boolean getNegativeMaxInclusive() { - return negativeMaxInclusive; + public Boolean getMaxInclusive() { + return maxInclusive; } @Nullable diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ValidateArbitraryGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ValidateArbitraryGenerator.java index 536ba72b2..afb667ee1 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ValidateArbitraryGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/generator/ValidateArbitraryGenerator.java @@ -133,52 +133,22 @@ public CombinableArbitrary generate(ArbitraryGeneratorContext context) { BigDecimal value = toBigDecimal(it); - if (value.compareTo(BigDecimal.ZERO) < 0) { - if (javaDecimalConstraint.getNegativeMin() != null) { - if (value.compareTo(javaDecimalConstraint.getNegativeMin()) == 0 - && Boolean.FALSE.equals(javaDecimalConstraint.getNegativeMinInclusive())) { - return false; - } - - if (value.compareTo(javaDecimalConstraint.getNegativeMin()) < 0) { - return false; - } + if (javaDecimalConstraint.getMin() != null) { + if (value.compareTo(javaDecimalConstraint.getMin()) == 0 + && Boolean.FALSE.equals(javaDecimalConstraint.getMinInclusive())) { + return false; } - if (javaDecimalConstraint.getNegativeMax() != null) { - if (value.compareTo(javaDecimalConstraint.getNegativeMax()) == 0 - && Boolean.FALSE.equals(javaDecimalConstraint.getNegativeMaxInclusive())) { - return false; - } - - if (value.compareTo(javaDecimalConstraint.getNegativeMax()) > 0) { - return false; - } - } + return value.compareTo(javaDecimalConstraint.getMin()) >= 0; } - if (value.compareTo(BigDecimal.ZERO) > 0) { - if (javaDecimalConstraint.getPositiveMin() != null) { - if (value.compareTo(javaDecimalConstraint.getPositiveMin()) == 0 - && Boolean.FALSE.equals(javaDecimalConstraint.getPositiveMinInclusive())) { - return false; - } - - if (value.compareTo(javaDecimalConstraint.getPositiveMin()) < 0) { - return false; - } + if (javaDecimalConstraint.getMax() != null) { + if (value.compareTo(javaDecimalConstraint.getMax()) == 0 + && Boolean.FALSE.equals(javaDecimalConstraint.getMaxInclusive())) { + return false; } - if (javaDecimalConstraint.getPositiveMax() != null) { - if (value.compareTo(javaDecimalConstraint.getPositiveMax()) == 0 - && Boolean.FALSE.equals(javaDecimalConstraint.getPositiveMaxInclusive())) { - return false; - } - - if (value.compareTo(javaDecimalConstraint.getPositiveMax()) > 0) { - return false; - } - } + return value.compareTo(javaDecimalConstraint.getMax()) <= 0; } return true; diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JqwikJavaArbitraryResolver.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JqwikJavaArbitraryResolver.java index d808da8c8..0ed57f4e3 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JqwikJavaArbitraryResolver.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/jqwik/JqwikJavaArbitraryResolver.java @@ -207,61 +207,40 @@ public Arbitrary floats( return floatArbitrary; } - BigDecimal positiveMin = constraint.getPositiveMin(); - BigDecimal positiveMax = constraint.getPositiveMax(); - Boolean positiveMinInclusive = constraint.getPositiveMinInclusive(); - Boolean positiveMaxInclusive = constraint.getPositiveMaxInclusive(); - BigDecimal negativeMin = constraint.getNegativeMin(); - BigDecimal negativeMax = constraint.getNegativeMax(); - Boolean negativeMinInclusive = constraint.getNegativeMinInclusive(); - Boolean negativeMaxInclusive = constraint.getNegativeMaxInclusive(); + BigDecimal min = constraint.getMin(); + Boolean minInclusive = constraint.getMinInclusive(); + BigDecimal max = constraint.getMax(); + Boolean maxInclusive = constraint.getMaxInclusive(); Integer scale = constraint.getScale(); - FloatArbitrary positiveArbitrary = null; - FloatArbitrary negativeArbitrary = null; - if (positiveMin != null) { - positiveArbitrary = Types.defaultIfNull(positiveArbitrary, () -> floatArbitrary); - if (positiveMinInclusive != null && positiveMinInclusive) { - positiveArbitrary = positiveArbitrary.greaterOrEqual(positiveMin.floatValue()); - } else { - positiveArbitrary = positiveArbitrary.greaterThan(positiveMin.floatValue()); - } - } - if (positiveMax != null) { - positiveArbitrary = Types.defaultIfNull(positiveArbitrary, () -> floatArbitrary); - if (positiveMaxInclusive != null && positiveMaxInclusive) { - positiveArbitrary = positiveArbitrary.lessOrEqual(positiveMax.floatValue()); - } else { - positiveArbitrary = positiveArbitrary.lessThan(positiveMax.floatValue()); - } - } - if (negativeMin != null) { - negativeArbitrary = Types.defaultIfNull(negativeArbitrary, () -> floatArbitrary); - if (negativeMinInclusive != null && negativeMinInclusive) { - negativeArbitrary = negativeArbitrary.greaterOrEqual(negativeMin.floatValue()); + FloatArbitrary arbitrary = null; + + if (min != null) { + arbitrary = Types.defaultIfNull(arbitrary, () -> floatArbitrary); + if (minInclusive == null || minInclusive) { + arbitrary = arbitrary.greaterOrEqual(min.floatValue()); } else { - negativeArbitrary = negativeArbitrary.greaterThan(negativeMin.floatValue()); + arbitrary = arbitrary.greaterThan(min.floatValue()); } } - if (negativeMax != null) { - negativeArbitrary = Types.defaultIfNull(negativeArbitrary, () -> floatArbitrary); - if (negativeMaxInclusive != null && negativeMaxInclusive) { - negativeArbitrary = negativeArbitrary.lessOrEqual(negativeMax.floatValue()); + if (max != null) { + arbitrary = Types.defaultIfNull(arbitrary, () -> floatArbitrary); + if (maxInclusive == null || maxInclusive) { + arbitrary = arbitrary.lessOrEqual(max.floatValue()); } else { - negativeArbitrary = negativeArbitrary.lessThan(negativeMax.floatValue()); + arbitrary = arbitrary.lessThan(max.floatValue()); } } - if (scale != null) { - if (positiveArbitrary != null) { - positiveArbitrary = positiveArbitrary.ofScale(scale); - } - if (negativeArbitrary != null) { - negativeArbitrary = negativeArbitrary.ofScale(scale); + if (arbitrary != null) { + arbitrary = arbitrary.ofScale(scale); } } - return resolveArbitrary(floatArbitrary, positiveArbitrary, negativeArbitrary); + if (arbitrary == null) { + return floatArbitrary; + } + return arbitrary; } @Override @@ -274,61 +253,40 @@ public Arbitrary doubles( return doubleArbitrary; } - BigDecimal positiveMin = constraint.getPositiveMin(); - BigDecimal positiveMax = constraint.getPositiveMax(); - Boolean positiveMinInclusive = constraint.getPositiveMinInclusive(); - Boolean positiveMaxInclusive = constraint.getPositiveMaxInclusive(); - BigDecimal negativeMin = constraint.getNegativeMin(); - BigDecimal negativeMax = constraint.getNegativeMax(); - Boolean negativeMinInclusive = constraint.getNegativeMinInclusive(); - Boolean negativeMaxInclusive = constraint.getNegativeMaxInclusive(); + BigDecimal min = constraint.getMin(); + Boolean minInclusive = constraint.getMinInclusive(); + BigDecimal max = constraint.getMax(); + Boolean maxInclusive = constraint.getMaxInclusive(); Integer scale = constraint.getScale(); - DoubleArbitrary positiveArbitrary = null; - DoubleArbitrary negativeArbitrary = null; - if (positiveMin != null) { - positiveArbitrary = Types.defaultIfNull(positiveArbitrary, () -> doubleArbitrary); - if (positiveMinInclusive != null && positiveMinInclusive) { - positiveArbitrary = positiveArbitrary.greaterOrEqual(positiveMin.doubleValue()); - } else { - positiveArbitrary = positiveArbitrary.greaterThan(positiveMin.doubleValue()); - } - } - if (positiveMax != null) { - positiveArbitrary = Types.defaultIfNull(positiveArbitrary, () -> doubleArbitrary); - if (positiveMaxInclusive != null && positiveMaxInclusive) { - positiveArbitrary = positiveArbitrary.lessOrEqual(positiveMax.doubleValue()); - } else { - positiveArbitrary = positiveArbitrary.lessThan(positiveMax.doubleValue()); - } - } - if (negativeMin != null) { - negativeArbitrary = Types.defaultIfNull(negativeArbitrary, () -> doubleArbitrary); - if (negativeMinInclusive != null && negativeMinInclusive) { - negativeArbitrary = negativeArbitrary.greaterOrEqual(negativeMin.floatValue()); + DoubleArbitrary arbitrary = null; + + if (min != null) { + arbitrary = Types.defaultIfNull(arbitrary, () -> doubleArbitrary); + if (minInclusive == null || minInclusive) { + arbitrary = arbitrary.greaterOrEqual(min.doubleValue()); } else { - negativeArbitrary = negativeArbitrary.greaterThan(negativeMin.floatValue()); + arbitrary = arbitrary.greaterThan(min.doubleValue()); } } - if (negativeMax != null) { - negativeArbitrary = Types.defaultIfNull(negativeArbitrary, () -> doubleArbitrary); - if (negativeMaxInclusive != null && negativeMaxInclusive) { - negativeArbitrary = negativeArbitrary.lessOrEqual(negativeMax.doubleValue()); + if (max != null) { + arbitrary = Types.defaultIfNull(arbitrary, () -> doubleArbitrary); + if (maxInclusive == null || maxInclusive) { + arbitrary = arbitrary.lessOrEqual(max.doubleValue()); } else { - negativeArbitrary = negativeArbitrary.lessThan(negativeMax.doubleValue()); + arbitrary = arbitrary.lessThan(max.doubleValue()); } } - if (scale != null) { - if (positiveArbitrary != null) { - positiveArbitrary = positiveArbitrary.ofScale(scale); - } - if (negativeArbitrary != null) { - negativeArbitrary = negativeArbitrary.ofScale(scale); + if (arbitrary != null) { + arbitrary = arbitrary.ofScale(scale); } } - return resolveArbitrary(doubleArbitrary, positiveArbitrary, negativeArbitrary); + if (arbitrary == null) { + return doubleArbitrary; + } + return arbitrary; } @Override @@ -450,62 +408,40 @@ public Arbitrary bigDecimals( return bigDecimalArbitrary; } - BigDecimal positiveMin = constraint.getPositiveMin(); - BigDecimal positiveMax = constraint.getPositiveMax(); - Boolean positiveMinInclusive = constraint.getPositiveMinInclusive(); - Boolean positiveMaxInclusive = constraint.getPositiveMaxInclusive(); - BigDecimal negativeMin = constraint.getNegativeMin(); - BigDecimal negativeMax = constraint.getNegativeMax(); - Boolean negativeMinInclusive = constraint.getNegativeMinInclusive(); - Boolean negativeMaxInclusive = constraint.getNegativeMaxInclusive(); + BigDecimal min = constraint.getMin(); + Boolean minInclusive = constraint.getMinInclusive(); + BigDecimal max = constraint.getMax(); + Boolean maxInclusive = constraint.getMaxInclusive(); Integer scale = constraint.getScale(); - BigDecimalArbitrary positiveArbitrary = null; - BigDecimalArbitrary negativeArbitrary = null; - if (positiveMin != null) { - positiveArbitrary = Types.defaultIfNull(positiveArbitrary, () -> bigDecimalArbitrary); - if (positiveMinInclusive != null && positiveMinInclusive) { - positiveArbitrary = positiveArbitrary.greaterOrEqual(positiveMin); - } else { - positiveArbitrary = positiveArbitrary.greaterThan(positiveMin); - } - } - if (positiveMax != null) { - positiveArbitrary = Types.defaultIfNull(positiveArbitrary, () -> bigDecimalArbitrary); - if (positiveMaxInclusive != null && positiveMaxInclusive) { - positiveArbitrary = positiveArbitrary.lessOrEqual(positiveMax); - } else { - positiveArbitrary = positiveArbitrary.lessThan(positiveMax); - } - } + BigDecimalArbitrary arbitrary = null; - if (negativeMin != null) { - negativeArbitrary = Types.defaultIfNull(negativeArbitrary, () -> bigDecimalArbitrary); - if (negativeMinInclusive != null && negativeMinInclusive) { - negativeArbitrary = negativeArbitrary.greaterOrEqual(negativeMin); + if (min != null) { + arbitrary = Types.defaultIfNull(arbitrary, () -> bigDecimalArbitrary); + if (minInclusive == null || minInclusive) { + arbitrary = arbitrary.greaterOrEqual(min); } else { - negativeArbitrary = negativeArbitrary.greaterThan(negativeMin); + arbitrary = arbitrary.greaterThan(min); } } - if (negativeMax != null) { - negativeArbitrary = Types.defaultIfNull(negativeArbitrary, () -> bigDecimalArbitrary); - if (negativeMaxInclusive != null && negativeMaxInclusive) { - negativeArbitrary = negativeArbitrary.lessOrEqual(negativeMax); + if (max != null) { + arbitrary = Types.defaultIfNull(arbitrary, () -> bigDecimalArbitrary); + if (maxInclusive == null || maxInclusive) { + arbitrary = arbitrary.lessOrEqual(max); } else { - negativeArbitrary = negativeArbitrary.lessThan(negativeMax); + arbitrary = arbitrary.lessThan(max); } } - if (scale != null) { - if (positiveArbitrary != null) { - positiveArbitrary = positiveArbitrary.ofScale(scale); - } - if (negativeArbitrary != null) { - negativeArbitrary = negativeArbitrary.ofScale(scale); + if (arbitrary != null) { + arbitrary = arbitrary.ofScale(scale); } } - return resolveArbitrary(bigDecimalArbitrary, positiveArbitrary, negativeArbitrary); + if (arbitrary == null) { + return bigDecimalArbitrary; + } + return arbitrary; } private static Arbitrary resolveArbitrary( diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java index 1599f0e95..54afa7c5c 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java @@ -237,13 +237,9 @@ public JavaIntegerConstraint generateIntegerConstraint(ArbitraryGeneratorContext @Override public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext context) { return new JavaDecimalConstraint( - BigDecimal.valueOf(this.positiveMinNumberValue), - true, - BigDecimal.valueOf(this.positiveMaxNumberValue), - true, BigDecimal.valueOf(this.negativeMinNumberValue), true, - BigDecimal.valueOf(this.negativeMaxNumberValue), + BigDecimal.valueOf(this.positiveMaxNumberValue), true, 2 ); diff --git a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java index 35c329567..b4181518e 100644 --- a/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java +++ b/fixture-monkey-jakarta-validation/src/main/java/com/navercorp/fixturemonkey/jakarta/validation/introspector/JakartaValidationConstraintGenerator.java @@ -399,51 +399,7 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext return null; } - boolean isPositiveMin = min != null && min.compareTo(BigDecimal.ZERO) >= 0; - boolean isPositiveMax = max != null && max.compareTo(BigDecimal.ZERO) >= 0; - boolean isNegativeMin = min != null && min.compareTo(BigDecimal.ZERO) < 0; - boolean isNegativeMax = max != null && max.compareTo(BigDecimal.ZERO) < 0; - - if (isPositiveMax && max.equals(BigDecimal.ZERO)) { - return new JavaDecimalConstraint( - null, - null, - null, - null, - isNegativeMin ? min : null, - isNegativeMin ? minInclusive : null, - BigDecimal.ZERO, - isNegativeMax ? maxInclusive : null, - scale - ); - } - - if (isNegativeMin && isPositiveMax) { - return new JavaDecimalConstraint( - BigDecimal.ZERO, - true, - max, - maxInclusive, - min, - minInclusive, - BigDecimal.ZERO, - false, - scale - ); - } - - return new JavaDecimalConstraint( - isPositiveMin ? min : null, - isPositiveMin ? minInclusive : null, - isPositiveMax ? max : null, - isPositiveMax ? maxInclusive : null, - isNegativeMin ? min : null, - isNegativeMin ? minInclusive : null, - isNegativeMax ? max : null, - isNegativeMax ? maxInclusive : null, - scale - ); - + return new JavaDecimalConstraint(min, minInclusive, max, maxInclusive, scale); } @Override diff --git a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java index 5835a624a..070c67aac 100644 --- a/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java +++ b/fixture-monkey-javax-validation/src/main/java/com/navercorp/fixturemonkey/javax/validation/introspector/JavaxValidationConstraintGenerator.java @@ -398,50 +398,7 @@ public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext return null; } - boolean isPositiveMin = min != null && min.compareTo(BigDecimal.ZERO) >= 0; - boolean isPositiveMax = max != null && max.compareTo(BigDecimal.ZERO) >= 0; - boolean isNegativeMin = min != null && min.compareTo(BigDecimal.ZERO) < 0; - boolean isNegativeMax = max != null && max.compareTo(BigDecimal.ZERO) < 0; - - if (isPositiveMax && max.equals(BigDecimal.ZERO)) { - return new JavaDecimalConstraint( - null, - null, - null, - null, - isNegativeMin ? min : null, - isNegativeMin ? minInclusive : null, - BigDecimal.ZERO, - isNegativeMax ? maxInclusive : null, - scale - ); - } - - if (isNegativeMin && isPositiveMax) { - return new JavaDecimalConstraint( - BigDecimal.ZERO, - true, - max, - maxInclusive, - min, - minInclusive, - BigDecimal.ZERO, - false, - scale - ); - } - - return new JavaDecimalConstraint( - isPositiveMin ? min : null, - isPositiveMin ? minInclusive : null, - isPositiveMax ? max : null, - isPositiveMax ? maxInclusive : null, - isNegativeMin ? min : null, - isNegativeMin ? minInclusive : null, - isNegativeMax ? max : null, - isNegativeMax ? maxInclusive : null, - scale - ); + return new JavaDecimalConstraint(min, minInclusive, max, maxInclusive, scale); } @Override diff --git a/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt b/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt index 924c8c679..f4e4c5e9e 100644 --- a/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt +++ b/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt @@ -24,31 +24,7 @@ import com.navercorp.fixturemonkey.api.arbitrary.JavaTypeArbitraryGeneratorSet import com.navercorp.fixturemonkey.api.constraint.JavaConstraintGenerator import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext import io.kotest.property.Arb -import io.kotest.property.arbitrary.bigDecimal -import io.kotest.property.arbitrary.bigInt -import io.kotest.property.arbitrary.byte -import io.kotest.property.arbitrary.char -import io.kotest.property.arbitrary.choice -import io.kotest.property.arbitrary.double -import io.kotest.property.arbitrary.duration -import io.kotest.property.arbitrary.filter -import io.kotest.property.arbitrary.float -import io.kotest.property.arbitrary.instant -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.localDate -import io.kotest.property.arbitrary.localDateTime -import io.kotest.property.arbitrary.localTime -import io.kotest.property.arbitrary.long -import io.kotest.property.arbitrary.map -import io.kotest.property.arbitrary.offsetDateTime -import io.kotest.property.arbitrary.period -import io.kotest.property.arbitrary.short -import io.kotest.property.arbitrary.single -import io.kotest.property.arbitrary.string -import io.kotest.property.arbitrary.yearMonth -import io.kotest.property.arbitrary.zoneId -import io.kotest.property.arbitrary.zoneOffset -import io.kotest.property.arbitrary.zonedDateTime +import io.kotest.property.arbitrary.* import org.apiguardian.api.API import org.apiguardian.api.API.Status import java.math.BigDecimal @@ -166,46 +142,24 @@ class KotestJavaArbitraryGeneratorSet( return CombinableArbitrary.from { if (decimalConstraint != null) { val scale = decimalConstraint.scale - // TODO: waits for update in Kotest - // val positiveMaxInclusive = decimalConstraint.positiveMaxInclusive ?: false - // val positiveMinInclusive = decimalConstraint.positiveMinInclusive ?: false - // val negativeMaxInclusive = decimalConstraint.negativeMaxInclusive ?: false - // val negativeMinInclusive = decimalConstraint.negativeMinInclusive ?: false - - val positiveArb = if (decimalConstraint.positiveMin != null || decimalConstraint.positiveMax != null) { - val positiveMinSize = - decimalConstraint.positiveMin?.toDouble() ?: 0.0 - val positiveMaxSize = decimalConstraint.positiveMax?.toDouble() ?: Double.MAX_VALUE - Arb.double(min = positiveMinSize, max = positiveMaxSize).map { - if (scale != null) { - it.ofScale(scale) - } else { - it - } - } - } else { - null - } + var min = decimalConstraint.min?.toDouble() ?: -Double.MAX_VALUE + var max = decimalConstraint.max?.toDouble() ?: Double.MAX_VALUE - val negativeArb = if (decimalConstraint.negativeMin != null || decimalConstraint.negativeMax != null) { - val negativeMinSize = decimalConstraint.negativeMin?.toDouble() ?: -Double.MIN_VALUE - val negativeMaxSize = decimalConstraint.negativeMax?.toDouble() ?: -0.0 - Arb.double(min = negativeMinSize, max = negativeMaxSize).map { - if (scale != null) { - it.ofScale(scale) - } else { - it - } + if (decimalConstraint.minInclusive == false) { + min += Double.MIN_VALUE + } + if (decimalConstraint.maxInclusive ?: true) { + if (max != Double.MAX_VALUE) { + max += Double.MIN_VALUE } - } else { - null } - if (positiveArb != null && negativeArb != null) { - Arb.choice(negativeArb, positiveArb) + if (min == max) { + Arb.constant(min) } else { - negativeArb ?: positiveArb!! - }.single() + Arb.double(min = min, max = max) + }.map { if (scale != null) it.ofScale(scale) else it } + .single() } else { Arb.double().single() } @@ -218,46 +172,24 @@ class KotestJavaArbitraryGeneratorSet( return CombinableArbitrary.from { if (decimalConstraint != null) { val scale = decimalConstraint.scale - // TODO: waits for update in Kotest - // val positiveMaxInclusive = decimalConstraint.positiveMaxInclusive ?: false - // val positiveMinInclusive = decimalConstraint.positiveMinInclusive ?: false - // val negativeMaxInclusive = decimalConstraint.negativeMaxInclusive ?: false - // val negativeMinInclusive = decimalConstraint.negativeMinInclusive ?: false - - val positiveArb = if (decimalConstraint.positiveMin != null || decimalConstraint.positiveMax != null) { - val positiveMinSize = - decimalConstraint.positiveMin?.toFloat() ?: 0.0f - val positiveMaxSize = decimalConstraint.positiveMax?.toFloat() ?: Float.MAX_VALUE - Arb.float(min = positiveMinSize, max = positiveMaxSize).map { - if (scale != null) { - it.ofScale(scale) - } else { - it - } - } - } else { - null - } + var min = decimalConstraint.min?.toFloat() ?: -Float.MAX_VALUE + var max = decimalConstraint.max?.toFloat() ?: Float.MAX_VALUE - val negativeArb = if (decimalConstraint.negativeMin != null || decimalConstraint.negativeMax != null) { - val negativeMinSize = decimalConstraint.negativeMin?.toFloat() ?: -Float.MIN_VALUE - val negativeMaxSize = decimalConstraint.negativeMax?.toFloat() ?: -0.0f - Arb.float(min = negativeMinSize, max = negativeMaxSize).map { - if (scale != null) { - it.ofScale(scale) - } else { - it - } + if (decimalConstraint.minInclusive == false) { + min += Float.MIN_VALUE + } + if (decimalConstraint.maxInclusive ?: true) { + if (max != Float.MAX_VALUE) { + max += Float.MIN_VALUE } - } else { - null } - if (positiveArb != null && negativeArb != null) { - Arb.choice(negativeArb, positiveArb) + if (min == max) { + Arb.constant(min) } else { - negativeArb ?: positiveArb!! - }.single() + Arb.float(min = min, max = max) + }.map { if (scale != null) it.ofScale(scale) else it } + .single() } else { Arb.float().single() } @@ -366,46 +298,24 @@ class KotestJavaArbitraryGeneratorSet( return CombinableArbitrary.from { if (decimalConstraint != null) { val scale = decimalConstraint.scale - // TODO: waits for update in Kotest - // val positiveMaxInclusive = decimalConstraint.positiveMaxInclusive ?: false - // val positiveMinInclusive = decimalConstraint.positiveMinInclusive ?: false - // val negativeMaxInclusive = decimalConstraint.negativeMaxInclusive ?: false - // val negativeMinInclusive = decimalConstraint.negativeMinInclusive ?: false - - val positiveArb = if (decimalConstraint.positiveMin != null || decimalConstraint.positiveMax != null) { - val positiveMinSize = - decimalConstraint.positiveMin ?: BigDecimal.ZERO - val positiveMaxSize = decimalConstraint.positiveMax ?: BigDecimal.valueOf(Double.MAX_VALUE) - Arb.bigDecimal(min = positiveMinSize, max = positiveMaxSize).map { - if (scale != null) { - it.setScale(scale, RoundingMode.DOWN) - } else { - it - } - } - } else { - null - } + var min = decimalConstraint.min ?: BigDecimal.valueOf(-Double.MAX_VALUE) + var max = decimalConstraint.max ?: BigDecimal.valueOf(Double.MAX_VALUE) - val negativeArb = if (decimalConstraint.negativeMin != null || decimalConstraint.negativeMax != null) { - val negativeMinSize = decimalConstraint.negativeMin ?: -BigDecimal.valueOf(Double.MIN_VALUE) - val negativeMaxSize = decimalConstraint.negativeMax ?: -BigDecimal.ZERO - Arb.bigDecimal(min = negativeMinSize, max = negativeMaxSize).map { - if (scale != null) { - it.setScale(scale, RoundingMode.DOWN) - } else { - it - } + if (decimalConstraint.minInclusive == false) { + min = min.add(BigDecimal.valueOf(Double.MIN_VALUE)) + } + if (decimalConstraint.maxInclusive ?: true) { + if (max != BigDecimal.valueOf(Double.MAX_VALUE)) { + max += max.add(BigDecimal.valueOf(Double.MIN_VALUE)) } - } else { - null } - if (positiveArb != null && negativeArb != null) { - Arb.choice(negativeArb, positiveArb) + if (min.compareTo(max) == 0) { + Arb.constant(min) } else { - negativeArb ?: positiveArb!! - }.single() + Arb.bigDecimal(min = min, max = max) + }.map { if (scale != null) it.setScale(scale, RoundingMode.DOWN) else it } + .single() } else { Arb.bigDecimal().single() } diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt index 9912471a6..cbe0e99c8 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotestInJunitTest.kt @@ -309,6 +309,43 @@ class KotestInJunitTest { then(actual).matches { it in -99.0..99.0 } } + @RepeatedTest(TEST_COUNT) + fun sampleDoubleWithEqualMinMax() { + class DoubleObject( + @field:DecimalMin("10.0") @field:DecimalMax("10.0") + val value: Double + ) + + val actual = SUT.giveMeOne().value + then(actual).isEqualTo(10.0) + } + + @RepeatedTest(TEST_COUNT) + fun sampleDoubleWithMultipleConstraints() { + class DoubleObject( + @field:DecimalMax("11.5") @field:Max(10) + val value: Double + ) + + val actual = SUT.giveMeOne().value + then(actual).isLessThanOrEqualTo(10.0) + } + + @RepeatedTest(TEST_COUNT) + fun sampleDoubleWithPreciseExclusiveBounds() { + class DoubleObject( + @field:DecimalMin(value = "10.0", inclusive = false) + @field:DecimalMax(value = "10.1", inclusive = false) + val value: Double + ) + + val actual = SUT.giveMeOne().value + + then(actual) + .isGreaterThan(10.0) + .isLessThan(10.1) + } + @RepeatedTest(TEST_COUNT) fun sampleFloatWithNegative() { class FloatObject(@field:Negative val value: Float) @@ -390,6 +427,43 @@ class KotestInJunitTest { then(actual).matches { it in -99.0..99.0 } } + @RepeatedTest(TEST_COUNT) + fun sampleFloatWithEqualMinMax() { + class DoubleObject( + @field:DecimalMin("10.0") @field:DecimalMax("10.0") + val value: Double + ) + + val actual = SUT.giveMeOne().value + then(actual).isEqualTo(10.0) + } + + @RepeatedTest(TEST_COUNT) + fun sampleFloatWithMultipleConstraints() { + class DoubleObject( + @field:DecimalMax("11.5") @field:Max(10) + val value: Double + ) + + val actual = SUT.giveMeOne().value + then(actual).isLessThanOrEqualTo(10.0) + } + + @RepeatedTest(TEST_COUNT) + fun sampleFloatWithPreciseExclusiveBounds() { + class FloatObject( + @field:DecimalMin(value = "10.0", inclusive = false) + @field:DecimalMax(value = "10.1", inclusive = false) + val value: Float + ) + + val actual = SUT.giveMeOne().value + + then(actual) + .isGreaterThan(10.0f) + .isLessThan(10.1f) + } + @RepeatedTest(TEST_COUNT) fun sampleIntWithNegative() { class IntObject(@field:Negative val value: Int) @@ -718,6 +792,43 @@ class KotestInJunitTest { } } + @RepeatedTest(TEST_COUNT) + fun sampleBigDecimalWithEqualMinMax() { + class BigDecimalObject( + @field:DecimalMin("10.00") @field:DecimalMax("10.00") + val value: BigDecimal + ) + + val actual = SUT.giveMeOne().value + then(actual).isEqualByComparingTo(BigDecimal("10.00")) + } + + @RepeatedTest(TEST_COUNT) + fun sampleBigDecimalWithMultipleConstraints() { + class BigDecimalObject( + @field:DecimalMax("11.5") @field:Max(10) + val value: BigDecimal + ) + + val actual = SUT.giveMeOne().value + then(actual).isLessThanOrEqualTo(BigDecimal.valueOf(10)) + } + + @RepeatedTest(TEST_COUNT) + fun sampleBigDecimalWithPreciseExclusiveBounds() { + class BigDecimalObject( + @field:DecimalMin(value = "10.0", inclusive = false) + @field:DecimalMax(value = "10.1", inclusive = false) + val value: BigDecimal + ) + + val actual = SUT.giveMeOne().value + + then(actual) + .isGreaterThan(BigDecimal("10.0")) + .isLessThan(BigDecimal("10.1")) + } + @RepeatedTest(TEST_COUNT) fun setPostConditionExtension() { class StringObject(val string: String) From 7e0439a7727ede458478f837cdda2873486b0c27 Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Sat, 8 Feb 2025 00:31:05 +0900 Subject: [PATCH 11/13] chore: resolve Kotlin lint issue --- .../kotest/KotestArbitraryGeneratorSet.kt | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt b/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt index f4e4c5e9e..7ca349b96 100644 --- a/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt +++ b/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt @@ -24,7 +24,32 @@ import com.navercorp.fixturemonkey.api.arbitrary.JavaTypeArbitraryGeneratorSet import com.navercorp.fixturemonkey.api.constraint.JavaConstraintGenerator import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext import io.kotest.property.Arb -import io.kotest.property.arbitrary.* +import io.kotest.property.arbitrary.bigDecimal +import io.kotest.property.arbitrary.bigInt +import io.kotest.property.arbitrary.byte +import io.kotest.property.arbitrary.char +import io.kotest.property.arbitrary.choice +import io.kotest.property.arbitrary.constant +import io.kotest.property.arbitrary.double +import io.kotest.property.arbitrary.duration +import io.kotest.property.arbitrary.filter +import io.kotest.property.arbitrary.float +import io.kotest.property.arbitrary.instant +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.localDate +import io.kotest.property.arbitrary.localDateTime +import io.kotest.property.arbitrary.localTime +import io.kotest.property.arbitrary.long +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.offsetDateTime +import io.kotest.property.arbitrary.period +import io.kotest.property.arbitrary.short +import io.kotest.property.arbitrary.single +import io.kotest.property.arbitrary.string +import io.kotest.property.arbitrary.yearMonth +import io.kotest.property.arbitrary.zonedDateTime +import io.kotest.property.arbitrary.zoneId +import io.kotest.property.arbitrary.zoneOffset import org.apiguardian.api.API import org.apiguardian.api.API.Status import java.math.BigDecimal From e961cd4b3aa9c0c60f83313e83c64561d6b1f24b Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Sat, 8 Feb 2025 01:25:04 +0900 Subject: [PATCH 12/13] fix: min/max equality check timing adjustment in decimal value generators --- .../kotest/KotestArbitraryGeneratorSet.kt | 69 +++++++++++-------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt b/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt index 7ca349b96..5f7c5c19c 100644 --- a/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt +++ b/fixture-monkey-kotest/src/main/kotlin/com/navercorp/fixturemonkey/kotest/KotestArbitraryGeneratorSet.kt @@ -170,18 +170,21 @@ class KotestJavaArbitraryGeneratorSet( var min = decimalConstraint.min?.toDouble() ?: -Double.MAX_VALUE var max = decimalConstraint.max?.toDouble() ?: Double.MAX_VALUE - if (decimalConstraint.minInclusive == false) { - min += Double.MIN_VALUE - } - if (decimalConstraint.maxInclusive ?: true) { - if (max != Double.MAX_VALUE) { - max += Double.MIN_VALUE - } - } - - if (min == max) { + if (min == max && + (decimalConstraint.minInclusive ?: true) && + (decimalConstraint.maxInclusive ?: true) + ) { Arb.constant(min) } else { + if (decimalConstraint.minInclusive == false) { + min += Double.MIN_VALUE + } + if (decimalConstraint.maxInclusive ?: true) { + if (max != Double.MAX_VALUE) { + max += Double.MIN_VALUE + } + } + Arb.double(min = min, max = max) }.map { if (scale != null) it.ofScale(scale) else it } .single() @@ -200,18 +203,21 @@ class KotestJavaArbitraryGeneratorSet( var min = decimalConstraint.min?.toFloat() ?: -Float.MAX_VALUE var max = decimalConstraint.max?.toFloat() ?: Float.MAX_VALUE - if (decimalConstraint.minInclusive == false) { - min += Float.MIN_VALUE - } - if (decimalConstraint.maxInclusive ?: true) { - if (max != Float.MAX_VALUE) { - max += Float.MIN_VALUE - } - } - - if (min == max) { + if (min == max && + (decimalConstraint.minInclusive ?: true) && + (decimalConstraint.maxInclusive ?: true) + ) { Arb.constant(min) } else { + if (decimalConstraint.minInclusive == false) { + min += Float.MIN_VALUE + } + if (decimalConstraint.maxInclusive ?: true) { + if (max != Float.MAX_VALUE) { + max += Float.MIN_VALUE + } + } + Arb.float(min = min, max = max) }.map { if (scale != null) it.ofScale(scale) else it } .single() @@ -326,18 +332,21 @@ class KotestJavaArbitraryGeneratorSet( var min = decimalConstraint.min ?: BigDecimal.valueOf(-Double.MAX_VALUE) var max = decimalConstraint.max ?: BigDecimal.valueOf(Double.MAX_VALUE) - if (decimalConstraint.minInclusive == false) { - min = min.add(BigDecimal.valueOf(Double.MIN_VALUE)) - } - if (decimalConstraint.maxInclusive ?: true) { - if (max != BigDecimal.valueOf(Double.MAX_VALUE)) { - max += max.add(BigDecimal.valueOf(Double.MIN_VALUE)) - } - } - - if (min.compareTo(max) == 0) { + if (min.compareTo(max) == 0 && + (decimalConstraint.minInclusive ?: true) && + (decimalConstraint.maxInclusive ?: true) + ) { Arb.constant(min) } else { + if (decimalConstraint.minInclusive == false) { + min = min.add(BigDecimal.valueOf(Double.MIN_VALUE)) + } + if (decimalConstraint.maxInclusive ?: true) { + if (max != BigDecimal.valueOf(Double.MAX_VALUE)) { + max = max.add(BigDecimal.valueOf(Double.MIN_VALUE)) + } + } + Arb.bigDecimal(min = min, max = max) }.map { if (scale != null) it.setScale(scale, RoundingMode.DOWN) else it } .single() From cca9e541608794d46acd41f181a96609266fa0fc Mon Sep 17 00:00:00 2001 From: Seol_JY Date: Sat, 8 Feb 2025 18:15:32 +0900 Subject: [PATCH 13/13] fix: unify number range handling in decimal constraint generation --- .../api/plugin/SimpleValueJqwikPlugin.java | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java index b975e4b78..c58120bf2 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/plugin/SimpleValueJqwikPlugin.java @@ -262,28 +262,15 @@ public JavaIntegerConstraint generateIntegerConstraint(ArbitraryGeneratorContext @Override public JavaDecimalConstraint generateDecimalConstraint(ArbitraryGeneratorContext context) { - BigDecimal positiveMin = ifNotNull(this.positiveMinNumberValue, BigDecimal::valueOf); - BigDecimal positiveMax = ifNotNull(this.positiveMaxNumberValue, BigDecimal::valueOf); - BigDecimal negativeMin = ifNotNull(this.negativeMinNumberValue, BigDecimal::valueOf); - BigDecimal negativeMax = ifNotNull(this.negativeMaxNumberValue, BigDecimal::valueOf); + BigDecimal min = negativeMinNumberValue != null + ? BigDecimal.valueOf(negativeMinNumberValue) : + BigDecimal.valueOf(defaultIfNull(positiveMinNumberValue, () -> DEFAULT_MIN_NUMBER_VALUE)); - if (positiveMin == null) { - negativeMin = defaultIfNull(negativeMin, () -> BigDecimal.valueOf(DEFAULT_MIN_NUMBER_VALUE)); - negativeMax = defaultIfNull(negativeMax, () -> BigDecimal.ZERO); - } - - if (negativeMax == null) { - positiveMin = defaultIfNull(positiveMin, () -> BigDecimal.ZERO); - positiveMax = defaultIfNull(positiveMax, () -> BigDecimal.valueOf(DEFAULT_MAX_NUMBER_VALUE)); - } + BigDecimal max = positiveMaxNumberValue != null + ? BigDecimal.valueOf(positiveMaxNumberValue) : + BigDecimal.valueOf(defaultIfNull(negativeMaxNumberValue, () -> DEFAULT_MAX_NUMBER_VALUE)); - return new JavaDecimalConstraint( - BigDecimal.valueOf(this.negativeMinNumberValue), - true, - BigDecimal.valueOf(this.positiveMaxNumberValue), - true, - 2 - ); + return new JavaDecimalConstraint(min, true, max, true, 2); } @Override