Skip to content

Commit a8f5b4a

Browse files
committed
Move string-based argument conversion tests to platform-test
1 parent ed5ac99 commit a8f5b4a

File tree

2 files changed

+339
-1
lines changed

2 files changed

+339
-1
lines changed

jupiter-tests/src/test/java/org/junit/jupiter/params/converter/DefaultArgumentConverterTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ void throwsExceptionOnInvalidStringForPrimitiveTypes() {
183183
}
184184

185185
@Test
186-
void throwsExceptionWhenImplicitConverstionIsUnsupported() {
186+
void throwsExceptionWhenImplicitConversionIsUnsupported() {
187187
assertThatExceptionOfType(ArgumentConversionException.class) //
188188
.isThrownBy(() -> convert("foo", Enigma.class)) //
189189
.withMessage("No built-in converter for source type java.lang.String and target type %s",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
package org.junit.platform.commons.support.conversion;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
5+
6+
import java.io.File;
7+
import java.lang.reflect.Method;
8+
import java.math.BigDecimal;
9+
import java.math.BigInteger;
10+
import java.net.URI;
11+
import java.net.URL;
12+
import java.nio.charset.Charset;
13+
import java.nio.charset.StandardCharsets;
14+
import java.nio.file.Path;
15+
import java.nio.file.Paths;
16+
import java.time.Duration;
17+
import java.time.Instant;
18+
import java.time.LocalDate;
19+
import java.time.LocalDateTime;
20+
import java.time.LocalTime;
21+
import java.time.MonthDay;
22+
import java.time.OffsetDateTime;
23+
import java.time.OffsetTime;
24+
import java.time.Period;
25+
import java.time.Year;
26+
import java.time.YearMonth;
27+
import java.time.ZoneId;
28+
import java.time.ZoneOffset;
29+
import java.time.ZonedDateTime;
30+
import java.util.Currency;
31+
import java.util.Locale;
32+
import java.util.UUID;
33+
import java.util.concurrent.TimeUnit;
34+
35+
import org.junit.jupiter.api.Test;
36+
import org.junit.jupiter.params.ParameterizedTest;
37+
import org.junit.jupiter.params.provider.ValueSource;
38+
import org.junit.platform.commons.support.ReflectionSupport;
39+
import org.junit.platform.commons.test.TestClassLoader;
40+
import org.junit.platform.commons.util.ClassLoaderUtils;
41+
42+
/**
43+
* Unit tests for {@link ConversionSupport}.
44+
*
45+
* @since 5.12
46+
*/
47+
class ConversionSupportTests {
48+
49+
@Test
50+
void isAwareOfNull() {
51+
assertConverts(null, Object.class, null);
52+
assertConverts(null, String.class, null);
53+
assertConverts(null, Boolean.class, null);
54+
}
55+
56+
@Test
57+
void convertsStringsToPrimitiveTypes() {
58+
assertConverts("true", boolean.class, true);
59+
assertConverts("false", boolean.class, false);
60+
assertConverts("o", char.class, 'o');
61+
assertConverts("1", byte.class, (byte) 1);
62+
assertConverts("1_0", byte.class, (byte) 10);
63+
assertConverts("1", short.class, (short) 1);
64+
assertConverts("1_2", short.class, (short) 12);
65+
assertConverts("42", int.class, 42);
66+
assertConverts("700_050_000", int.class, 700_050_000);
67+
assertConverts("42", long.class, 42L);
68+
assertConverts("4_2", long.class, 42L);
69+
assertConverts("42.23", float.class, 42.23f);
70+
assertConverts("42.2_3", float.class, 42.23f);
71+
assertConverts("42.23", double.class, 42.23);
72+
assertConverts("42.2_3", double.class, 42.23);
73+
}
74+
75+
@Test
76+
void convertsStringsToPrimitiveWrapperTypes() {
77+
assertConverts("true", Boolean.class, true);
78+
assertConverts("false", Boolean.class, false);
79+
assertConverts("o", Character.class, 'o');
80+
assertConverts("1", Byte.class, (byte) 1);
81+
assertConverts("1_0", Byte.class, (byte) 10);
82+
assertConverts("1", Short.class, (short) 1);
83+
assertConverts("1_2", Short.class, (short) 12);
84+
assertConverts("42", Integer.class, 42);
85+
assertConverts("700_050_000", Integer.class, 700_050_000);
86+
assertConverts("42", Long.class, 42L);
87+
assertConverts("4_2", Long.class, 42L);
88+
assertConverts("42.23", Float.class, 42.23f);
89+
assertConverts("42.2_3", Float.class, 42.23f);
90+
assertConverts("42.23", Double.class, 42.23);
91+
assertConverts("42.2_3", Double.class, 42.23);
92+
}
93+
94+
@ParameterizedTest(name = "[{index}] {0}")
95+
@ValueSource(classes = { char.class, boolean.class, short.class, byte.class, int.class, long.class, float.class,
96+
double.class, void.class })
97+
void throwsExceptionForNullToPrimitiveTypeConversion(Class<?> type) {
98+
assertThatExceptionOfType(ConversionException.class) //
99+
.isThrownBy(() -> convert(null, type)) //
100+
.withMessage("Cannot convert null to primitive value of type " + type.getCanonicalName());
101+
}
102+
103+
@ParameterizedTest(name = "[{index}] {0}")
104+
@ValueSource(classes = { Boolean.class, Character.class, Short.class, Byte.class, Integer.class, Long.class,
105+
Float.class, Double.class })
106+
void throwsExceptionWhenConvertingTheWordNullToPrimitiveWrapperType(Class<?> type) {
107+
assertThatExceptionOfType(ConversionException.class) //
108+
.isThrownBy(() -> convert("null", type)) //
109+
.withMessage("Failed to convert String \"null\" to type " + type.getCanonicalName());
110+
assertThatExceptionOfType(ConversionException.class) //
111+
.isThrownBy(() -> convert("NULL", type)) //
112+
.withMessage("Failed to convert String \"NULL\" to type " + type.getCanonicalName());
113+
}
114+
115+
@Test
116+
void throwsExceptionOnInvalidStringForPrimitiveTypes() {
117+
assertThatExceptionOfType(ConversionException.class) //
118+
.isThrownBy(() -> convert("ab", char.class)) //
119+
.withMessage("Failed to convert String \"ab\" to type char") //
120+
.havingCause() //
121+
.withMessage("String must have length of 1: ab");
122+
123+
assertThatExceptionOfType(ConversionException.class) //
124+
.isThrownBy(() -> convert("tru", boolean.class)) //
125+
.withMessage("Failed to convert String \"tru\" to type boolean") //
126+
.havingCause() //
127+
.withMessage("String must be 'true' or 'false' (ignoring case): tru");
128+
129+
assertThatExceptionOfType(ConversionException.class) //
130+
.isThrownBy(() -> convert("null", boolean.class)) //
131+
.withMessage("Failed to convert String \"null\" to type boolean") //
132+
.havingCause() //
133+
.withMessage("String must be 'true' or 'false' (ignoring case): null");
134+
135+
assertThatExceptionOfType(ConversionException.class) //
136+
.isThrownBy(() -> convert("NULL", boolean.class)) //
137+
.withMessage("Failed to convert String \"NULL\" to type boolean") //
138+
.havingCause() //
139+
.withMessage("String must be 'true' or 'false' (ignoring case): NULL");
140+
}
141+
142+
@Test
143+
void throwsExceptionWhenImplicitConversionIsUnsupported() {
144+
assertThatExceptionOfType(ConversionException.class) //
145+
.isThrownBy(() -> convert("foo", Enigma.class)) //
146+
.withMessage("No built-in converter for source type java.lang.String and target type %s",
147+
Enigma.class.getName());
148+
}
149+
150+
/**
151+
* @since 5.4
152+
*/
153+
@Test
154+
@SuppressWarnings("OctalInteger") // We test parsing octal integers here as well as hex.
155+
void convertsEncodedStringsToIntegralTypes() {
156+
assertConverts("0x1f", byte.class, (byte) 0x1F);
157+
assertConverts("-0x1F", byte.class, (byte) -0x1F);
158+
assertConverts("010", byte.class, (byte) 010);
159+
160+
assertConverts("0x1f00", short.class, (short) 0x1F00);
161+
assertConverts("-0x1F00", short.class, (short) -0x1F00);
162+
assertConverts("01000", short.class, (short) 01000);
163+
164+
assertConverts("0x1f000000", int.class, 0x1F000000);
165+
assertConverts("-0x1F000000", int.class, -0x1F000000);
166+
assertConverts("010000000", int.class, 010000000);
167+
168+
assertConverts("0x1f000000000", long.class, 0x1F000000000L);
169+
assertConverts("-0x1F000000000", long.class, -0x1F000000000L);
170+
assertConverts("0100000000000", long.class, 0100000000000L);
171+
}
172+
173+
@Test
174+
void convertsStringsToEnumConstants() {
175+
assertConverts("DAYS", TimeUnit.class, TimeUnit.DAYS);
176+
}
177+
178+
// --- java.io and java.nio ------------------------------------------------
179+
180+
@Test
181+
void convertsStringToCharset() {
182+
assertConverts("ISO-8859-1", Charset.class, StandardCharsets.ISO_8859_1);
183+
assertConverts("UTF-8", Charset.class, StandardCharsets.UTF_8);
184+
}
185+
186+
@Test
187+
void convertsStringToFile() {
188+
assertConverts("file", File.class, new File("file"));
189+
assertConverts("/file", File.class, new File("/file"));
190+
assertConverts("/some/file", File.class, new File("/some/file"));
191+
}
192+
193+
@Test
194+
void convertsStringToPath() {
195+
assertConverts("path", Path.class, Paths.get("path"));
196+
assertConverts("/path", Path.class, Paths.get("/path"));
197+
assertConverts("/some/path", Path.class, Paths.get("/some/path"));
198+
}
199+
200+
// --- java.lang -----------------------------------------------------------
201+
202+
@Test
203+
void convertsStringToClass() {
204+
assertConverts("java.lang.Integer", Class.class, Integer.class);
205+
assertConverts("java.lang.Void", Class.class, Void.class);
206+
assertConverts("java.lang.Thread$State", Class.class, Thread.State.class);
207+
assertConverts("byte", Class.class, byte.class);
208+
assertConverts("void", Class.class, void.class);
209+
assertConverts("char[]", Class.class, char[].class);
210+
assertConverts("java.lang.Long[][]", Class.class, Long[][].class);
211+
assertConverts("[[[I", Class.class, int[][][].class);
212+
assertConverts("[[Ljava.lang.String;", Class.class, String[][].class);
213+
}
214+
215+
@Test
216+
void convertsStringToClassWithCustomTypeFromDifferentClassLoader() throws Exception {
217+
String customTypeName = Enigma.class.getName();
218+
try (var testClassLoader = TestClassLoader.forClasses(Enigma.class)) {
219+
var customType = testClassLoader.loadClass(customTypeName);
220+
assertThat(customType.getClassLoader()).isSameAs(testClassLoader);
221+
222+
var declaringExecutable = ReflectionSupport.findMethod(customType, "foo").get();
223+
assertThat(declaringExecutable.getDeclaringClass().getClassLoader()).isSameAs(testClassLoader);
224+
225+
var clazz = (Class<?>) convert(customTypeName, Class.class, classLoader(declaringExecutable));
226+
assertThat(clazz).isNotEqualTo(Enigma.class);
227+
assertThat(clazz).isEqualTo(customType);
228+
assertThat(clazz.getClassLoader()).isSameAs(testClassLoader);
229+
}
230+
}
231+
232+
// --- java.math -----------------------------------------------------------
233+
234+
@Test
235+
void convertsStringToBigDecimal() {
236+
assertConverts("123.456e789", BigDecimal.class, new BigDecimal("123.456e789"));
237+
}
238+
239+
@Test
240+
void convertsStringToBigInteger() {
241+
assertConverts("1234567890123456789", BigInteger.class, new BigInteger("1234567890123456789"));
242+
}
243+
244+
// --- java.net ------------------------------------------------------------
245+
246+
@Test
247+
void convertsStringToURI() {
248+
assertConverts("https://docs.oracle.com/en/java/javase/12/", URI.class,
249+
URI.create("https://docs.oracle.com/en/java/javase/12/"));
250+
}
251+
252+
@Test
253+
void convertsStringToURL() throws Exception {
254+
assertConverts("https://junit.org/junit5", URL.class, URI.create("https://junit.org/junit5").toURL());
255+
}
256+
257+
// --- java.time -----------------------------------------------------------
258+
259+
@Test
260+
void convertsStringsToJavaTimeInstances() {
261+
assertConverts("PT1234.5678S", Duration.class, Duration.ofSeconds(1234, 567800000));
262+
assertConverts("1970-01-01T00:00:00Z", Instant.class, Instant.ofEpochMilli(0));
263+
assertConverts("2017-03-14", LocalDate.class, LocalDate.of(2017, 3, 14));
264+
assertConverts("2017-03-14T12:34:56.789", LocalDateTime.class,
265+
LocalDateTime.of(2017, 3, 14, 12, 34, 56, 789_000_000));
266+
assertConverts("12:34:56.789", LocalTime.class, LocalTime.of(12, 34, 56, 789_000_000));
267+
assertConverts("--03-14", MonthDay.class, MonthDay.of(3, 14));
268+
assertConverts("2017-03-14T12:34:56.789Z", OffsetDateTime.class,
269+
OffsetDateTime.of(2017, 3, 14, 12, 34, 56, 789_000_000, ZoneOffset.UTC));
270+
assertConverts("12:34:56.789Z", OffsetTime.class, OffsetTime.of(12, 34, 56, 789_000_000, ZoneOffset.UTC));
271+
assertConverts("P2M6D", Period.class, Period.of(0, 2, 6));
272+
assertConverts("2017", Year.class, Year.of(2017));
273+
assertConverts("2017-03", YearMonth.class, YearMonth.of(2017, 3));
274+
assertConverts("2017-03-14T12:34:56.789Z", ZonedDateTime.class,
275+
ZonedDateTime.of(2017, 3, 14, 12, 34, 56, 789_000_000, ZoneOffset.UTC));
276+
assertConverts("Europe/Berlin", ZoneId.class, ZoneId.of("Europe/Berlin"));
277+
assertConverts("+02:30", ZoneOffset.class, ZoneOffset.ofHoursMinutes(2, 30));
278+
}
279+
280+
// --- java.util -----------------------------------------------------------
281+
282+
@Test
283+
void convertsStringToCurrency() {
284+
assertConverts("JPY", Currency.class, Currency.getInstance("JPY"));
285+
}
286+
287+
@Test
288+
@SuppressWarnings("deprecation")
289+
void convertsStringToLocale() {
290+
assertConverts("en", Locale.class, Locale.ENGLISH);
291+
assertConverts("en_us", Locale.class, new Locale(Locale.US.toString()));
292+
}
293+
294+
@Test
295+
void convertsStringToUUID() {
296+
var uuid = "d043e930-7b3b-48e3-bdbe-5a3ccfb833db";
297+
assertConverts(uuid, UUID.class, UUID.fromString(uuid));
298+
}
299+
300+
// -------------------------------------------------------------------------
301+
302+
private void assertConverts(String input, Class<?> targetClass, Object expectedOutput) {
303+
var result = convert(input, targetClass);
304+
305+
assertThat(result) //
306+
.describedAs(input + " --(" + targetClass.getName() + ")--> " + expectedOutput) //
307+
.isEqualTo(expectedOutput);
308+
}
309+
310+
private Object convert(String input, Class<?> targetClass) {
311+
return convert(input, targetClass, classLoader());
312+
}
313+
314+
private Object convert(String input, Class<?> targetClass, ClassLoader classLoader) {
315+
return ConversionSupport.convert(input, targetClass, classLoader);
316+
}
317+
318+
private static ClassLoader classLoader() {
319+
Method declaringExecutable = ReflectionSupport.findMethod(ConversionSupportTests.class, "foo").get();
320+
return classLoader(declaringExecutable);
321+
}
322+
323+
private static ClassLoader classLoader(Method declaringExecutable) {
324+
return ClassLoaderUtils.getClassLoader(declaringExecutable.getDeclaringClass());
325+
}
326+
327+
@SuppressWarnings("unused")
328+
private static void foo() {
329+
}
330+
331+
private static class Enigma {
332+
333+
@SuppressWarnings("unused")
334+
void foo() {
335+
}
336+
}
337+
338+
}

0 commit comments

Comments
 (0)