Skip to content

Commit e63c2fc

Browse files
committed
Remove built-in support for Locale conversion in ISO 639 format
Related issue: #853
1 parent eaf5ae9 commit e63c2fc

File tree

11 files changed

+46
-104
lines changed

11 files changed

+46
-104
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M2.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ repository on GitHub.
6565
of the `TestTemplateInvocationContextProvider` interface from
6666
`Stream<TestTemplateInvocationContext>` to
6767
`Stream<? extends TestTemplateInvocationContext>`.
68+
* Remove support for `junit.jupiter.params.arguments.conversion.locale.format`
69+
configuration parameter. `Locale` conversions are now always performed using the IETF
70+
BCP 47 language tag format supported by `Locale.forLanguageTag(String)`.
6871

6972
[[release-notes-6.0.0-M2-junit-jupiter-new-features-and-improvements]]
7073
==== New Features and Improvements

documentation/src/docs/asciidoc/user-guide/writing-tests.adoc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2500,12 +2500,6 @@ integral types: `byte`, `short`, `int`, `long`, and their boxed counterparts.
25002500
| `java.util.UUID` | `"d043e930-7b3b-48e3-bdbe-5a3ccfb833db"` -> `UUID.fromString("d043e930-7b3b-48e3-bdbe-5a3ccfb833db")`
25012501
|===
25022502

