diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e48c2b..1d86223 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,6 @@ jobs: fail-fast: false matrix: java-version: - - 11 - 17 steps: - uses: actions/checkout@v1 diff --git a/pom.xml b/pom.xml index afe17db..6f98177 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ io.airlift airbase - 129 + 143 2016 @@ -21,7 +21,8 @@ true true -missing - 11 + 17 + 234 @@ -38,8 +39,8 @@ - javax.validation - validation-api + jakarta.validation + jakarta.validation-api true @@ -71,20 +72,20 @@ io.airlift testing - 218 + ${dep.airlift.version} test io.airlift json - 218 + ${dep.airlift.version} test - org.apache.bval - bval-jsr + org.hibernate.validator + hibernate-validator test diff --git a/src/main/java/io/airlift/units/DataSize.java b/src/main/java/io/airlift/units/DataSize.java index 60f9781..b765386 100644 --- a/src/main/java/io/airlift/units/DataSize.java +++ b/src/main/java/io/airlift/units/DataSize.java @@ -79,6 +79,7 @@ public static DataSize succinctBytes(long bytes) /** * Prefer {@link DataSize#of(long, Unit)} when conversion to the most 'succinct' unit is not necessary or desirable. * Otherwise, use {@link DataSize#succinctBytes(long)} since it will not incur rounding and loss of precision. + * * @deprecated use {@link DataSize#succinctBytes(long)} instead, double values are imprecise */ @Deprecated @@ -93,6 +94,7 @@ public static DataSize succinctDataSize(double size, Unit unit) /** * Private constructor to avoid confusing usage sites with having to pass a number of bytes * alongside non-bytes unit + * * @param bytes The number of bytes, regardless of unit * @param unit The preferred display unit of this value */ diff --git a/src/main/java/io/airlift/units/MaxDataSize.java b/src/main/java/io/airlift/units/MaxDataSize.java index a39745a..b6ea6b6 100644 --- a/src/main/java/io/airlift/units/MaxDataSize.java +++ b/src/main/java/io/airlift/units/MaxDataSize.java @@ -13,8 +13,8 @@ */ package io.airlift.units; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Retention; diff --git a/src/main/java/io/airlift/units/MaxDataSizeValidator.java b/src/main/java/io/airlift/units/MaxDataSizeValidator.java index e71b9a7..e396b54 100644 --- a/src/main/java/io/airlift/units/MaxDataSizeValidator.java +++ b/src/main/java/io/airlift/units/MaxDataSizeValidator.java @@ -13,8 +13,8 @@ */ package io.airlift.units; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class MaxDataSizeValidator implements ConstraintValidator diff --git a/src/main/java/io/airlift/units/MaxDuration.java b/src/main/java/io/airlift/units/MaxDuration.java index 223aa3d..fc21259 100644 --- a/src/main/java/io/airlift/units/MaxDuration.java +++ b/src/main/java/io/airlift/units/MaxDuration.java @@ -15,8 +15,8 @@ */ package io.airlift.units; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Retention; diff --git a/src/main/java/io/airlift/units/MaxDurationValidator.java b/src/main/java/io/airlift/units/MaxDurationValidator.java index f27b964..9d10a36 100644 --- a/src/main/java/io/airlift/units/MaxDurationValidator.java +++ b/src/main/java/io/airlift/units/MaxDurationValidator.java @@ -15,8 +15,8 @@ */ package io.airlift.units; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class MaxDurationValidator implements ConstraintValidator diff --git a/src/main/java/io/airlift/units/MinDataSize.java b/src/main/java/io/airlift/units/MinDataSize.java index 6f9c5ca..16ce4af 100644 --- a/src/main/java/io/airlift/units/MinDataSize.java +++ b/src/main/java/io/airlift/units/MinDataSize.java @@ -13,8 +13,8 @@ */ package io.airlift.units; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Retention; diff --git a/src/main/java/io/airlift/units/MinDataSizeValidator.java b/src/main/java/io/airlift/units/MinDataSizeValidator.java index 7251939..0059d56 100644 --- a/src/main/java/io/airlift/units/MinDataSizeValidator.java +++ b/src/main/java/io/airlift/units/MinDataSizeValidator.java @@ -13,8 +13,8 @@ */ package io.airlift.units; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class MinDataSizeValidator implements ConstraintValidator diff --git a/src/main/java/io/airlift/units/MinDuration.java b/src/main/java/io/airlift/units/MinDuration.java index a080d08..a3462dc 100644 --- a/src/main/java/io/airlift/units/MinDuration.java +++ b/src/main/java/io/airlift/units/MinDuration.java @@ -15,8 +15,8 @@ */ package io.airlift.units; -import javax.validation.Constraint; -import javax.validation.Payload; +import jakarta.validation.Constraint; +import jakarta.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Retention; diff --git a/src/main/java/io/airlift/units/MinDurationValidator.java b/src/main/java/io/airlift/units/MinDurationValidator.java index 28cb3dd..d943bd4 100644 --- a/src/main/java/io/airlift/units/MinDurationValidator.java +++ b/src/main/java/io/airlift/units/MinDurationValidator.java @@ -15,8 +15,8 @@ */ package io.airlift.units; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; public class MinDurationValidator implements ConstraintValidator diff --git a/src/test/java/io/airlift/units/ConstraintValidatorAssert.java b/src/test/java/io/airlift/units/ConstraintValidatorAssert.java index 9625a89..94ec558 100644 --- a/src/test/java/io/airlift/units/ConstraintValidatorAssert.java +++ b/src/test/java/io/airlift/units/ConstraintValidatorAssert.java @@ -13,12 +13,11 @@ */ package io.airlift.units; +import jakarta.validation.ClockProvider; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; import org.assertj.core.api.AbstractAssert; -import javax.validation.ClockProvider; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - import java.lang.annotation.Annotation; final class ConstraintValidatorAssert diff --git a/src/test/java/io/airlift/units/MockMaxDataSize.java b/src/test/java/io/airlift/units/MockMaxDataSize.java index 07c5651..a204729 100644 --- a/src/test/java/io/airlift/units/MockMaxDataSize.java +++ b/src/test/java/io/airlift/units/MockMaxDataSize.java @@ -13,7 +13,7 @@ */ package io.airlift.units; -import javax.validation.Payload; +import jakarta.validation.Payload; import java.lang.annotation.Annotation; diff --git a/src/test/java/io/airlift/units/MockMaxDuration.java b/src/test/java/io/airlift/units/MockMaxDuration.java index bba5dc2..dd8bea8 100644 --- a/src/test/java/io/airlift/units/MockMaxDuration.java +++ b/src/test/java/io/airlift/units/MockMaxDuration.java @@ -15,7 +15,7 @@ */ package io.airlift.units; -import javax.validation.Payload; +import jakarta.validation.Payload; import java.lang.annotation.Annotation; diff --git a/src/test/java/io/airlift/units/MockMinDataSize.java b/src/test/java/io/airlift/units/MockMinDataSize.java index 591a6c9..3d58611 100644 --- a/src/test/java/io/airlift/units/MockMinDataSize.java +++ b/src/test/java/io/airlift/units/MockMinDataSize.java @@ -13,7 +13,7 @@ */ package io.airlift.units; -import javax.validation.Payload; +import jakarta.validation.Payload; import java.lang.annotation.Annotation; diff --git a/src/test/java/io/airlift/units/MockMinDuration.java b/src/test/java/io/airlift/units/MockMinDuration.java index a20e682..2b3b470 100644 --- a/src/test/java/io/airlift/units/MockMinDuration.java +++ b/src/test/java/io/airlift/units/MockMinDuration.java @@ -15,7 +15,7 @@ */ package io.airlift.units; -import javax.validation.Payload; +import jakarta.validation.Payload; import java.lang.annotation.Annotation; diff --git a/src/test/java/io/airlift/units/TestDataSizeValidator.java b/src/test/java/io/airlift/units/TestDataSizeValidator.java index c239c56..6729689 100644 --- a/src/test/java/io/airlift/units/TestDataSizeValidator.java +++ b/src/test/java/io/airlift/units/TestDataSizeValidator.java @@ -13,29 +13,21 @@ */ package io.airlift.units; -import org.apache.bval.jsr.ApacheValidationProvider; +import jakarta.validation.ValidationException; import org.testng.annotations.Test; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.ValidationException; -import javax.validation.Validator; - import java.util.Optional; -import java.util.Set; +import static io.airlift.testing.ValidationAssertions.assertFailsValidation; +import static io.airlift.testing.ValidationAssertions.assertValidates; import static io.airlift.units.ConstraintValidatorAssert.assertThat; import static io.airlift.units.DataSize.Unit.GIGABYTE; import static io.airlift.units.DataSize.Unit.KILOBYTE; import static io.airlift.units.DataSize.Unit.MEGABYTE; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.testng.Assert.assertTrue; public class TestDataSizeValidator { - private static final Validator VALIDATOR = Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory().getValidator(); - @Test public void testMaxDataSizeValidator() { @@ -68,117 +60,82 @@ public void testMinDataSizeValidator() @Test public void testAllowsNullMinAnnotation() { - VALIDATOR.validate(new NullMinAnnotation()); + assertValidates(new NullMinAnnotation()); } @Test public void testAllowsNullMaxAnnotation() { - VALIDATOR.validate(new NullMaxAnnotation()); + assertValidates(new NullMaxAnnotation()); } @Test public void testDetectsBrokenMinAnnotation() { - assertThatThrownBy(() -> VALIDATOR.validate(new BrokenMinAnnotation())) + assertThatThrownBy(() -> assertValidates(new BrokenMinAnnotation())) .isInstanceOf(ValidationException.class) + .hasMessage("HV000032: Unable to initialize io.airlift.units.MinDataSizeValidator.") .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasMessage("java.lang.IllegalArgumentException: size is not a valid data size string: broken"); + .hasRootCauseMessage("size is not a valid data size string: broken"); - assertThatThrownBy(() -> VALIDATOR.validate(new MinAnnotationOnOptional())) + assertThatThrownBy(() -> assertValidates(new MinAnnotationOnOptional())) .isInstanceOf(ValidationException.class) - .hasMessage("No validator found for (composition) constraint @MinDataSize declared on \"public java.util.Optional io.airlift.units.TestDataSizeValidator$MinAnnotationOnOptional.getConstrainedByMin()\" for validated type \"java.util.Optional\""); + .hasMessageContaining("No validator could be found for constraint 'io.airlift.units.MinDataSize' validating type 'java.util.Optional'. Check configuration for 'constrainedByMin'"); - assertThatThrownBy(() -> VALIDATOR.validate(new BrokenOptionalMinAnnotation())) + assertThatThrownBy(() -> assertValidates(new BrokenOptionalMinAnnotation())) .isInstanceOf(ValidationException.class) + .hasMessage("HV000032: Unable to initialize io.airlift.units.MinDataSizeValidator.") .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasMessage("java.lang.IllegalArgumentException: size is not a valid data size string: broken"); + .hasRootCauseMessage("size is not a valid data size string: broken"); } @Test public void testDetectsBrokenMaxAnnotation() { - assertThatThrownBy(() -> VALIDATOR.validate(new BrokenMaxAnnotation())) + assertThatThrownBy(() -> assertValidates(new BrokenMaxAnnotation())) .isInstanceOf(ValidationException.class) + .hasMessage("HV000032: Unable to initialize io.airlift.units.MaxDataSizeValidator.") .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasMessage("java.lang.IllegalArgumentException: size is not a valid data size string: broken"); + .hasRootCauseMessage("size is not a valid data size string: broken"); - assertThatThrownBy(() -> VALIDATOR.validate(new MaxAnnotationOnOptional())) + assertThatThrownBy(() -> assertValidates(new MaxAnnotationOnOptional())) .isInstanceOf(ValidationException.class) - .hasMessage("No validator found for (composition) constraint @MaxDataSize declared on \"public java.util.Optional io.airlift.units.TestDataSizeValidator$MaxAnnotationOnOptional.getConstrainedByMin()\" for validated type \"java.util.Optional\""); + .hasMessageContaining("No validator could be found for constraint 'io.airlift.units.MaxDataSize' validating type 'java.util.Optional'. Check configuration for 'constrainedByMin'"); - assertThatThrownBy(() -> VALIDATOR.validate(new BrokenOptionalMaxAnnotation())) + assertThatThrownBy(() -> assertValidates(new BrokenOptionalMaxAnnotation())) .isInstanceOf(ValidationException.class) + .hasMessage("HV000032: Unable to initialize io.airlift.units.MaxDataSizeValidator.") .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasMessage("java.lang.IllegalArgumentException: size is not a valid data size string: broken"); + .hasRootCauseMessage("size is not a valid data size string: broken"); } @Test public void testPassesValidation() { - assertTrue(VALIDATOR.validate(new ConstrainedDataSize(new DataSize(7, MEGABYTE))).isEmpty()); - - assertThat(VALIDATOR.validate(new ConstrainedOptionalDataSize(Optional.of(new DataSize(7, MEGABYTE))))).isEmpty(); - - assertThat(VALIDATOR.validate(new ConstrainedOptionalDataSize(Optional.empty()))).isEmpty(); - - assertThat(VALIDATOR.validate(new ConstrainedOptionalDataSize(null))).isEmpty(); + assertValidates(new ConstrainedDataSize(new DataSize(7, MEGABYTE))); + assertValidates(new ConstrainedOptionalDataSize(Optional.of(new DataSize(7, MEGABYTE)))); + assertValidates(new ConstrainedOptionalDataSize(Optional.empty())); + assertValidates(new ConstrainedOptionalDataSize(null)); } @Test public void testFailsMaxDataSizeConstraint() { - Set> violations = VALIDATOR.validate(new ConstrainedDataSize(new DataSize(11, MEGABYTE))); - assertThat(violations).hasSize(2); - assertThat(violations) - .extracting(violation -> violation.getConstraintDescriptor().getAnnotation()) - .allMatch(MaxDataSize.class::isInstance); - assertThat(violations) - .extracting(violation -> violation.getPropertyPath().toString()) - .containsOnly("constrainedByMax", "constrainedByMinAndMax"); - assertThat(violations) - .extracting(ConstraintViolation::getMessage) - .containsOnly("must be less than or equal to 10000kB", "must be less than or equal to 10MB"); - - violations = VALIDATOR.validate(new ConstrainedOptionalDataSize(Optional.of(new DataSize(11, MEGABYTE)))); - assertThat(violations).hasSize(2); - assertThat(violations) - .extracting(violation -> violation.getConstraintDescriptor().getAnnotation()) - .allMatch(MaxDataSize.class::isInstance); - assertThat(violations) - .extracting(violation -> violation.getPropertyPath().toString()) - .containsOnly("constrainedByMax", "constrainedByMinAndMax"); - assertThat(violations) - .extracting(ConstraintViolation::getMessage) - .containsOnly("must be less than or equal to 10000kB", "must be less than or equal to 10MB"); + assertFailsValidation(new ConstrainedDataSize(new DataSize(11, MEGABYTE)), "constrainedByMinAndMax", "must be less than or equal to 10000kB", MaxDataSize.class); + assertFailsValidation(new ConstrainedDataSize(new DataSize(11, MEGABYTE)), "constrainedByMax", "must be less than or equal to 10MB", MaxDataSize.class); + + assertFailsValidation(new ConstrainedOptionalDataSize(Optional.of(new DataSize(11, MEGABYTE))), "constrainedByMinAndMax", "must be less than or equal to 10000kB", MaxDataSize.class); + assertFailsValidation(new ConstrainedOptionalDataSize(Optional.of(new DataSize(11, MEGABYTE))), "constrainedByMax", "must be less than or equal to 10MB", MaxDataSize.class); } @Test public void testFailsMinDataSizeConstraint() { - Set> violations = VALIDATOR.validate(new ConstrainedDataSize(new DataSize(1, MEGABYTE))); - assertThat(violations).hasSize(2); - assertThat(violations) - .extracting(violation -> violation.getConstraintDescriptor().getAnnotation()) - .allMatch(MinDataSize.class::isInstance); - assertThat(violations) - .extracting(violation -> violation.getPropertyPath().toString()) - .containsOnly("constrainedByMin", "constrainedByMinAndMax"); - assertThat(violations) - .extracting(ConstraintViolation::getMessage) - .containsOnly("must be greater than or equal to 5MB", "must be greater than or equal to 5000kB"); - - violations = VALIDATOR.validate(new ConstrainedOptionalDataSize(Optional.of(new DataSize(1, MEGABYTE)))); - assertThat(violations).hasSize(2); - assertThat(violations) - .extracting(violation -> violation.getConstraintDescriptor().getAnnotation()) - .allMatch(MinDataSize.class::isInstance); - assertThat(violations) - .extracting(violation -> violation.getPropertyPath().toString()) - .containsOnly("constrainedByMin", "constrainedByMinAndMax"); - assertThat(violations) - .extracting(ConstraintViolation::getMessage) - .containsOnly("must be greater than or equal to 5MB", "must be greater than or equal to 5000kB"); + assertFailsValidation(new ConstrainedDataSize(new DataSize(1, MEGABYTE)), "constrainedByMin", "must be greater than or equal to 5MB", MinDataSize.class); + assertFailsValidation(new ConstrainedDataSize(new DataSize(1, MEGABYTE)), "constrainedByMinAndMax", "must be greater than or equal to 5000kB", MinDataSize.class); + + assertFailsValidation(new ConstrainedOptionalDataSize(Optional.of(new DataSize(1, MEGABYTE))), "constrainedByMin", "must be greater than or equal to 5MB", MinDataSize.class); + assertFailsValidation(new ConstrainedOptionalDataSize(Optional.of(new DataSize(1, MEGABYTE))), "constrainedByMinAndMax", "must be greater than or equal to 5000kB", MinDataSize.class); } @SuppressWarnings("UnusedDeclaration") @@ -270,7 +227,7 @@ public DataSize getConstrainedByMin() public static class BrokenMaxAnnotation { @SuppressWarnings("UnusedDeclaration") - @MinDataSize("broken") + @MaxDataSize("broken") public DataSize getConstrainedByMin() { return new DataSize(32, KILOBYTE); diff --git a/src/test/java/io/airlift/units/TestDurationValidator.java b/src/test/java/io/airlift/units/TestDurationValidator.java index f8caa27..c97d65a 100644 --- a/src/test/java/io/airlift/units/TestDurationValidator.java +++ b/src/test/java/io/airlift/units/TestDurationValidator.java @@ -15,26 +15,19 @@ */ package io.airlift.units; -import org.apache.bval.jsr.ApacheValidationProvider; +import jakarta.validation.ValidationException; import org.testng.annotations.Test; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.ValidationException; -import javax.validation.Validator; - import java.util.Optional; -import java.util.Set; import java.util.concurrent.TimeUnit; +import static io.airlift.testing.ValidationAssertions.assertFailsValidation; +import static io.airlift.testing.ValidationAssertions.assertValidates; import static io.airlift.units.ConstraintValidatorAssert.assertThat; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; public class TestDurationValidator { - private static final Validator VALIDATOR = Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory().getValidator(); - @Test public void testMaxDurationValidator() { @@ -60,117 +53,82 @@ public void testMinDurationValidator() @Test public void testAllowsNullMinAnnotation() { - VALIDATOR.validate(new NullMinAnnotation()); + assertValidates(new NullMinAnnotation()); } @Test public void testAllowsNullMaxAnnotation() { - VALIDATOR.validate(new NullMaxAnnotation()); + assertValidates(new NullMaxAnnotation()); } @Test public void testDetectsBrokenMinAnnotation() { - assertThatThrownBy(() -> VALIDATOR.validate(new BrokenMinAnnotation())) + assertThatThrownBy(() -> assertValidates(new BrokenMinAnnotation())) .isInstanceOf(ValidationException.class) + .hasMessage("HV000032: Unable to initialize io.airlift.units.MinDurationValidator.") .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasMessage("java.lang.IllegalArgumentException: duration is not a valid data duration string: broken"); + .hasRootCauseMessage("duration is not a valid data duration string: broken"); - assertThatThrownBy(() -> VALIDATOR.validate(new MinAnnotationOnOptional())) + assertThatThrownBy(() -> assertValidates(new MinAnnotationOnOptional())) .isInstanceOf(ValidationException.class) - .hasMessage("No validator found for (composition) constraint @MinDuration declared on \"public java.util.Optional io.airlift.units.TestDurationValidator$MinAnnotationOnOptional.getConstrainedByMin()\" for validated type \"java.util.Optional\""); + .hasMessageContaining("No validator could be found for constraint 'io.airlift.units.MinDuration' validating type 'java.util.Optional'. Check configuration for 'constrainedByMin'"); - assertThatThrownBy(() -> VALIDATOR.validate(new BrokenOptionalMinAnnotation())) + assertThatThrownBy(() -> assertValidates(new BrokenOptionalMinAnnotation())) .isInstanceOf(ValidationException.class) + .hasMessage("HV000032: Unable to initialize io.airlift.units.MinDurationValidator.") .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasMessage("java.lang.IllegalArgumentException: duration is not a valid data duration string: broken"); + .hasRootCauseMessage("duration is not a valid data duration string: broken"); } @Test public void testDetectsBrokenMaxAnnotation() { - assertThatThrownBy(() -> VALIDATOR.validate(new BrokenMaxAnnotation())) + assertThatThrownBy(() -> assertValidates(new BrokenMaxAnnotation())) .isInstanceOf(ValidationException.class) + .hasMessage("HV000032: Unable to initialize io.airlift.units.MinDurationValidator.") .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasMessage("java.lang.IllegalArgumentException: duration is not a valid data duration string: broken"); + .hasRootCauseMessage("duration is not a valid data duration string: broken"); - assertThatThrownBy(() -> VALIDATOR.validate(new MaxAnnotationOnOptional())) + assertThatThrownBy(() -> assertValidates(new MaxAnnotationOnOptional())) .isInstanceOf(ValidationException.class) - .hasMessage("No validator found for (composition) constraint @MaxDuration declared on \"public java.util.Optional io.airlift.units.TestDurationValidator$MaxAnnotationOnOptional.getConstrainedByMin()\" for validated type \"java.util.Optional\""); + .hasMessageContaining("No validator could be found for constraint 'io.airlift.units.MaxDuration' validating type 'java.util.Optional'. Check configuration for 'constrainedByMin'"); - assertThatThrownBy(() -> VALIDATOR.validate(new BrokenOptionalMaxAnnotation())) + assertThatThrownBy(() -> assertValidates(new BrokenOptionalMaxAnnotation())) .isInstanceOf(ValidationException.class) + .hasMessage("HV000032: Unable to initialize io.airlift.units.MaxDurationValidator.") .hasRootCauseInstanceOf(IllegalArgumentException.class) - .hasMessage("java.lang.IllegalArgumentException: duration is not a valid data duration string: broken"); + .hasRootCauseMessage("duration is not a valid data duration string: broken"); } @Test public void testPassesValidation() { - assertThat(VALIDATOR.validate(new ConstrainedDuration(new Duration(7, TimeUnit.SECONDS)))).isEmpty(); - - assertThat(VALIDATOR.validate(new ConstrainedOptionalDuration(Optional.of(new Duration(7, TimeUnit.SECONDS))))).isEmpty(); - - assertThat(VALIDATOR.validate(new ConstrainedOptionalDuration(Optional.empty()))).isEmpty(); - - assertThat(VALIDATOR.validate(new ConstrainedOptionalDuration(null))).isEmpty(); + assertValidates(new ConstrainedDuration(new Duration(7, TimeUnit.SECONDS))); + assertValidates(new ConstrainedOptionalDuration(Optional.of(new Duration(7, TimeUnit.SECONDS)))); + assertValidates(new ConstrainedOptionalDuration(Optional.empty())); + assertValidates(new ConstrainedOptionalDuration(null)); } @Test public void testFailsMaxDurationConstraint() { - Set> violations = VALIDATOR.validate(new ConstrainedDuration(new Duration(11, TimeUnit.SECONDS))); - assertThat(violations).hasSize(2); - assertThat(violations) - .extracting(violation -> violation.getConstraintDescriptor().getAnnotation()) - .allMatch(MaxDuration.class::isInstance); - assertThat(violations) - .extracting(violation -> violation.getPropertyPath().toString()) - .containsOnly("constrainedByMax", "constrainedByMinAndMax"); - assertThat(violations) - .extracting(ConstraintViolation::getMessage) - .containsOnly("must be less than or equal to 10s", "must be less than or equal to 10000ms"); - - violations = VALIDATOR.validate(new ConstrainedOptionalDuration(Optional.of(new Duration(11, TimeUnit.SECONDS)))); - assertThat(violations).hasSize(2); - assertThat(violations) - .extracting(violation -> violation.getConstraintDescriptor().getAnnotation()) - .allMatch(MaxDuration.class::isInstance); - assertThat(violations) - .extracting(violation -> violation.getPropertyPath().toString()) - .containsOnly("constrainedByMax", "constrainedByMinAndMax"); - assertThat(violations) - .extracting(ConstraintViolation::getMessage) - .containsOnly("must be less than or equal to 10s", "must be less than or equal to 10000ms"); + assertFailsValidation(new ConstrainedDuration(new Duration(11, TimeUnit.SECONDS)), "constrainedByMax", "must be less than or equal to 10s", MaxDuration.class); + assertFailsValidation(new ConstrainedDuration(new Duration(11, TimeUnit.SECONDS)), "constrainedByMinAndMax", "must be less than or equal to 10000ms", MaxDuration.class); + + assertFailsValidation(new ConstrainedOptionalDuration(Optional.of(new Duration(11, TimeUnit.SECONDS))), "constrainedByMax", "must be less than or equal to 10s", MaxDuration.class); + assertFailsValidation(new ConstrainedOptionalDuration(Optional.of(new Duration(11, TimeUnit.SECONDS))), "constrainedByMinAndMax", "must be less than or equal to 10000ms", MaxDuration.class); } @Test public void testFailsMinDurationConstraint() { - Set> violations = VALIDATOR.validate(new ConstrainedDuration(new Duration(1, TimeUnit.SECONDS))); - assertThat(violations).hasSize(2); - assertThat(violations) - .extracting(violation -> violation.getConstraintDescriptor().getAnnotation()) - .allMatch(MinDuration.class::isInstance); - assertThat(violations) - .extracting(violation -> violation.getPropertyPath().toString()) - .containsOnly("constrainedByMin", "constrainedByMinAndMax"); - assertThat(violations) - .extracting(ConstraintViolation::getMessage) - .containsOnly("must be greater than or equal to 5000ms", "must be greater than or equal to 5s"); - - violations = VALIDATOR.validate(new ConstrainedOptionalDuration(Optional.of(new Duration(1, TimeUnit.SECONDS)))); - assertThat(violations).hasSize(2); - assertThat(violations) - .extracting(violation -> violation.getConstraintDescriptor().getAnnotation()) - .allMatch(MinDuration.class::isInstance); - assertThat(violations) - .extracting(violation -> violation.getPropertyPath().toString()) - .containsOnly("constrainedByMin", "constrainedByMinAndMax"); - assertThat(violations) - .extracting(ConstraintViolation::getMessage) - .containsOnly("must be greater than or equal to 5000ms", "must be greater than or equal to 5s"); + assertFailsValidation(new ConstrainedDuration(new Duration(1, TimeUnit.SECONDS)), "constrainedByMin", "must be greater than or equal to 5s", MinDuration.class); + assertFailsValidation(new ConstrainedDuration(new Duration(1, TimeUnit.SECONDS)), "constrainedByMinAndMax", "must be greater than or equal to 5000ms", MinDuration.class); + + assertFailsValidation(new ConstrainedOptionalDuration(Optional.of(new Duration(1, TimeUnit.SECONDS))), "constrainedByMin", "must be greater than or equal to 5s", MinDuration.class); + assertFailsValidation(new ConstrainedOptionalDuration(Optional.of(new Duration(1, TimeUnit.SECONDS))), "constrainedByMinAndMax", "must be greater than or equal to 5000ms", MinDuration.class); } @SuppressWarnings("UnusedDeclaration")