From d7c8bba10feb25d54f8e6bcc8a6c646b21cb84e7 Mon Sep 17 00:00:00 2001 From: Seth Falco Date: Fri, 2 Feb 2024 12:43:01 +0000 Subject: [PATCH] feat: updated existing converters --- .../commons/beanutils2/ConvertUtilsBean.java | 6 + .../converters/CharacterConverter.java | 22 +++- .../converters/DateTimeConverter.java | 22 ++++ .../converters/DurationConverter.java | 2 +- .../beanutils2/converters/EnumConverter.java | 44 ++++++-- .../converters/InstantConverter.java | 62 +++++++++++ .../converters/PeriodConverter.java | 2 +- .../CharacterConverterTestCase.java | 105 +++++++++--------- .../converters/DurationConverterTestCase.java | 42 +++---- .../converters/EnumConverterTestCase.java | 79 +++++++++---- .../converters/InstantConverterTestCase.java | 78 +++++++++++++ .../converters/PeriodConverterTestCase.java | 42 +++---- 12 files changed, 367 insertions(+), 139 deletions(-) create mode 100644 src/main/java/org/apache/commons/beanutils2/converters/InstantConverter.java create mode 100644 src/test/java/org/apache/commons/beanutils2/converters/InstantConverterTestCase.java diff --git a/src/main/java/org/apache/commons/beanutils2/ConvertUtilsBean.java b/src/main/java/org/apache/commons/beanutils2/ConvertUtilsBean.java index 4cc322bfa..43b6a72b6 100644 --- a/src/main/java/org/apache/commons/beanutils2/ConvertUtilsBean.java +++ b/src/main/java/org/apache/commons/beanutils2/ConvertUtilsBean.java @@ -30,6 +30,7 @@ import java.nio.file.Path; import java.sql.Timestamp; import java.time.Duration; +import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; @@ -66,6 +67,7 @@ import org.apache.commons.beanutils2.converters.FileConverter; import org.apache.commons.beanutils2.converters.FloatConverter; import org.apache.commons.beanutils2.converters.InetAddressConverter; +import org.apache.commons.beanutils2.converters.InstantConverter; import org.apache.commons.beanutils2.converters.IntegerConverter; import org.apache.commons.beanutils2.converters.LocalDateConverter; import org.apache.commons.beanutils2.converters.LocalDateTimeConverter; @@ -128,6 +130,7 @@ *
  • java.sql.Date (no default value)
  • *
  • java.sql.Time (no default value)
  • *
  • java.sql.Timestamp (no default value)
  • + *
  • java.time.Instant (no default value)
  • *
  • java.time.LocalDate (no default value)
  • *
  • java.time.LocalDateTime (no default value)
  • *
  • java.time.LocalTime (no default value)
  • @@ -566,6 +569,7 @@ private void registerArrays(final boolean throwException, final int defaultArray registerArrayConverter(Dimension.class, new DimensionConverter(), throwException, defaultArraySize); registerArrayConverter(File.class, new FileConverter(), throwException, defaultArraySize); registerArrayConverter(InetAddress.class, new InetAddressConverter(), throwException, defaultArraySize); + registerArrayConverter(Instant.class, new InstantConverter(), throwException, defaultArraySize); registerArrayConverter(Path.class, new PathConverter(), throwException, defaultArraySize); registerArrayConverter(java.sql.Date.class, new SqlDateConverter(), throwException, defaultArraySize); registerArrayConverter(java.sql.Time.class, new SqlTimeConverter(), throwException, defaultArraySize); @@ -602,6 +606,7 @@ private void registerArrays(final boolean throwException, final int defaultArray *
  • {@link java.util.Date.class} - {@link DateConverter}
  • *
  • {@link java.util.Calendar.class} - {@link CalendarConverter}
  • *
  • {@code File.class} - {@link FileConverter}
  • + *
  • {@code Instant.class} - {@link InstantConverter}
  • *
  • {@code Path.class} - {@link PathConverter}
  • *
  • {@link java.sql.Date.class} - {@link SqlDateConverter}
  • *
  • {@link java.sql.Time.class} - {@link SqlTimeConverter}
  • @@ -637,6 +642,7 @@ private void registerOther(final boolean throwException) { register(Calendar.class, throwException ? new CalendarConverter() : new CalendarConverter(null)); register(File.class, throwException ? new FileConverter() : new FileConverter(null)); register(InetAddress.class, throwException ? new InetAddressConverter() : new InetAddressConverter(null)); + register(Instant.class, throwException ? new InstantConverter() : new InstantConverter(null)); register(Path.class, throwException ? new PathConverter() : new PathConverter(null)); register(java.sql.Date.class, throwException ? new SqlDateConverter() : new SqlDateConverter(null)); register(java.sql.Time.class, throwException ? new SqlTimeConverter() : new SqlTimeConverter(null)); diff --git a/src/main/java/org/apache/commons/beanutils2/converters/CharacterConverter.java b/src/main/java/org/apache/commons/beanutils2/converters/CharacterConverter.java index e702b5322..c0585892f 100644 --- a/src/main/java/org/apache/commons/beanutils2/converters/CharacterConverter.java +++ b/src/main/java/org/apache/commons/beanutils2/converters/CharacterConverter.java @@ -22,11 +22,19 @@ *

    * Can be configured to either return a default value or throw a * {@code ConversionException} if a conversion error occurs. + *

    + * + *

    + * Also accepts hexadecimal {@link String strings} if values are prefixed with {@link #HEX_PREFIX}. + *

    * * @since 1.3 */ public final class CharacterConverter extends AbstractConverter { + /** Determines if an input is a hexadecimal {@link String}. */ + private static final String HEX_PREFIX = "0x"; + /** * Constructs a java.lang.Character Converter that throws * a {@code ConversionException} if an error occurs. @@ -84,7 +92,19 @@ protected String convertToString(final Object value) { @Override protected T convertToType(final Class type, final Object value) throws Exception { if (Character.class.equals(type) || Character.TYPE.equals(type)) { - return type.cast(Character.valueOf(value.toString().charAt(0))); + final String stringValue = toString(value); + + if (stringValue.isEmpty()) { + throw new IllegalArgumentException("Value must not be empty"); + } + + if (stringValue.length() > 2 && stringValue.substring(0, 2).equalsIgnoreCase(HEX_PREFIX)) { + final String substring = stringValue.substring(HEX_PREFIX.length()); + final int hex = Integer.parseInt(substring, 16); + return type.cast((char) hex); + } + + return type.cast(stringValue.charAt(0)); } throw conversionException(type, value); diff --git a/src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java b/src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java index f164187d0..1b09cc9f2 100644 --- a/src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java +++ b/src/main/java/org/apache/commons/beanutils2/converters/DateTimeConverter.java @@ -25,6 +25,7 @@ import java.time.OffsetDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAccessor; import java.util.Calendar; import java.util.Date; @@ -152,6 +153,8 @@ protected String convertToString(final Object value) { } else if (value instanceof TemporalAccessor) { // Backstop for other TemporalAccessor implementations. date = Date.from(Instant.from(((TemporalAccessor) value))); + } else if (value instanceof Instant) { + date = Date.from((Instant) value); } String result = null; @@ -188,6 +191,7 @@ protected String convertToString(final Object value) { *
  • {@link java.time.LocalDate}
  • *
  • {@link java.time.LocalDateTime}
  • *
  • {@link java.time.OffsetDateTime}
  • + *
  • {@link java.time.Instant}
  • *
  • {@link java.time.ZonedDateTime}
  • *
  • {@link java.sql.Date}
  • *
  • {@link java.sql.Time}
  • @@ -269,6 +273,11 @@ protected T convertToType(final Class targetType, final Object value) thr return toDate(targetType, date.toInstant().toEpochMilli()); } + if (value instanceof Instant) { + final Instant date = (Instant) value; + return toDate(targetType, date.toEpochMilli()); + } + // Convert all other types to String & handle final String stringValue = toTrim(value); if (stringValue.isEmpty()) { @@ -587,6 +596,10 @@ private T toDate(final Class type, final long value) { return type.cast(offsetDateTime); } + if (type.equals(Instant.class)) { + return type.cast(Instant.ofEpochMilli(value)); + } + // java.util.Calendar if (type.equals(Calendar.class)) { Calendar calendar = null; @@ -620,6 +633,7 @@ private T toDate(final Class type, final long value) { *
  • {@link java.sql.Date}
  • *
  • {@link java.sql.Time}
  • *
  • {@link java.sql.Timestamp}
  • + *
  • {@link java.time.Instant}
  • * *

    * N.B. No default String conversion @@ -663,6 +677,14 @@ private T toDate(final Class type, final String value) { } } + if (type.equals(Instant.class)) { + try { + return type.cast(Instant.parse(value)); + } catch (final DateTimeParseException ex) { + throw new ConversionException("String must be in ISO-8601 format to create a java.time.Instant"); + } + } + final String msg = toString(getClass()) + " does not support default String to '" + toString(type) + "' conversion."; if (log().isWarnEnabled()) { diff --git a/src/main/java/org/apache/commons/beanutils2/converters/DurationConverter.java b/src/main/java/org/apache/commons/beanutils2/converters/DurationConverter.java index e4b396e43..55cd1d6e6 100644 --- a/src/main/java/org/apache/commons/beanutils2/converters/DurationConverter.java +++ b/src/main/java/org/apache/commons/beanutils2/converters/DurationConverter.java @@ -63,7 +63,7 @@ public DurationConverter(final Duration defaultValue) { @Override protected T convertToType(final Class type, final Object value) throws Throwable { if (Duration.class.equals(type)) { - return type.cast(Duration.parse((String.valueOf(value)))); + return type.cast(Duration.parse(toString(value))); } throw conversionException(type, value); diff --git a/src/main/java/org/apache/commons/beanutils2/converters/EnumConverter.java b/src/main/java/org/apache/commons/beanutils2/converters/EnumConverter.java index c8337882f..a75cf10af 100644 --- a/src/main/java/org/apache/commons/beanutils2/converters/EnumConverter.java +++ b/src/main/java/org/apache/commons/beanutils2/converters/EnumConverter.java @@ -16,6 +16,9 @@ */ package org.apache.commons.beanutils2.converters; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * {@link org.apache.commons.beanutils2.Converter} implementation that handles conversion * to and from java.lang.Enum objects. @@ -30,6 +33,11 @@ */ public final class EnumConverter> extends AbstractConverter> { + /** Matches if a given input is an enum string. */ + private static final Pattern ENUM_PATTERN = Pattern.compile( + "((?:[a-z\\d.]+)*)\\.([A-Za-z\\d]+)[#.]([A-Z\\d_]+)" + ); + /** * Constructs a java.lang.Enum Converter that throws * a {@code ConversionException} if an error occurs. @@ -63,15 +71,37 @@ public EnumConverter(final Enum defaultValue) { @Override protected R convertToType(final Class type, final Object value) throws Throwable { if (Enum.class.isAssignableFrom(type)) { - final String enumValue = String.valueOf(value); - final R[] constants = type.getEnumConstants(); - if (constants == null) { - throw conversionException(type, value); + final String stringValue = toString(value); + + try { + return type.cast((Enum) Enum.valueOf((Class) type, stringValue)); + } catch (IllegalArgumentException ex) { + // Continue to check fully qualified name. + } + + Matcher matcher = ENUM_PATTERN.matcher(stringValue); + + if (!matcher.matches()) { + throw new IllegalArgumentException( + "Value doesn't follow Enum naming convention, expecting value like: java.time.DayOfWeek.MONDAY"); } - for (final R candidate : constants) { - if (((Enum)candidate).name().equalsIgnoreCase(enumValue)) { - return candidate; + + String className = matcher.group(1) + "." + matcher.group(2); + + try { + Class classForName = Class.forName(className); + + if (!classForName.isEnum()) { + throw new IllegalArgumentException("Value isn't an enumerated type."); } + + if (!type.isAssignableFrom(classForName)) { + throw new IllegalArgumentException("Class is not the required type."); + } + + return type.cast((Enum) Enum.valueOf(classForName, matcher.group(3))); + } catch (ClassNotFoundException ex) { + throw new IllegalArgumentException("Class \"" + className + "\" doesn't exist.", ex); } } diff --git a/src/main/java/org/apache/commons/beanutils2/converters/InstantConverter.java b/src/main/java/org/apache/commons/beanutils2/converters/InstantConverter.java new file mode 100644 index 000000000..862edb6f1 --- /dev/null +++ b/src/main/java/org/apache/commons/beanutils2/converters/InstantConverter.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.beanutils2.converters; + +import java.time.Instant; + +/** + * {@link org.apache.commons.beanutils2.Converter} implementation that handles conversion + * to and from {@link Instant} objects. + * + *

    + * Can be configured to either return a default value or throw a + * {@code ConversionException} if a conversion error occurs. + *

    + * + * @since 2.0 + * @see Instant + */ +public final class InstantConverter extends DateTimeConverter { + + /** + * Constructs a {@link Instant} Converter that throws a {@code ConversionException} if an + * error occurs. + */ + public InstantConverter() { + super(); + } + + /** + * Constructs a {@link Instant} Converter that returns a default value if an error occurs. + * + * @param defaultValue The default value to be returned if the value to be converted is missing or an error occurs + * converting the value. + */ + public InstantConverter(final Instant defaultValue) { + super(defaultValue); + } + + /** + * Gets the default type this {@code Converter} handles. + * + * @return The default type this {@code Converter} handles. + */ + @Override + protected Class getDefaultType() { + return Instant.class; + } +} diff --git a/src/main/java/org/apache/commons/beanutils2/converters/PeriodConverter.java b/src/main/java/org/apache/commons/beanutils2/converters/PeriodConverter.java index d9ca46bb0..dd64f64d7 100644 --- a/src/main/java/org/apache/commons/beanutils2/converters/PeriodConverter.java +++ b/src/main/java/org/apache/commons/beanutils2/converters/PeriodConverter.java @@ -63,7 +63,7 @@ public PeriodConverter(final Period defaultValue) { @Override protected T convertToType(final Class type, final Object value) throws Throwable { if (Period.class.equals(type)) { - return type.cast(Period.parse((String.valueOf(value)))); + return type.cast(Period.parse(toString(value))); } throw conversionException(type, value); diff --git a/src/test/java/org/apache/commons/beanutils2/converters/CharacterConverterTestCase.java b/src/test/java/org/apache/commons/beanutils2/converters/CharacterConverterTestCase.java index fa5934f89..0a9f955d0 100644 --- a/src/test/java/org/apache/commons/beanutils2/converters/CharacterConverterTestCase.java +++ b/src/test/java/org/apache/commons/beanutils2/converters/CharacterConverterTestCase.java @@ -16,112 +16,107 @@ */ package org.apache.commons.beanutils2.converters; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + import org.apache.commons.beanutils2.ConversionException; import org.apache.commons.beanutils2.Converter; - -import junit.framework.TestCase; -import junit.framework.TestSuite; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; /** * Test Case for the CharacterConverter class. */ -public class CharacterConverterTestCase extends TestCase { - - /** - * Create Test Suite - * - * @return test suite - */ - public static TestSuite suite() { - return new TestSuite(CharacterConverterTestCase.class); - } +class CharacterConverterTestCase { - /** - * Constructs a new Character Converter test case. - * - * @param name Test Name - */ - public CharacterConverterTestCase(final String name) { - super(name); - } + private Converter converter; - /** Sets Up */ - @Override + @BeforeEach public void setUp() throws Exception { + converter = new CharacterConverter(); } - /** Tear Down */ - @Override + @AfterEach public void tearDown() throws Exception { + converter = null; } /** * Tests whether the primitive char class can be passed as target type. */ - public void testConvertToChar() { - final Converter converter = new CharacterConverter(); - assertEquals("Wrong result", Character.valueOf('F'), converter.convert(Character.TYPE, "FOO")); + @Test + void testConvertToChar() { + assertEquals(Character.valueOf('F'), converter.convert(Character.TYPE, "FOO"), "Wrong result"); } /** * Test Conversion to Character */ - public void testConvertToCharacter() { - final Converter converter = new CharacterConverter(); - assertEquals("Character Test", Character.valueOf('N'), converter.convert(Character.class, Character.valueOf('N'))); - assertEquals("String Test", Character.valueOf('F'), converter.convert(Character.class, "FOO")); - assertEquals("Integer Test", Character.valueOf('3'), converter.convert(Character.class, Integer.valueOf(321))); + @Test + void testConvertToCharacter() { + assertEquals(Character.valueOf('N'), converter.convert(Character.class, Character.valueOf('N')), "Character Test"); + assertEquals(Character.valueOf('F'), converter.convert(Character.class, "FOO"), "String Test"); + assertEquals(Character.valueOf('3'), converter.convert(Character.class, Integer.valueOf(321)), "Integer Test"); } /** * Tests a conversion to character for null input if no default value is provided. */ - public void testConvertToCharacterNullNoDefault() { - final Converter converter = new CharacterConverter(); - try { - converter.convert(Character.class, null); - fail("Expected a ConversionException for null value"); - } catch (final Exception e) { - // expected result - } + @Test + void testConvertToCharacterNullNoDefault() { + assertThrows(ConversionException.class, () -> converter.convert(Character.class, null)); } /** * Test Conversion to String */ + @Test @SuppressWarnings("unchecked") // testing raw conversion - public void testConvertToString() { + void testConvertToString() { final Converter converter = new CharacterConverter(); @SuppressWarnings("rawtypes") final Converter raw = converter; - assertEquals("Character Test", "N", raw.convert(String.class, Character.valueOf('N'))); - assertEquals("String Test", "F", raw.convert(String.class, "FOO")); - assertEquals("Integer Test", "3", raw.convert(String.class, Integer.valueOf(321))); - assertEquals("Null Test", null, raw.convert(String.class, null)); + assertEquals("N", raw.convert(String.class, Character.valueOf('N')), "Character Test"); + assertEquals("F", raw.convert(String.class, "FOO"), "String Test"); + assertEquals("3", raw.convert(String.class, Integer.valueOf(321)), "Integer Test"); + assertEquals(null, raw.convert(String.class, null), "Null Test"); } /** * Tries a conversion to an unsupported type. */ @SuppressWarnings("unchecked") // tests failure so allow mismatch - public void testConvertToUnsupportedType() { + @Test + void testConvertToUnsupportedType() { @SuppressWarnings("rawtypes") // tests failure so allow mismatch final Converter converter = new CharacterConverter(); - try { - converter.convert(Integer.class, "Test"); - fail("Could convert to unsupported type!"); - } catch (final ConversionException cex) { - // expected result - } + assertThrows(ConversionException.class, () -> converter.convert(Integer.class, "Test")); } /** * Test Conversion to Character (with default) */ - public void testDefault() { + @Test + void testDefault() { final CharacterConverter converter = new CharacterConverter('C'); - assertEquals("Default Test", Character.valueOf('C'), converter.convert(Character.class, null)); + assertEquals(Character.valueOf('C'), converter.convert(Character.class, null), "Default Test"); + } + + /** + * If a hexadecimal value is provided, we'll convert it to a character if possible. + */ + @Test + void testConvertHexCharacter() { + final Converter converter = new CharacterConverter(); + assertEquals('A', (char) converter.convert(Character.class, "0x41")); + } + + @Test + void testConvertHexSymbol() { + final Converter converter = new CharacterConverter(); + assertEquals('£', (char) converter.convert(Character.class, "0xA3")); } } diff --git a/src/test/java/org/apache/commons/beanutils2/converters/DurationConverterTestCase.java b/src/test/java/org/apache/commons/beanutils2/converters/DurationConverterTestCase.java index 63aeede90..688fcf8bc 100644 --- a/src/test/java/org/apache/commons/beanutils2/converters/DurationConverterTestCase.java +++ b/src/test/java/org/apache/commons/beanutils2/converters/DurationConverterTestCase.java @@ -17,29 +17,24 @@ package org.apache.commons.beanutils2.converters; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + import java.time.Duration; import org.apache.commons.beanutils2.ConversionException; import org.apache.commons.beanutils2.Converter; - -import junit.framework.TestCase; -import junit.framework.TestSuite; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; /** * Test Case for the DurationConverter class. */ -public class DurationConverterTestCase extends TestCase { - - public static TestSuite suite() { - return new TestSuite(DurationConverterTestCase.class); - } +class DurationConverterTestCase { private Converter converter; - public DurationConverterTestCase(final String name) { - super(name); - } - protected Class getExpectedType() { return Duration.class; } @@ -48,17 +43,18 @@ protected Converter makeConverter() { return new DurationConverter(); } - @Override + @BeforeEach public void setUp() throws Exception { converter = makeConverter(); } - @Override + @AfterEach public void tearDown() throws Exception { converter = null; } - public void testSimpleConversion() throws Exception { + @Test + void testSimpleConversion() throws Exception { final String[] message = { "from String", "from String", "from String", "from String", "from String", "from String", "from String", "from String", }; final Object[] input = { "PT20.345S", "PT15M", "PT51H4M" }; @@ -66,24 +62,20 @@ public void testSimpleConversion() throws Exception { final Duration[] expected = { Duration.parse("PT20.345S"), Duration.parse("PT15M"), Duration.parse("P2DT3H4M") }; for (int i = 0; i < expected.length; i++) { - assertEquals(message[i] + " to URI", expected[i], converter.convert(Duration.class, input[i])); - assertEquals(message[i] + " to null type", expected[i], converter.convert(null, input[i])); + assertEquals(expected[i], converter.convert(Duration.class, input[i]), message[i] + " to URI"); + assertEquals(expected[i], converter.convert(null, input[i]), message[i] + " to null type"); } for (int i = 0; i < expected.length; i++) { - assertEquals(input[i] + " to String", input[i], converter.convert(String.class, expected[i])); + assertEquals(input[i], converter.convert(String.class, expected[i]), input[i] + " to String"); } } /** * Tests a conversion to an unsupported type. */ - public void testUnsupportedType() { - try { - converter.convert(Integer.class, "http://www.apache.org"); - fail("Unsupported type could be converted!"); - } catch (final ConversionException cex) { - // expected result - } + @Test + void testUnsupportedType() { + assertThrows(ConversionException.class, () -> converter.convert(Integer.class, "http://www.apache.org")); } } diff --git a/src/test/java/org/apache/commons/beanutils2/converters/EnumConverterTestCase.java b/src/test/java/org/apache/commons/beanutils2/converters/EnumConverterTestCase.java index 8929140b9..51d3b7bad 100644 --- a/src/test/java/org/apache/commons/beanutils2/converters/EnumConverterTestCase.java +++ b/src/test/java/org/apache/commons/beanutils2/converters/EnumConverterTestCase.java @@ -17,31 +17,29 @@ package org.apache.commons.beanutils2.converters; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.time.DayOfWeek; +import java.util.concurrent.TimeUnit; + import org.apache.commons.beanutils2.ConversionException; import org.apache.commons.beanutils2.Converter; - -import junit.framework.TestCase; -import junit.framework.TestSuite; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; /** * Test Case for the EnumConverter class. */ -public class EnumConverterTestCase extends TestCase { +class EnumConverterTestCase { public enum PizzaStatus { ORDERED, READY, DELIVERED; } - public static TestSuite suite() { - return new TestSuite(EnumConverterTestCase.class); - } - private Converter> converter; - public EnumConverterTestCase(final String name) { - super(name); - } - protected Class getExpectedType() { return Enum.class; } @@ -50,17 +48,18 @@ protected Converter> makeConverter() { return new EnumConverter<>(); } - @Override + @BeforeEach public void setUp() throws Exception { converter = makeConverter(); } - @Override + @AfterEach public void tearDown() throws Exception { converter = null; } - public void testSimpleConversion() throws Exception { + @Test + void testSimpleConversion() throws Exception { final String[] message = { "from String", "from String", "from String", "from String", "from String", "from String", "from String", "from String", }; final Object[] input = { "DELIVERED", "ORDERED", "READY" }; @@ -68,23 +67,55 @@ public void testSimpleConversion() throws Exception { final PizzaStatus[] expected = { PizzaStatus.DELIVERED, PizzaStatus.ORDERED, PizzaStatus.READY }; for (int i = 0; i < expected.length; i++) { - assertEquals(message[i] + " to Enum", expected[i], converter.convert(PizzaStatus.class, input[i])); + assertEquals(expected[i], converter.convert(PizzaStatus.class, input[i]), message[i] + " to Enum"); } for (int i = 0; i < expected.length; i++) { - assertEquals(input[i] + " to String", input[i], converter.convert(String.class, expected[i])); + assertEquals(input[i], converter.convert(String.class, expected[i]), input[i] + " to String"); } } /** * Tests a conversion to an unsupported type. */ - public void testUnsupportedType() { - try { - converter.convert(Integer.class, "http://www.apache.org"); - fail("Unsupported type could be converted!"); - } catch (final ConversionException cex) { - // expected result - } + @Test + void testUnsupportedType() { + assertThrows(ConversionException.class, () -> converter.convert(Integer.class, "http://www.apache.org")); + } + + @Test + void testConvertTimeUnit() { + final TimeUnit expected = TimeUnit.NANOSECONDS; + final Enum actual = converter.convert(Enum.class, "java.util.concurrent.TimeUnit.NANOSECONDS"); + + assertEquals(expected, actual); + } + + @Test + void testConvertDayOfWeek() { + final DayOfWeek expected = DayOfWeek.MONDAY; + final DayOfWeek actual = converter.convert(DayOfWeek.class, "java.time.DayOfWeek#MONDAY"); + + assertEquals(expected, actual); + } + + @Test + void testConvertMismatchingEnumType() { + assertThrows(ConversionException.class, () -> converter.convert(TimeUnit.class, "java.time.DayOfWeek#MONDAY")); + } + + @Test + void testBrokenNamingConvention() { + assertThrows(ConversionException.class, () -> converter.convert(Enum.class, "JAVA-TIME-DAYOFWEEK#MONDAY")); + } + + @Test + void testNonEnumClasses() { + assertThrows(ConversionException.class, () -> converter.convert(Enum.class, "java.lang.String#MONDAY")); + } + + @Test + void testNonExistingClasses() { + assertThrows(ConversionException.class, () -> converter.convert(Enum.class, "java.lang.does.not.exist#MONDAY")); } } diff --git a/src/test/java/org/apache/commons/beanutils2/converters/InstantConverterTestCase.java b/src/test/java/org/apache/commons/beanutils2/converters/InstantConverterTestCase.java new file mode 100644 index 000000000..6a767f49c --- /dev/null +++ b/src/test/java/org/apache/commons/beanutils2/converters/InstantConverterTestCase.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.beanutils2.converters; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.time.Instant; +import java.time.Period; + +import org.apache.commons.beanutils2.ConversionException; +import org.apache.commons.beanutils2.Converter; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class InstantConverterTestCase { + + private Converter converter; + + protected Class getExpectedType() { + return Period.class; + } + + protected Converter makeConverter() { + return new InstantConverter(); + } + + @BeforeEach + public void setUp() throws Exception { + converter = makeConverter(); + } + + @AfterEach + public void tearDown() throws Exception { + converter = null; + } + + @Test + void testConvertingMilliseconds() { + final Instant expected = Instant.ofEpochMilli(1596500083605L); + final Instant actual = converter.convert(Instant.class, 1596500083605L); + + assertEquals(expected, actual); + } + + @Test + void testConvertingInstantString() { + final Instant expected = Instant.ofEpochMilli(1196676930000L); + final Instant actual = converter.convert(Instant.class, "2007-12-03T10:15:30.00Z"); + + assertEquals(expected, actual); + } + + @Test + void testText() { + assertThrows(ConversionException.class, () -> converter.convert(Instant.class, "Hello, world!")); + } + + @Test + void testLocalizedNumber() { + assertThrows(ConversionException.class, () -> converter.convert(Instant.class, "200,000,000,000")); + } +} diff --git a/src/test/java/org/apache/commons/beanutils2/converters/PeriodConverterTestCase.java b/src/test/java/org/apache/commons/beanutils2/converters/PeriodConverterTestCase.java index b39ae470a..74df5c387 100644 --- a/src/test/java/org/apache/commons/beanutils2/converters/PeriodConverterTestCase.java +++ b/src/test/java/org/apache/commons/beanutils2/converters/PeriodConverterTestCase.java @@ -17,29 +17,24 @@ package org.apache.commons.beanutils2.converters; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + import java.time.Period; import org.apache.commons.beanutils2.ConversionException; import org.apache.commons.beanutils2.Converter; - -import junit.framework.TestCase; -import junit.framework.TestSuite; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; /** * Test Case for the PeriodConverter class. */ -public class PeriodConverterTestCase extends TestCase { - - public static TestSuite suite() { - return new TestSuite(PeriodConverterTestCase.class); - } +class PeriodConverterTestCase { private Converter converter; - public PeriodConverterTestCase(final String name) { - super(name); - } - protected Class getExpectedType() { return Period.class; } @@ -48,17 +43,18 @@ protected Converter makeConverter() { return new PeriodConverter(); } - @Override + @BeforeEach public void setUp() throws Exception { converter = makeConverter(); } - @Override + @AfterEach public void tearDown() throws Exception { converter = null; } - public void testSimpleConversion() throws Exception { + @Test + void testSimpleConversion() throws Exception { final String[] message = { "from String", "from String", "from String", "from String", "from String", "from String", "from String", "from String", }; final Object[] input = { "P2Y", "P5D", "P1Y2M3D" }; @@ -66,24 +62,20 @@ public void testSimpleConversion() throws Exception { final Period[] expected = { Period.parse("P2Y"), Period.parse("P5D"), Period.parse("P1Y2M3D") }; for (int i = 0; i < expected.length; i++) { - assertEquals(message[i] + " to URI", expected[i], converter.convert(Period.class, input[i])); - assertEquals(message[i] + " to null type", expected[i], converter.convert(null, input[i])); + assertEquals(expected[i], converter.convert(Period.class, input[i]), message[i] + " to URI"); + assertEquals(expected[i], converter.convert(null, input[i]), message[i] + " to null type"); } for (int i = 0; i < expected.length; i++) { - assertEquals(input[i] + " to String", input[i], converter.convert(String.class, expected[i])); + assertEquals(input[i], converter.convert(String.class, expected[i]), input[i] + " to String"); } } /** * Tests a conversion to an unsupported type. */ - public void testUnsupportedType() { - try { - converter.convert(Integer.class, "http://www.apache.org"); - fail("Unsupported type could be converted!"); - } catch (final ConversionException cex) { - // expected result - } + @Test + void testUnsupportedType() { + assertThrows(ConversionException.class, () -> converter.convert(Integer.class, "http://www.apache.org")); } }