2503-
WARNING: To revert to the old `java.util.Locale` conversion behavior of version 5.12 and
2504-
earlier (which called the deprecated `Locale(String)` constructor), you can set the
2505-
`junit.jupiter.params.arguments.conversion.locale.format`
2506-
<<running-tests-config-params, configuration parameter>> to `iso_639`. However, please
2507-
note that this parameter is deprecated and will be removed in a future release.
2508-
25092503
[[writing-tests-parameterized-tests-argument-conversion-implicit-fallback]]
25102504
====== Fallback String-to-Object Conversion
25112505

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@
4848
@API(status = INTERNAL, since = "5.4")
4949
public class DefaultJupiterConfiguration implements JupiterConfiguration {
5050

51-
private static final List<String> UNSUPPORTED_CONFIGURATION_PARAMETERS = List.of("junit.jupiter.tempdir.scope");
51+
private static final List<String> UNSUPPORTED_CONFIGURATION_PARAMETERS = List.of( //
52+
"junit.jupiter.tempdir.scope", //
53+
"junit.jupiter.params.arguments.conversion.locale.format" //
54+
);
5255

5356
private static final EnumConfigurationParameterConverter<ExecutionMode> executionModeConverter = //
5457
new EnumConfigurationParameterConverter<>(ExecutionMode.class, "parallel execution mode");

junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ private void storeParameterInfo(ExtensionContext context) {
7474
ClassLoader classLoader = getClassLoader(this.declarationContext.getTestClass());
7575
@Nullable
7676
Object[] arguments = this.arguments.getConsumedPayloads();
77-
ArgumentsAccessor accessor = DefaultArgumentsAccessor.create(context, invocationIndex, classLoader, arguments);
77+
ArgumentsAccessor accessor = DefaultArgumentsAccessor.create(invocationIndex, classLoader, arguments);
7878
new DefaultParameterInfo(declarations, accessor).store(context);
7979
}
8080

junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ private static Converter createConverter(ParameterDeclaration declaration, Exten
435435
.map(clazz -> ParameterizedTestSpiInstantiator.instantiate(ArgumentConverter.class, clazz, extensionContext))
436436
.map(converter -> AnnotationConsumerInitializer.initialize(declaration.getAnnotatedElement(), converter))
437437
.map(Converter::new)
438-
.orElseGet(() -> Converter.createDefault(extensionContext));
438+
.orElse(Converter.DEFAULT);
439439
} // @formatter:on
440440
catch (Exception ex) {
441441
throw parameterResolutionException("Error creating ArgumentConverter", ex, declaration.getParameterIndex());
@@ -479,9 +479,7 @@ Object resolve(FieldContext fieldContext, ExtensionContext extensionContext, Eva
479479

480480
private record Converter(ArgumentConverter argumentConverter) implements Resolver {
481481

482-
private static Converter createDefault(ExtensionContext context) {
483-
return new Converter(new DefaultArgumentConverter(context));
484-
}
482+
static final Converter DEFAULT = new Converter(new DefaultArgumentConverter());
485483

486484
@Override
487485
public @Nullable Object resolve(ParameterContext parameterContext, int parameterIndex,

junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
import org.apiguardian.api.API;
2121
import org.jspecify.annotations.Nullable;
22-
import org.junit.jupiter.api.extension.ExtensionContext;
2322
import org.junit.jupiter.params.converter.DefaultArgumentConverter;
2423
import org.junit.platform.commons.util.ClassUtils;
2524
import org.junit.platform.commons.util.Preconditions;
@@ -41,13 +40,13 @@ public class DefaultArgumentsAccessor implements ArgumentsAccessor {
4140
private final @Nullable Object[] arguments;
4241
private final BiFunction<@Nullable Object, Class<?>, @Nullable Object> converter;
4342

44-
public static DefaultArgumentsAccessor create(ExtensionContext context, int invocationIndex,
45-
ClassLoader classLoader, @Nullable Object[] arguments) {
43+
public static DefaultArgumentsAccessor create(int invocationIndex, ClassLoader classLoader,
44+
@Nullable Object[] arguments) {
4645
Preconditions.notNull(classLoader, "ClassLoader must not be null");
4746

47+
var argumentConverter = new DefaultArgumentConverter();
4848
BiFunction<@Nullable Object, Class<?>, @Nullable Object> converter = (source,
49-
targetType) -> new DefaultArgumentConverter(context) //
50-
.convert(source, targetType, classLoader);
49+
targetType) -> argumentConverter.convert(source, targetType, classLoader);
5150
return new DefaultArgumentsAccessor(converter, invocationIndex, arguments);
5251
}
5352

junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,9 @@
2121
import java.util.Currency;
2222
import java.util.Locale;
2323
import java.util.UUID;
24-
import java.util.function.Function;
2524

2625
import org.apiguardian.api.API;
2726
import org.jspecify.annotations.Nullable;
28-
import org.junit.jupiter.api.extension.ExtensionContext;
2927
import org.junit.jupiter.api.extension.ParameterContext;
3028
import org.junit.jupiter.params.support.FieldContext;
3129
import org.junit.platform.commons.support.conversion.ConversionException;
@@ -53,31 +51,7 @@
5351
@API(status = INTERNAL, since = "5.0")
5452
public class DefaultArgumentConverter implements ArgumentConverter {
5553

56-
/**
57-
* Property name used to set the format for the conversion of {@link Locale}
58-
* arguments: {@value}
59-
*
60-
* <h4>Supported Values</h4>
61-
* <ul>
62-
* <li>{@code bcp_47}: uses the IETF BCP 47 language tag format, delegating
63-
* the conversion to {@link Locale#forLanguageTag(String)}</li>
64-
* <li>{@code iso_639}: uses the ISO 639 alpha-2 or alpha-3 language code
65-
* format, delegating the conversion to {@link Locale#Locale(String)}</li>
66-
* </ul>
67-
*
68-
* <p>If not specified, the default is {@code bcp_47}.
69-
*
70-
* @since 5.13
71-
*/
72-
public static final String DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME = "junit.jupiter.params.arguments.conversion.locale.format";
73-
74-
private static final Function<String, LocaleConversionFormat> TRANSFORMER = value -> LocaleConversionFormat.valueOf(
75-
value.strip().toUpperCase(Locale.ROOT));
76-
77-
private final ExtensionContext context;
78-
79-
public DefaultArgumentConverter(ExtensionContext context) {
80-
this.context = context;
54+
public DefaultArgumentConverter() {
8155
}
8256

8357
@Override
@@ -110,7 +84,7 @@ public DefaultArgumentConverter(ExtensionContext context) {
11084
}
11185

11286
if (source instanceof String string) {
113-
if (targetType == Locale.class && getLocaleConversionFormat() == LocaleConversionFormat.BCP_47) {
87+
if (targetType == Locale.class) {
11488
return Locale.forLanguageTag(string);
11589
}
11690

@@ -126,22 +100,9 @@ public DefaultArgumentConverter(ExtensionContext context) {
126100
source.getClass().getTypeName(), targetType.getTypeName()));
127101
}
128102

129-
private LocaleConversionFormat getLocaleConversionFormat() {
130-
return context.getConfigurationParameter(DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME, TRANSFORMER) //
131-
.orElse(LocaleConversionFormat.BCP_47);
132-
}
133-
134103
@Nullable
135104
Object convert(@Nullable String source, Class<?> targetType, ClassLoader classLoader) {
136105
return ConversionSupport.convert(source, targetType, classLoader);
137106
}
138107

139-
enum LocaleConversionFormat {
140-
141-
BCP_47,
142-
143-
ISO_639
144-
145-
}
146-
147108
}

jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
package org.junit.jupiter.params;
1212

1313
import static java.lang.annotation.RetentionPolicy.RUNTIME;
14+
import static java.util.Objects.requireNonNull;
1415
import static org.assertj.core.api.Assertions.assertThat;
1516
import static org.assertj.core.api.Assertions.within;
1617
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -22,7 +23,6 @@
2223
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
2324
import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.appendTestTemplateInvocationSegment;
2425
import static org.junit.jupiter.engine.discovery.JupiterUniqueIdBuilder.uniqueIdForTestTemplateMethod;
25-
import static org.junit.jupiter.params.converter.DefaultArgumentConverter.DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME;
2626
import static org.junit.jupiter.params.provider.Arguments.arguments;
2727
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectIteration;
2828
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod;
@@ -99,6 +99,7 @@
9999
import org.junit.jupiter.params.converter.ArgumentConversionException;
100100
import org.junit.jupiter.params.converter.ArgumentConverter;
101101
import org.junit.jupiter.params.converter.ConvertWith;
102+
import org.junit.jupiter.params.converter.TypedArgumentConverter;
102103
import org.junit.jupiter.params.provider.Arguments;
103104
import org.junit.jupiter.params.provider.ArgumentsProvider;
104105
import org.junit.jupiter.params.provider.ArgumentsSource;
@@ -114,6 +115,7 @@
114115
import org.junit.jupiter.params.support.ParameterDeclarations;
115116
import org.junit.platform.commons.PreconditionViolationException;
116117
import org.junit.platform.commons.util.ClassUtils;
118+
import org.junit.platform.engine.DiscoveryIssue;
117119
import org.junit.platform.engine.TestDescriptor;
118120
import org.junit.platform.engine.TestExecutionResult;
119121
import org.junit.platform.testkit.engine.EngineExecutionResults;
@@ -488,17 +490,19 @@ void executesWithDefaultLocaleConversionFormat() {
488490
}
489491

490492
@Test
491-
void executesWithBcp47LocaleConversionFormat() {
492-
var results = execute(Map.of(DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME, "bcp_47"),
493-
LocaleConversionTestCase.class, "testWithBcp47", Locale.class);
493+
void emitsWarningForNoLongerSupportedConfigurationParameter() {
494+
var results = discoverTests(request -> request //
495+
.configurationParameter("junit.jupiter.params.arguments.conversion.locale.format", "iso_639").selectors(
496+
selectMethod(LocaleConversionTestCase.class, "testWithBcp47", Locale.class)));
494497

495-
results.allEvents().assertStatistics(stats -> stats.started(4).succeeded(4));
498+
assertThat(results.getDiscoveryIssues()) //
499+
.contains(DiscoveryIssue.create(DiscoveryIssue.Severity.WARNING,
500+
"The 'junit.jupiter.params.arguments.conversion.locale.format' configuration parameter is no longer supported: iso_639. Please remove it from your configuration."));
496501
}
497502

498503
@Test
499-
void executesWithIso639LocaleConversionFormat() {
500-
var results = execute(Map.of(DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME, "iso_639"),
501-
LocaleConversionTestCase.class, "testWithIso639", Locale.class);
504+
void executesWithCustomLocalConverterUsingIso639Format() {
505+
var results = execute(LocaleConversionTestCase.class, "testWithIso639", Locale.class);
502506

503507
results.allEvents().assertStatistics(stats -> stats.started(4).succeeded(4));
504508
}
@@ -2566,11 +2570,24 @@ void testWithBcp47(Locale locale) {
25662570

25672571
@ParameterizedTest
25682572
@ValueSource(strings = "en-US")
2569-
void testWithIso639(Locale locale) {
2573+
void testWithIso639(@ConvertWith(Iso636Converter.class) Locale locale) {
25702574
assertEquals("en-us", locale.getLanguage());
25712575
assertEquals("", locale.getCountry());
25722576
}
25732577

2578+
static class Iso636Converter extends TypedArgumentConverter<String, Locale> {
2579+
2580+
Iso636Converter() {
2581+
super(String.class, Locale.class);
2582+
}
2583+
2584+
@SuppressWarnings("deprecation")
2585+
@Override
2586+
protected Locale convert(@Nullable String source) throws ArgumentConversionException {
2587+
return new Locale(requireNonNull(source));
2588+
}
2589+
}
2590+
25742591
}
25752592

25762593
private static class TwoSingleStringArgumentsProvider implements ArgumentsProvider {

jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessorTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ private static DefaultArgumentsAccessor defaultArgumentsAccessor(int invocationI
171171
@Nullable Object... arguments) {
172172
var context = mock(ExtensionContext.class);
173173
var classLoader = DefaultArgumentsAccessorTests.class.getClassLoader();
174-
return DefaultArgumentsAccessor.create(context, invocationIndex, classLoader, arguments);
174+
return DefaultArgumentsAccessor.create(invocationIndex, classLoader, arguments);
175175
}
176176

177177
@SuppressWarnings("unused")

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

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,18 @@
1212

1313
import static org.assertj.core.api.Assertions.assertThat;
1414
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
15-
import static org.junit.jupiter.params.converter.DefaultArgumentConverter.DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME;
16-
import static org.junit.jupiter.params.converter.DefaultArgumentConverter.LocaleConversionFormat.BCP_47;
17-
import static org.junit.jupiter.params.converter.DefaultArgumentConverter.LocaleConversionFormat.ISO_639;
1815
import static org.junit.platform.commons.util.ClassLoaderUtils.getClassLoader;
1916
import static org.mockito.ArgumentMatchers.any;
20-
import static org.mockito.ArgumentMatchers.eq;
2117
import static org.mockito.Mockito.doReturn;
2218
import static org.mockito.Mockito.doThrow;
23-
import static org.mockito.Mockito.mock;
2419
import static org.mockito.Mockito.never;
2520
import static org.mockito.Mockito.spy;
2621
import static org.mockito.Mockito.verify;
27-
import static org.mockito.Mockito.when;
2822

2923
import java.util.Locale;
30-
import java.util.Optional;
3124

3225
import org.jspecify.annotations.Nullable;
3326
import org.junit.jupiter.api.Test;
34-
import org.junit.jupiter.api.extension.ExtensionContext;
3527
import org.junit.jupiter.params.ParameterizedTest;
3628
import org.junit.jupiter.params.provider.ValueSource;
3729
import org.junit.platform.commons.support.ReflectionSupport;
@@ -46,8 +38,7 @@
4638
*/
4739
class DefaultArgumentConverterTests {
4840

49-
private final ExtensionContext context = mock();
50-
private final DefaultArgumentConverter underTest = spy(new DefaultArgumentConverter(context));
41+
private final DefaultArgumentConverter underTest = spy(new DefaultArgumentConverter());
5142

5243
@Test
5344
void isAwareOfNull() {
@@ -113,35 +104,11 @@ void delegatesStringsConversion() {
113104
}
114105

115106
@Test
116-
void convertsLocaleWithDefaultFormat() {
117-
when(context.getConfigurationParameter(eq(DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME), any())) //
118-
.thenReturn(Optional.empty());
119-
120-
assertConverts("en", Locale.class, Locale.ENGLISH);
121-
assertConverts("en-US", Locale.class, Locale.US);
122-
}
123-
124-
@Test
125-
void convertsLocaleWithExplicitBcp47Format() {
126-
when(context.getConfigurationParameter(eq(DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME), any())) //
127-
.thenReturn(Optional.of(BCP_47));
128-
107+
void convertsLocaleWithBcp47Format() {
129108
assertConverts("en", Locale.class, Locale.ENGLISH);
130109
assertConverts("en-US", Locale.class, Locale.US);
131110
}
132111

133-
@Test
134-
void delegatesLocaleConversionWithExplicitIso639Format() {
135-
when(context.getConfigurationParameter(eq(DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME), any())) //
136-
.thenReturn(Optional.of(ISO_639));
137-
138-
doReturn(null).when(underTest).convert(any(), any(), any(ClassLoader.class));
139-
140-
convert("en", Locale.class);
141-
142-
verify(underTest).convert("en", Locale.class, getClassLoader(DefaultArgumentConverterTests.class));
143-
}
144-
145112
@Test
146113
void throwsExceptionForDelegatedConversionFailure() {
147114
ConversionException exception = new ConversionException("fail");

0 commit comments

Comments
 (0)