diff --git a/src/test/java/com/cedarsoftware/util/convert/ConverterEverythingTest.java b/src/test/java/com/cedarsoftware/util/convert/ConverterEverythingTest.java index 27f3849d..cc9a388e 100644 --- a/src/test/java/com/cedarsoftware/util/convert/ConverterEverythingTest.java +++ b/src/test/java/com/cedarsoftware/util/convert/ConverterEverythingTest.java @@ -2,6 +2,8 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.net.URI; +import java.net.URL; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.sql.Timestamp; @@ -1564,49 +1566,103 @@ public ZoneId getZoneId() { { LocalTime.of(9, 26, 17, 1), "09:26:17.000000001" }, }); TEST_DB.put(pair(MonthDay.class, String.class), new Object[][] { - { MonthDay.of(1, 1), "--01-01"}, - { MonthDay.of(12, 31), "--12-31"}, + { MonthDay.of(1, 1), "--01-01", true }, + { MonthDay.of(12, 31), "--12-31", true }, }); TEST_DB.put(pair(YearMonth.class, String.class), new Object[][] { - { YearMonth.of(2024, 1), "2024-01" }, - { YearMonth.of(2024, 12), "2024-12" }, + { YearMonth.of(2024, 1), "2024-01" , true }, + { YearMonth.of(2024, 12), "2024-12" , true }, }); TEST_DB.put(pair(Period.class, String.class), new Object[][] { - { Period.of(6, 3, 21), "P6Y3M21D" }, - { Period.ofWeeks(160), "P1120D" }, + { Period.of(6, 3, 21), "P6Y3M21D" , true }, + { Period.ofWeeks(160), "P1120D" , true }, }); TEST_DB.put(pair(ZoneId.class, String.class), new Object[][] { - { ZoneId.of("America/New_York"), "America/New_York"}, - { ZoneId.of("Z"), "Z"}, - { ZoneId.of("UTC"), "UTC"}, - { ZoneId.of("GMT"), "GMT"}, + { ZoneId.of("America/New_York"), "America/New_York", true }, + { ZoneId.of("Z"), "Z", true }, + { ZoneId.of("UTC"), "UTC", true }, + { ZoneId.of("GMT"), "GMT", true }, }); TEST_DB.put(pair(ZoneOffset.class, String.class), new Object[][] { - { ZoneOffset.of("+1"), "+01:00" }, - { ZoneOffset.of("+0109"), "+01:09" }, + { ZoneOffset.of("+1"), "+01:00" , true }, + { ZoneOffset.of("+0109"), "+01:09" , true }, }); TEST_DB.put(pair(OffsetTime.class, String.class), new Object[][] { - { OffsetTime.parse("10:15:30+01:00"), "10:15:30+01:00" }, + { OffsetTime.parse("10:15:30+01:00"), "10:15:30+01:00" , true }, }); TEST_DB.put(pair(OffsetDateTime.class, String.class), new Object[][] { - { OffsetDateTime.parse("2024-02-10T10:15:07+01:00"), "2024-02-10T10:15:07+01:00" }, + { OffsetDateTime.parse("2024-02-10T10:15:07+01:00"), "2024-02-10T10:15:07+01:00" , true }, }); TEST_DB.put(pair(Year.class, String.class), new Object[][] { - { Year.of(2024), "2024" }, - { Year.of(1582), "1582" }, - { Year.of(500), "500" }, - { Year.of(1), "1" }, - { Year.of(0), "0" }, - { Year.of(-1), "-1" }, + { Year.of(2024), "2024", true }, + { Year.of(1582), "1582", true }, + { Year.of(500), "500", true }, + { Year.of(1), "1", true }, + { Year.of(0), "0", true }, + { Year.of(-1), "-1", true }, + }); + + TEST_DB.put(pair(URL.class, String.class), new Object[][] { + { toURL("https://domain.com"), "https://domain.com", true}, + { toURL("http://localhost"), "http://localhost", true }, + { toURL("http://localhost:8080"), "http://localhost:8080", true }, + { toURL("http://localhost:8080/file/path"), "http://localhost:8080/file/path", true }, + { toURL("http://localhost:8080/path/file.html"), "http://localhost:8080/path/file.html", true }, + { toURL("http://localhost:8080/path/file.html?foo=1&bar=2"), "http://localhost:8080/path/file.html?foo=1&bar=2", true }, + { toURL("http://localhost:8080/path/file.html?foo=bar&qux=quy#AnchorLocation"), "http://localhost:8080/path/file.html?foo=bar&qux=quy#AnchorLocation", true }, + { toURL("https://foo.bar.com/"), "https://foo.bar.com/", true }, + { toURL("https://foo.bar.com/path/foo%20bar.html"), "https://foo.bar.com/path/foo%20bar.html", true }, + { toURL("https://foo.bar.com/path/file.html?text=Hello+G%C3%BCnter"), "https://foo.bar.com/path/file.html?text=Hello+G%C3%BCnter", true }, + { toURL("ftp://user@bar.com/foo/bar.txt"), "ftp://user@bar.com/foo/bar.txt", true }, + { toURL("ftp://user:password@host/foo/bar.txt"), "ftp://user:password@host/foo/bar.txt", true }, + { toURL("ftp://user:password@host:8192/foo/bar.txt"), "ftp://user:password@host:8192/foo/bar.txt", true }, + { toURL("file:/path/to/file"), "file:/path/to/file", true }, + { toURL("file://localhost/path/to/file.json"), "file://localhost/path/to/file.json", true }, + { toURL("file://servername/path/to/file.json"),"file://servername/path/to/file.json", true }, + { toURL("jar:file:/c://my.jar!/"), "jar:file:/c://my.jar!/", true }, + { toURL("jar:file:/c://my.jar!/com/mycompany/MyClass.class"), "jar:file:/c://my.jar!/com/mycompany/MyClass.class", true } + }); + + TEST_DB.put(pair(URI.class, String.class), new Object[][] { + { toURI("https://domain.com"), "https://domain.com", true }, + { toURI("http://localhost"), "http://localhost", true }, + { toURI("http://localhost:8080"), "http://localhost:8080", true }, + { toURI("http://localhost:8080/file/path"), "http://localhost:8080/file/path", true }, + { toURI("http://localhost:8080/path/file.html"), "http://localhost:8080/path/file.html", true }, + { toURI("http://localhost:8080/path/file.html?foo=1&bar=2"), "http://localhost:8080/path/file.html?foo=1&bar=2", true }, + { toURI("http://localhost:8080/path/file.html?foo=bar&qux=quy#AnchorLocation"), "http://localhost:8080/path/file.html?foo=bar&qux=quy#AnchorLocation", true }, + { toURI("https://foo.bar.com/"), "https://foo.bar.com/", true }, + { toURI("https://foo.bar.com/path/foo%20bar.html"), "https://foo.bar.com/path/foo%20bar.html", true }, + { toURI("https://foo.bar.com/path/file.html?text=Hello+G%C3%BCnter"), "https://foo.bar.com/path/file.html?text=Hello+G%C3%BCnter", true }, + { toURI("ftp://user@bar.com/foo/bar.txt"), "ftp://user@bar.com/foo/bar.txt", true }, + { toURI("ftp://user:password@host/foo/bar.txt"), "ftp://user:password@host/foo/bar.txt", true }, + { toURI("ftp://user:password@host:8192/foo/bar.txt"), "ftp://user:password@host:8192/foo/bar.txt", true }, + { toURI("file:/path/to/file"), "file:/path/to/file", true }, + { toURI("file://localhost/path/to/file.json"), "file://localhost/path/to/file.json", true }, + { toURI("file://servername/path/to/file.json"),"file://servername/path/to/file.json", true }, + { toURI("jar:file:/c://my.jar!/"), "jar:file:/c://my.jar!/", true }, + { toURI("jar:file:/c://my.jar!/com/mycompany/MyClass.class"), "jar:file:/c://my.jar!/com/mycompany/MyClass.class", true } }); } - + private static String toGmtString(Date date) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); simpleDateFormat.setTimeZone(TOKYO_TZ); return simpleDateFormat.format(date); } + private static URL toURL(String url) { + try { + return toURI(url).toURL(); + } catch (Exception e) { + return null; + } + } + + private static URI toURI(String url) { + return URI.create(url); + } + @BeforeEach void before() { // create converter with default options @@ -1649,6 +1705,7 @@ private static Object possiblyConvertSupplier(Object possibleSupplier) { return possibleSupplier; } + private static Stream generateTestEverythingParams() { List list = new ArrayList<>(400); @@ -1670,6 +1727,37 @@ private static Stream generateTestEverythingParams() { return Stream.of(list.toArray(new Arguments[] {})); } + + private static Stream generateTestEverythingParamsInReverse() { + List list = new ArrayList<>(400); + + for (Map.Entry, Class>, Object[][]> entry : TEST_DB.entrySet()) { + Class sourceClass = entry.getKey().getKey(); + Class targetClass = entry.getKey().getValue(); + + String sourceName = Converter.getShortName(sourceClass); + String targetName = Converter.getShortName(targetClass); + Object[][] testData = entry.getValue(); + + for (Object[] testPair : testData) { + boolean reverse = false; + Object source = possiblyConvertSupplier(testPair[0]); + Object target = possiblyConvertSupplier(testPair[1]); + + if (testPair.length > 2) { + reverse = (boolean)testPair[2]; + } + + if (!reverse) { + continue; + } + + list.add(Arguments.of(targetName, sourceName, target, source, targetClass, sourceClass)); + } + } + + return Stream.of(list.toArray(new Arguments[] {})); + } @ParameterizedTest(name = "{0}[{2}] ==> {1}[{3}]") @MethodSource("generateTestEverythingParams") @@ -1703,4 +1791,39 @@ void testConvert(String shortNameSource, String shortNameTarget, Object source, } } } + + @ParameterizedTest(name = "{0}[{2}] ==> {1}[{3}]") + @MethodSource("generateTestEverythingParamsInReverse") + void testConvertReverse(String shortNameSource, String shortNameTarget, Object source, Object target, Class sourceClass, Class targetClass) { + // Make sure source instance is of the sourceClass + if (source == null) { + assertEquals(sourceClass, Void.class, "On the source-side of test input, null can only appear in the Void.class data"); + } else { + assertTrue(ClassUtilities.toPrimitiveWrapperClass(sourceClass).isInstance(source), "source type mismatch"); + } + assertTrue(target == null || target instanceof Throwable || ClassUtilities.toPrimitiveWrapperClass(targetClass).isInstance(target), "target type mismatch"); + + // if the source/target are the same Class, then ensure identity lambda is used. + if (sourceClass.equals(targetClass)) { + assertSame(source, converter.convert(source, targetClass)); + } + + if (target instanceof Throwable) { + Throwable t = (Throwable) target; + assertThatExceptionOfType(t.getClass()) + .isThrownBy(() -> converter.convert(source, targetClass)) + .withMessageContaining(((Throwable) target).getMessage()); + } else { + // Assert values are equals + Object actual = converter.convert(source, targetClass); + try { + assertEquals(target, actual); + } catch (Throwable e) { + System.err.println(shortNameSource + "[" + source + "] ==> " + shortNameTarget + "[" + target + "] Failed with: " + actual); + throw e; + } + } + } + + }