DateTimeExceptionHandlingTest.java
package tools.jackson.databind.ext.javatime.deser;
import java.time.*;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.*;
import tools.jackson.databind.ext.javatime.DateTimeParseException;
import tools.jackson.databind.ext.javatime.DateTimeTestBase;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests for proper wrapping of {@link DateTimeException} and
* {@link ArithmeticException} into {@link DateTimeParseException} when deserializing
* java.time types.
*/
public class DateTimeExceptionHandlingTest extends DateTimeTestBase
{
private final ObjectMapper MAPPER = newMapper();
/*
/**********************************************************
/* Test for LocalDateTime - invalid date
/**********************************************************
*/
@Test
public void testLocalDateTimeInvalidDate() throws Exception
{
// February 30 is invalid
ObjectReader r = MAPPER.readerFor(LocalDateTime.class);
try {
r.readValue("[2023,2,30,12,30]");
fail("Should not pass with invalid date");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
assertThat(e).hasMessageContaining("Failed to deserialize");
assertThat(e).hasMessageContaining("[2023,2,30,12,30]");
}
}
@Test
public void testLocalDateTimeInvalidMonth() throws Exception
{
// Month 13 is invalid
ObjectReader r = MAPPER.readerFor(LocalDateTime.class);
try {
r.readValue("[2023,13,15,12,30]");
fail("Should not pass with invalid month");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
}
}
@Test
public void testLocalDateTimeInvalidTime() throws Exception
{
// Hour 25 is invalid
ObjectReader r = MAPPER.readerFor(LocalDateTime.class);
try {
r.readValue("[2023,2,15,25,30]");
fail("Should not pass with invalid hour");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
}
}
@Test
public void testLocalDateTimeInvalidDateString() throws Exception
{
// February 30 is invalid - string format
ObjectReader r = MAPPER.readerFor(LocalDateTime.class);
try {
r.readValue("\"2025-02-30T12:00:00\"");
fail("Should not pass with invalid date string");
} catch (DatabindException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
}
}
/*
/**********************************************************
/* Test for LocalDate - invalid date
/**********************************************************
*/
@Test
public void testLocalDateInvalidDate() throws Exception
{
// February 30 is invalid
ObjectReader r = MAPPER.readerFor(LocalDate.class);
try {
r.readValue("[2023,2,30]");
fail("Should not pass with invalid date");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
assertThat(e).hasMessageContaining("Failed to deserialize");
assertThat(e).hasMessageContaining("[2023,2,30]");
}
}
@Test
public void testLocalDateInvalidMonth() throws Exception
{
// Month 0 is invalid
ObjectReader r = MAPPER.readerFor(LocalDate.class);
try {
r.readValue("[2023,0,15]");
fail("Should not pass with invalid month");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
}
}
@Test
public void testLocalDateInvalidDateString() throws Exception
{
// February 30 is invalid - string format
ObjectReader r = MAPPER.readerFor(LocalDate.class);
try {
r.readValue("\"2025-02-30\"");
fail("Should not pass with invalid date string");
} catch (DatabindException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
}
}
/*
/**********************************************************
/* Test for LocalTime - invalid time
/**********************************************************
*/
@Test
public void testLocalTimeInvalidHour() throws Exception
{
// Hour 25 is invalid
ObjectReader r = MAPPER.readerFor(LocalTime.class);
try {
r.readValue("[25,30]");
fail("Should not pass with invalid hour");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
assertThat(e).hasMessageContaining("Failed to deserialize");
}
}
@Test
public void testLocalTimeInvalidMinute() throws Exception
{
// Minute 60 is invalid
ObjectReader r = MAPPER.readerFor(LocalTime.class);
try {
r.readValue("[12,60]");
fail("Should not pass with invalid minute");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
}
}
@Test
public void testLocalTimeInvalidMinuteString() throws Exception
{
// Minute 69 is invalid - string format
ObjectReader r = MAPPER.readerFor(LocalTime.class);
try {
r.readValue("\"12:69:00\"");
fail("Should not pass with invalid minute string");
} catch (DatabindException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
}
}
/*
/**********************************************************
/* Test for MonthDay - invalid date
/**********************************************************
*/
@Test
public void testMonthDayInvalidDate() throws Exception
{
// February 30 is invalid
ObjectReader r = MAPPER.readerFor(MonthDay.class);
try {
r.readValue("[2,30]");
fail("Should not pass with invalid date for MonthDay");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
assertThat(e).hasMessageContaining("Failed to deserialize");
}
}
@Test
public void testMonthDayInvalidMonth() throws Exception
{
// Month 13 is invalid
ObjectReader r = MAPPER.readerFor(MonthDay.class);
try {
r.readValue("[13,15]");
fail("Should not pass with invalid month");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
}
}
/*
/**********************************************************
/* Test for YearMonth - invalid values
/**********************************************************
*/
@Test
public void testYearMonthInvalidMonth() throws Exception
{
// Month 0 is invalid
ObjectReader r = MAPPER.readerFor(YearMonth.class);
try {
r.readValue("[2023,0]");
fail("Should not pass with invalid month");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
assertThat(e).hasMessageContaining("Failed to deserialize");
}
}
@Test
public void testYearMonthInvalidMonth13() throws Exception
{
// Month 13 is invalid
ObjectReader r = MAPPER.readerFor(YearMonth.class);
try {
r.readValue("[2023,13]");
fail("Should not pass with invalid month");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
}
}
/*
/**********************************************************
/* Test for Year - invalid year
/**********************************************************
*/
@Test
public void testYearOutOfRange() throws Exception
{
// Year value outside valid range
ObjectReader r = MAPPER.readerFor(Year.class);
try {
r.readValue("1000000000");
fail("Should not pass with out of range year");
} catch (DateTimeParseException e) {
assertInstanceOf(DateTimeException.class, e.getCause());
assertThat(e).hasMessageContaining("Failed to deserialize");
}
}
/*
/**********************************************************
/* Test for Duration - arithmetic exceptions
/**********************************************************
*/
@Test
public void testDurationFromLargeDecimal() throws Exception
{
// Very large decimal that could cause ArithmeticException
ObjectReader r = MAPPER.readerFor(Duration.class);
try {
// Using a decimal with extremely large scale that could trigger ArithmeticException
r.readValue("7E2147483647");
fail("Should not pass with extreme decimal value");
} catch (DateTimeParseException e) {
assertInstanceOf(ArithmeticException.class, e.getCause());
assertThat(e).hasMessageContaining("Failed to deserialize");
}
}
@Test
public void testInstantFromLargeDecimal() throws Exception
{
// Very large decimal that could cause ArithmeticException
ObjectReader r = MAPPER.readerFor(Instant.class);
try {
// Using a decimal with extremely large scale that could trigger ArithmeticException
r.readValue("7E2147483647");
fail("Should not pass with extreme decimal value");
} catch (DateTimeParseException e) {
assertInstanceOf(ArithmeticException.class, e.getCause());
assertThat(e).hasMessageContaining("Failed to deserialize");
}
}
}