From 85434d2a69f257afcb03bcf901e3ba40ed3b01cf Mon Sep 17 00:00:00 2001 From: Stefano Cordio Date: Mon, 31 Jul 2023 12:03:05 +0200 Subject: [PATCH] Add `Locale` conversion format configuration property --- .../junit-jupiter-engine.gradle.kts | 1 + .../config/CachingJupiterConfiguration.java | 7 ++++ .../config/DefaultJupiterConfiguration.java | 11 ++++++ .../engine/config/JupiterConfiguration.java | 4 ++ .../org.junit.jupiter.engine/module-info.java | 1 + .../converter/LocaleConversionFormat.java | 39 +++++++++++++++++++ .../converter/StringToLocaleConverter.java | 37 ++++++++++++++++++ .../CachingJupiterConfigurationTests.java | 20 ++++++++-- .../DefaultJupiterConfigurationTests.java | 9 +++++ .../junit-jupiter-engine.expected.txt | 1 + 10 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/LocaleConversionFormat.java create mode 100644 junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/StringToLocaleConverter.java diff --git a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts index 04d86e5f0da7..9a67d6d47893 100644 --- a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts +++ b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts @@ -9,6 +9,7 @@ dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformEngine) api(projects.junitJupiterApi) + api(projects.junitJupiterParams) compileOnlyApi(libs.apiguardian) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/CachingJupiterConfiguration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/CachingJupiterConfiguration.java index f2e24ba494dc..f08d4cd5ab76 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/CachingJupiterConfiguration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/CachingJupiterConfiguration.java @@ -30,6 +30,7 @@ import org.junit.jupiter.api.io.CleanupMode; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.api.parallel.ExecutionMode; +import org.junit.jupiter.params.converter.LocaleConversionFormat; /** * Caching implementation of the {@link JupiterConfiguration} API. @@ -138,4 +139,10 @@ public ExtensionContextScope getDefaultTestInstantiationExtensionContextScope() DEFAULT_TEST_INSTANTIATION_EXTENSION_CONTEXT_SCOPE_PROPERTY_NAME, __ -> delegate.getDefaultTestInstantiationExtensionContextScope()); } + @Override + public LocaleConversionFormat getDefaultLocaleConversionFormat() { + return (LocaleConversionFormat) cache.computeIfAbsent(DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME, + key -> delegate.getDefaultLocaleConversionFormat()); + } + } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java index b72b0362e638..8c25b6d46acc 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java @@ -14,6 +14,7 @@ import static org.junit.jupiter.api.io.CleanupMode.ALWAYS; import static org.junit.jupiter.api.io.TempDir.DEFAULT_CLEANUP_MODE_PROPERTY_NAME; import static org.junit.jupiter.api.io.TempDir.DEFAULT_FACTORY_PROPERTY_NAME; +import static org.junit.jupiter.params.converter.LocaleConversionFormat.ISO_639; import java.util.Optional; import java.util.function.Function; @@ -30,6 +31,7 @@ import org.junit.jupiter.api.io.CleanupMode; import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.api.parallel.ExecutionMode; +import org.junit.jupiter.params.converter.LocaleConversionFormat; import org.junit.platform.commons.util.ClassNamePatternFilterUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; @@ -66,6 +68,9 @@ public class DefaultJupiterConfiguration implements JupiterConfiguration { private static final EnumConfigurationParameterConverter extensionContextScopeConverter = // new EnumConfigurationParameterConverter<>(ExtensionContextScope.class, "extension context scope"); + private static final EnumConfigurationParameterConverter localeConversionFormatConverter = // + new EnumConfigurationParameterConverter<>(LocaleConversionFormat.class, "locale conversion format"); + private final ConfigurationParameters configurationParameters; public DefaultJupiterConfiguration(ConfigurationParameters configurationParameters) { @@ -156,4 +161,10 @@ public ExtensionContextScope getDefaultTestInstantiationExtensionContextScope() return extensionContextScopeConverter.get(configurationParameters, DEFAULT_TEST_INSTANTIATION_EXTENSION_CONTEXT_SCOPE_PROPERTY_NAME, ExtensionContextScope.DEFAULT); } + @Override + public LocaleConversionFormat getDefaultLocaleConversionFormat() { + return localeConversionFormatConverter.get(configurationParameters, + DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME, ISO_639); + } + } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/JupiterConfiguration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/JupiterConfiguration.java index b342054c5cbf..f67803b331a2 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/JupiterConfiguration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/JupiterConfiguration.java @@ -29,6 +29,7 @@ import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; +import org.junit.jupiter.params.converter.LocaleConversionFormat; /** * @since 5.4 @@ -47,6 +48,7 @@ public interface JupiterConfiguration { String DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME = MethodOrderer.DEFAULT_ORDER_PROPERTY_NAME; String DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME = ClassOrderer.DEFAULT_ORDER_PROPERTY_NAME;; String DEFAULT_TEST_INSTANTIATION_EXTENSION_CONTEXT_SCOPE_PROPERTY_NAME = ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; + String DEFAULT_LOCALE_CONVERSION_FORMAT_PROPERTY_NAME = "junit.jupiter.params.arguments.conversion.locale.format"; Optional getRawConfigurationParameter(String key); @@ -78,4 +80,6 @@ public interface JupiterConfiguration { ExtensionContextScope getDefaultTestInstantiationExtensionContextScope(); + LocaleConversionFormat getDefaultLocaleConversionFormat(); + } diff --git a/junit-jupiter-engine/src/module/org.junit.jupiter.engine/module-info.java b/junit-jupiter-engine/src/module/org.junit.jupiter.engine/module-info.java index 946b1dd3c6fb..b1a2a64ce810 100644 --- a/junit-jupiter-engine/src/module/org.junit.jupiter.engine/module-info.java +++ b/junit-jupiter-engine/src/module/org.junit.jupiter.engine/module-info.java @@ -20,6 +20,7 @@ module org.junit.jupiter.engine { requires static org.apiguardian.api; requires org.junit.jupiter.api; + requires org.junit.jupiter.params; requires org.junit.platform.commons; requires org.junit.platform.engine; requires org.opentest4j; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/LocaleConversionFormat.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/LocaleConversionFormat.java new file mode 100644 index 000000000000..28f4d5323f7a --- /dev/null +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/LocaleConversionFormat.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.params.converter; + +import static org.apiguardian.api.API.Status.INTERNAL; + +import org.apiguardian.api.API; + +/** + * Enumeration of {@link java.util.Locale} conversion formats. + * + * @since 5.11 + */ +@API(status = INTERNAL, since = "5.11") +public enum LocaleConversionFormat { + + /** + * The ISO 639 alpha-2 or alpha-3 language code format. + * + * @see java.util.Locale#Locale(String) + */ + ISO_639, + + /** + * The IETF BCP 47 language tag format. + * + * @see java.util.Locale#forLanguageTag(String) + */ + BCP_47 + +} diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/StringToLocaleConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/StringToLocaleConverter.java new file mode 100644 index 000000000000..dfd6009cf3a0 --- /dev/null +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/StringToLocaleConverter.java @@ -0,0 +1,37 @@ +/* + * Copyright 2015-2023 the original author or authors. + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v2.0 which + * accompanies this distribution and is available at + * + * https://www.eclipse.org/legal/epl-v20.html + */ + +package org.junit.jupiter.params.converter; + +import java.util.Locale; +import java.util.function.Function; + +import org.junit.platform.commons.util.Preconditions; + +class StringToLocaleConverter implements StringToObjectConverter { + + private final Function converter; + + StringToLocaleConverter(LocaleConversionFormat format) { + Preconditions.notNull(format, "format must not be null"); + this.converter = format == LocaleConversionFormat.ISO_639 ? Locale::new : Locale::forLanguageTag; + } + + @Override + public boolean canConvert(Class targetType) { + return targetType == Locale.class; + } + + @Override + public Object convert(String source, Class targetType) { + return converter.apply(source); + } + +} diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/CachingJupiterConfigurationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/CachingJupiterConfigurationTests.java index 5d1214a68972..7d82418f77a6 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/CachingJupiterConfigurationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/CachingJupiterConfigurationTests.java @@ -12,6 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.io.CleanupMode.NEVER; +import static org.junit.jupiter.params.converter.LocaleConversionFormat.ISO_639; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.only; import static org.mockito.Mockito.times; @@ -95,7 +96,7 @@ void cachesDefaultDisplayNameGenerator() { CustomDisplayNameGenerator customDisplayNameGenerator = new CustomDisplayNameGenerator(); when(delegate.getDefaultDisplayNameGenerator()).thenReturn(customDisplayNameGenerator); - // call `cache.getDefaultDisplayNameGenerator()` twice to verify the delegate method is called only once. + // call twice to verify the delegate method is called only once. assertThat(cache.getDefaultDisplayNameGenerator()).isSameAs(customDisplayNameGenerator); assertThat(cache.getDefaultDisplayNameGenerator()).isSameAs(customDisplayNameGenerator); @@ -107,7 +108,7 @@ void cachesDefaultTestMethodOrderer() { final Optional methodOrderer = Optional.of(new MethodOrderer.MethodName()); when(delegate.getDefaultTestMethodOrderer()).thenReturn(methodOrderer); - // call `cache.getDefaultTestMethodOrderer()` twice to verify the delegate method is called only once. + // call twice to verify the delegate method is called only once. assertThat(cache.getDefaultTestMethodOrderer()).isSameAs(methodOrderer); assertThat(cache.getDefaultTestMethodOrderer()).isSameAs(methodOrderer); @@ -118,7 +119,7 @@ void cachesDefaultTestMethodOrderer() { void cachesDefaultTempDirCleanupMode() { when(delegate.getDefaultTempDirCleanupMode()).thenReturn(NEVER); - // call `cache.getDefaultTempStrategyDirCleanupMode()` twice to verify the delegate method is called only once. + // call twice to verify the delegate method is called only once. assertThat(cache.getDefaultTempDirCleanupMode()).isSameAs(NEVER); assertThat(cache.getDefaultTempDirCleanupMode()).isSameAs(NEVER); @@ -130,13 +131,24 @@ void cachesDefaultTempDirFactorySupplier() { Supplier supplier = mock(); when(delegate.getDefaultTempDirFactorySupplier()).thenReturn(supplier); - // call `cache.getDefaultTempDirFactorySupplier()` twice to verify the delegate method is called only once. + // call twice to verify the delegate method is called only once. assertThat(cache.getDefaultTempDirFactorySupplier()).isSameAs(supplier); assertThat(cache.getDefaultTempDirFactorySupplier()).isSameAs(supplier); verify(delegate, only()).getDefaultTempDirFactorySupplier(); } + @Test + void cachesDefaultLocaleConversionFormat() { + when(delegate.getDefaultLocaleConversionFormat()).thenReturn(ISO_639); + + // call twice to verify the delegate method is called only once. + assertThat(cache.getDefaultLocaleConversionFormat()).isSameAs(ISO_639); + assertThat(cache.getDefaultLocaleConversionFormat()).isSameAs(ISO_639); + + verify(delegate, only()).getDefaultLocaleConversionFormat(); + } + @Test void doesNotCacheRawParameters() { when(delegate.getRawConfigurationParameter("foo")).thenReturn(Optional.of("bar")).thenReturn( diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java index a6c1d9919e56..310c43bc9767 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java @@ -17,6 +17,7 @@ import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD; import static org.junit.jupiter.api.io.CleanupMode.ALWAYS; import static org.junit.jupiter.engine.Constants.DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME; +import static org.junit.jupiter.params.converter.LocaleConversionFormat.ISO_639; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -34,6 +35,7 @@ import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.engine.Constants; import org.junit.jupiter.engine.descriptor.CustomDisplayNameGenerator; +import org.junit.jupiter.params.converter.LocaleConversionFormat; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.engine.ConfigurationParameters; @@ -145,6 +147,13 @@ void shouldGetStandardAsDefaultTempDirFactorySupplierWithoutConfigParamSet() { assertThat(supplier.get()).isSameAs(TempDirFactory.Standard.INSTANCE); } + @Test + void shouldGetDefaultLocaleConversionFormatWithNoConfigParamSet() { + JupiterConfiguration configuration = new DefaultJupiterConfiguration(mock()); + LocaleConversionFormat localeConversionFormat = configuration.getDefaultLocaleConversionFormat(); + assertThat(localeConversionFormat).isEqualTo(ISO_639); + } + private void assertDefaultConfigParam(String configValue, Lifecycle expected) { ConfigurationParameters configParams = mock(); when(configParams.get(KEY)).thenReturn(Optional.ofNullable(configValue)); diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt index 5c637457863f..f683f49b674e 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt @@ -2,6 +2,7 @@ org.junit.jupiter.engine@${jupiterVersion} jar:file:.+/junit-jupiter-engine-\d.+ requires java.base mandated requires org.apiguardian.api static requires org.junit.jupiter.api +requires org.junit.jupiter.params requires org.junit.platform.commons requires org.junit.platform.engine requires org.opentest4j