Skip to content

Commit

Permalink
fix: allow negative and zero time element
Browse files Browse the repository at this point in the history
Passes validation for duration strings with zero or negative durations.
  • Loading branch information
memdal committed Jan 2, 2024
1 parent 781e0fb commit 2741ff7
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 19 deletions.
6 changes: 2 additions & 4 deletions src/main/java/io/vertx/json/schema/impl/Format.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,12 @@ private static boolean testUri(String value) {
private static final Pattern DURATION_A = Pattern.compile("^-?P\\d+([.,]\\d+)?W$");
private static final Pattern DURATIION_B = Pattern.compile("^-?P[\\dYMDTHS]*(\\d[.,]\\d+)?[YMDHS]$");
private static final Pattern DURATIION_C = Pattern.compile("^-?P([.,\\d]+Y)?([.,\\d]+M)?([.,\\d]+D)?(T([.,\\d]+H)?([.,\\d]+M)?([.,\\d]+S)?)?$");
// Matches to true if a duration string is not a zero duration with a minus sign in front.
private static final Pattern DURATION_D = Pattern.compile("^(-.*[1-9].*|[^-].*)$");
private static final Pattern DURATION_D = Pattern.compile("^-?P(-?\\d+(\\.\\d+)?Y)?(-?\\d+(\\.\\d+)?M)?(-?\\d+(\\.\\d+)?W)?(-?\\d+(\\.\\d+)?D)?(T(-?\\d+(\\.\\d+)?H)?(-?\\d+(\\.\\d+)?M)?(-?\\d+(\\.\\d+)?S)?)?$");

private static boolean testDuration(String value) {
return value.length() > 1 &&
value.length() < 80 &&
(DURATION_A.matcher(value).find() || (DURATIION_B.matcher(value).find() && DURATIION_C.matcher(value).find())) &&
(DURATION_D.matcher(value).find());
(DURATION_A.matcher(value).find() || (DURATIION_B.matcher(value).find() && DURATIION_C.matcher(value).find())) || DURATION_D.matcher(value).find();
}

private static final Pattern FASTDATETIME = Pattern.compile("^\\d\\d\\d\\d-[0-1]\\d-[0-3]\\d[t\\s](?:[0-2]\\d:[0-5]\\d:[0-5]\\d|23:59:60)(?:\\.\\d+)?(?:z|[+-]\\d\\d(?::?\\d\\d)?)$", Pattern.CASE_INSENSITIVE);
Expand Down
56 changes: 41 additions & 15 deletions src/test/java/io/vertx/json/schema/ValidationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;

import java.util.function.Consumer;

@ExtendWith(VertxExtension.class)
class ValidationTest {

Expand Down Expand Up @@ -226,7 +228,7 @@ public void testIssue49b() throws JsonSchemaValidationException {
}

@Test
void testNegativeDurationValidation() throws JsonSchemaValidationException {
void testDurationValidation() {

SchemaRepository repository = SchemaRepository.create(new JsonSchemaOptions().setDraft(Draft.DRAFT201909).setBaseUri("app://"));

Expand All @@ -246,19 +248,43 @@ void testNegativeDurationValidation() throws JsonSchemaValidationException {
"}")
));

JsonObject positiveDuration = new JsonObject().put("duration", "P3W");
JsonObject negativeDuration = new JsonObject().put("duration", "-P3W");
JsonObject positiveNullDuration = new JsonObject().put("duration", "P0W");
JsonObject negativeNullDuration = new JsonObject().put("duration", "-PT0S");

repository.validator("acceptable-duration.json").validate(positiveDuration).checkValidity();
repository.validator("acceptable-duration.json").validate(negativeDuration).checkValidity();
repository.validator("acceptable-duration.json").validate(positiveNullDuration).checkValidity();
try {
repository.validator("acceptable-duration.json").validate(negativeNullDuration).checkValidity();
fail("Should have thrown an exception");
} catch (JsonSchemaValidationException e) {
// OK
}
Consumer<String> shouldValidate = duration -> {
try {
repository.validator("acceptable-duration.json").validate(new JsonObject().put("duration", duration)).checkValidity();
} catch (JsonSchemaValidationException ignored) {
fail("Duration " + duration + " should pass validation.");
}
};

Consumer<String> shouldNotValidate = duration -> {
try {
repository.validator("acceptable-duration.json").validate(new JsonObject().put("duration", duration)).checkValidity();
fail("Duration " + duration + " should not pass validation.");
} catch (JsonSchemaValidationException ignored) {}
};

shouldValidate.accept("PT0S");
shouldValidate.accept("-PT0S");
shouldValidate.accept("PT-0S");
shouldValidate.accept("P1Y");
shouldValidate.accept("P1M");
shouldValidate.accept("P1W");
shouldValidate.accept("P1D");
shouldValidate.accept("PT1H");
shouldValidate.accept("PT1M");
shouldValidate.accept("PT1S");
shouldValidate.accept("P1Y2M");
shouldValidate.accept("P1M2W");
shouldValidate.accept("P1W2D");
shouldNotValidate.accept("P1M2Y");
shouldNotValidate.accept("P1W2M");
shouldNotValidate.accept("P1D2W");
shouldValidate.accept("PT1H2M");
shouldValidate.accept("PT1M2S");
shouldNotValidate.accept("PT1M2H");
shouldNotValidate.accept("PT1S2M");
shouldValidate.accept("P1Y2M3W4DT5H6M7S");
shouldValidate.accept("P-1Y-2M-3W-4DT-5H-6M-7S");
shouldValidate.accept("-P-1.0Y2.2M-33.4W-4.2DT5H-7S");
}
}

0 comments on commit 2741ff7

Please sign in to comment.