classOrderer();
+
/**
* Tags that should be included for continuous testing. This supports JUnit Tag Expressions.
*
@@ -77,7 +84,6 @@ public interface TestConfig {
* is matched against the test class name (not the file name).
*
* This is ignored if include-pattern has been set.
- *
*/
@WithDefault(".*\\.IT[^.]+|.*IT|.*ITCase")
Optional excludePattern();
@@ -241,7 +247,6 @@ public interface TestConfig {
* is matched against the module groupId:artifactId.
*
* This is ignored if include-module-pattern has been set.
- *
*/
Optional excludeModulePattern();
@@ -265,7 +270,7 @@ interface Profile {
* then Quarkus will only execute tests that are annotated with a {@code @TestProfile} that has at least one of the
* supplied (via the aforementioned system property) tags.
*/
- Optional> tags();
+ Optional> tags();
}
interface Container {
diff --git a/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java b/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java
index 2adc409fab8162..acdf1b2cf490da 100644
--- a/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java
+++ b/core/runtime/src/main/java/io/quarkus/runtime/configuration/QuarkusConfigFactory.java
@@ -1,5 +1,7 @@
package io.quarkus.runtime.configuration;
+import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+
import io.quarkus.runtime.LaunchMode;
import io.smallrye.config.SmallRyeConfig;
import io.smallrye.config.SmallRyeConfigFactory;
@@ -30,15 +32,12 @@ public SmallRyeConfig getConfigFor(final SmallRyeConfigProviderResolver configPr
}
public static void setConfig(SmallRyeConfig config) {
- SmallRyeConfigProviderResolver configProviderResolver = (SmallRyeConfigProviderResolver) SmallRyeConfigProviderResolver
- .instance();
+ ConfigProviderResolver configProviderResolver = ConfigProviderResolver.instance();
// Uninstall previous config
if (QuarkusConfigFactory.config != null) {
configProviderResolver.releaseConfig(QuarkusConfigFactory.config);
QuarkusConfigFactory.config = null;
}
- // Also release the TCCL config, in case that config was not QuarkusConfigFactory.config
- configProviderResolver.releaseConfig(Thread.currentThread().getContextClassLoader());
// Install new config
if (config != null) {
QuarkusConfigFactory.config = config;
diff --git a/core/runtime/src/main/java/io/quarkus/runtime/logging/LoggingSetupRecorder.java b/core/runtime/src/main/java/io/quarkus/runtime/logging/LoggingSetupRecorder.java
index 2d390ab877db0e..16238c5f45eac8 100644
--- a/core/runtime/src/main/java/io/quarkus/runtime/logging/LoggingSetupRecorder.java
+++ b/core/runtime/src/main/java/io/quarkus/runtime/logging/LoggingSetupRecorder.java
@@ -12,12 +12,10 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
-import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -31,7 +29,6 @@
import java.util.logging.LogRecord;
import org.eclipse.microprofile.config.ConfigProvider;
-import org.eclipse.microprofile.config.spi.ConfigSource;
import org.jboss.logmanager.ExtFormatter;
import org.jboss.logmanager.LogContext;
import org.jboss.logmanager.LogContextInitializer;
@@ -57,7 +54,6 @@
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.annotations.Recorder;
-import io.quarkus.runtime.configuration.QuarkusConfigBuilderCustomizer;
import io.quarkus.runtime.console.ConsoleRuntimeConfig;
import io.quarkus.runtime.logging.LogBuildTimeConfig.CategoryBuildTimeConfig;
import io.quarkus.runtime.logging.LogRuntimeConfig.CategoryConfig;
@@ -67,7 +63,6 @@
import io.quarkus.runtime.logging.LogRuntimeConfig.SocketConfig;
import io.quarkus.runtime.shutdown.ShutdownListener;
import io.smallrye.config.SmallRyeConfig;
-import io.smallrye.config.SmallRyeConfigBuilder;
@Recorder
public class LoggingSetupRecorder {
@@ -87,34 +82,9 @@ public static void handleFailedStart() {
public static void handleFailedStart(RuntimeValue>> banner) {
SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
- // There may be cases where a Config with the mappings is already available, but we can't be sure, so we wrap
- // the original Config and map the logging classes.
- SmallRyeConfig loggingConfig = new SmallRyeConfigBuilder()
- .withCustomizers(new QuarkusConfigBuilderCustomizer())
- .withMapping(LogBuildTimeConfig.class)
- .withMapping(LogRuntimeConfig.class)
- .withMapping(ConsoleRuntimeConfig.class)
- .withSources(new ConfigSource() {
- @Override
- public Set getPropertyNames() {
- Set properties = new HashSet<>();
- config.getPropertyNames().forEach(properties::add);
- return properties;
- }
-
- @Override
- public String getValue(final String propertyName) {
- return config.getRawValue(propertyName);
- }
-
- @Override
- public String getName() {
- return "Logging Config";
- }
- }).build();
- LogRuntimeConfig logRuntimeConfig = loggingConfig.getConfigMapping(LogRuntimeConfig.class);
- LogBuildTimeConfig logBuildTimeConfig = loggingConfig.getConfigMapping(LogBuildTimeConfig.class);
- ConsoleRuntimeConfig consoleRuntimeConfig = loggingConfig.getConfigMapping(ConsoleRuntimeConfig.class);
+ LogRuntimeConfig logRuntimeConfig = config.getConfigMapping(LogRuntimeConfig.class);
+ LogBuildTimeConfig logBuildTimeConfig = config.getConfigMapping(LogBuildTimeConfig.class);
+ ConsoleRuntimeConfig consoleRuntimeConfig = config.getConfigMapping(ConsoleRuntimeConfig.class);
new LoggingSetupRecorder(new RuntimeValue<>(consoleRuntimeConfig)).initializeLogging(logRuntimeConfig,
logBuildTimeConfig,
DiscoveredLogComponents.ofEmpty(), emptyMap(), false, null, emptyList(), emptyList(), emptyList(), emptyList(),
diff --git a/docs/src/main/asciidoc/getting-started-testing.adoc b/docs/src/main/asciidoc/getting-started-testing.adoc
index ab8ff2b88e4dce..786766184a4228 100644
--- a/docs/src/main/asciidoc/getting-started-testing.adoc
+++ b/docs/src/main/asciidoc/getting-started-testing.adoc
@@ -469,6 +469,8 @@ To get around this Quarkus supports the idea of a test profile. If a test has a
run test then Quarkus will be shut down and started with the new profile before running the tests. This is obviously
a bit slower, as it adds a shutdown/startup cycle to the test time, but gives a great deal of flexibility.
+// TODO - Rewrite docs
+
To reduce the amount of times Quarkus needs to restart, `io.quarkus.test.junit.util.QuarkusTestProfileAwareClassOrderer`
is registered as a global `ClassOrderer` as described in the
link:https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order-classes[JUnit 5 User Guide].
diff --git a/test-framework/common/src/main/java/io/quarkus/test/common/LauncherUtil.java b/test-framework/common/src/main/java/io/quarkus/test/common/LauncherUtil.java
index 22a4ed3fcca754..63c687909ef0bc 100644
--- a/test-framework/common/src/main/java/io/quarkus/test/common/LauncherUtil.java
+++ b/test-framework/common/src/main/java/io/quarkus/test/common/LauncherUtil.java
@@ -22,13 +22,10 @@
import java.util.regex.Pattern;
import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
-import io.quarkus.runtime.LaunchMode;
-import io.quarkus.runtime.configuration.ConfigUtils;
-import io.quarkus.runtime.configuration.QuarkusConfigFactory;
import io.quarkus.test.common.http.TestHTTPResourceManager;
import io.quarkus.utilities.OS;
-import io.smallrye.config.SmallRyeConfig;
public final class LauncherUtil {
@@ -38,9 +35,7 @@ private LauncherUtil() {
}
public static Config installAndGetSomeConfig() {
- SmallRyeConfig config = ConfigUtils.configBuilder(false, LaunchMode.NORMAL).build();
- QuarkusConfigFactory.setConfig(config);
- return config;
+ return ConfigProvider.getConfig();
}
/**
diff --git a/test-framework/common/src/main/java/io/quarkus/test/common/TestResourceManager.java b/test-framework/common/src/main/java/io/quarkus/test/common/TestResourceManager.java
index d5f606290bebe4..176751c654bf46 100644
--- a/test-framework/common/src/main/java/io/quarkus/test/common/TestResourceManager.java
+++ b/test-framework/common/src/main/java/io/quarkus/test/common/TestResourceManager.java
@@ -38,8 +38,6 @@
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
-import io.smallrye.config.SmallRyeConfigProviderResolver;
-
/**
* Manages {@link QuarkusTestResourceLifecycleManager}
*/
@@ -214,18 +212,6 @@ public void close() {
throw new RuntimeException("Unable to stop Quarkus test resource " + entry.getTestResource(), e);
}
}
- // TODO using QuarkusConfigFactory.setConfig(null) here makes continuous testing fail,
- // e.g. in io.quarkus.hibernate.orm.HibernateHotReloadTestCase
- // or io.quarkus.opentelemetry.deployment.OpenTelemetryContinuousTestingTest;
- // maybe this cleanup is not really necessary and just "doesn't hurt" because
- // the released config is still cached in QuarkusConfigFactory#config
- // and will be restored soon after when QuarkusConfigFactory#getConfigFor is called?
- // In that case we should remove this cleanup.
- try {
- ((SmallRyeConfigProviderResolver) SmallRyeConfigProviderResolver.instance())
- .releaseConfig(Thread.currentThread().getContextClassLoader());
- } catch (Throwable ignored) {
- }
configProperties.clear();
}
diff --git a/test-framework/junit5-config/pom.xml b/test-framework/junit5-config/pom.xml
new file mode 100644
index 00000000000000..9e5a21c6e54bb2
--- /dev/null
+++ b/test-framework/junit5-config/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+
+ io.quarkus
+ quarkus-test-framework
+ 999-SNAPSHOT
+
+
+ quarkus-junit5-config
+ Quarkus - Test Framework - JUnit 5 Config
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+
+
+ io.smallrye.config
+ smallrye-config
+
+
+ io.quarkus
+ quarkus-core
+
+
+ io.quarkus
+ quarkus-core-deployment
+
+
+
+
diff --git a/test-framework/junit5-config/src/main/java/io/quarkus/test/config/LoggingSetupExtension.java b/test-framework/junit5-config/src/main/java/io/quarkus/test/config/LoggingSetupExtension.java
new file mode 100644
index 00000000000000..13ae524d8de99c
--- /dev/null
+++ b/test-framework/junit5-config/src/main/java/io/quarkus/test/config/LoggingSetupExtension.java
@@ -0,0 +1,14 @@
+package io.quarkus.test.config;
+
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.Extension;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+import io.quarkus.runtime.logging.LoggingSetupRecorder;
+
+public class LoggingSetupExtension implements Extension, BeforeAllCallback {
+ @Override
+ public void beforeAll(final ExtensionContext context) throws Exception {
+ LoggingSetupRecorder.handleFailedStart();
+ }
+}
diff --git a/test-framework/junit5-config/src/main/java/io/quarkus/test/config/QuarkusClassOrderer.java b/test-framework/junit5-config/src/main/java/io/quarkus/test/config/QuarkusClassOrderer.java
new file mode 100644
index 00000000000000..1a39f11b12884e
--- /dev/null
+++ b/test-framework/junit5-config/src/main/java/io/quarkus/test/config/QuarkusClassOrderer.java
@@ -0,0 +1,45 @@
+package io.quarkus.test.config;
+
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+import org.junit.jupiter.api.ClassOrderer;
+import org.junit.jupiter.api.ClassOrdererContext;
+import org.junit.platform.commons.util.ReflectionUtils;
+
+import io.quarkus.deployment.dev.testing.TestConfig;
+import io.quarkus.runtime.LaunchMode;
+import io.smallrye.config.SmallRyeConfig;
+
+public class QuarkusClassOrderer implements ClassOrderer {
+ private final ClassOrderer delegate;
+
+ static {
+ TestConfigProviderResolver resolver = new TestConfigProviderResolver();
+ ConfigProviderResolver.setInstance(resolver);
+ resolver.getConfig(LaunchMode.TEST);
+ }
+
+ public QuarkusClassOrderer() {
+ SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
+ TestConfig testConfig = config.getConfigMapping(TestConfig.class);
+
+ delegate = testConfig.classOrderer()
+ .map(klass -> ReflectionUtils.tryToLoadClass(klass)
+ .andThenTry(ReflectionUtils::newInstance)
+ .andThenTry(instance -> (ClassOrderer) instance)
+ .toOptional().orElse(EMPTY))
+ .orElse(EMPTY);
+ }
+
+ @Override
+ public void orderClasses(final ClassOrdererContext context) {
+ delegate.orderClasses(context);
+ }
+
+ private static final ClassOrderer EMPTY = new ClassOrderer() {
+ @Override
+ public void orderClasses(final ClassOrdererContext context) {
+
+ }
+ };
+}
diff --git a/test-framework/junit5-config/src/main/java/io/quarkus/test/config/TestConfigProviderResolver.java b/test-framework/junit5-config/src/main/java/io/quarkus/test/config/TestConfigProviderResolver.java
new file mode 100644
index 00000000000000..458f28c26bf544
--- /dev/null
+++ b/test-framework/junit5-config/src/main/java/io/quarkus/test/config/TestConfigProviderResolver.java
@@ -0,0 +1,74 @@
+package io.quarkus.test.config;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+
+import org.eclipse.microprofile.config.Config;
+
+import io.quarkus.deployment.dev.testing.TestConfig;
+import io.quarkus.runtime.LaunchMode;
+import io.quarkus.runtime.configuration.ConfigUtils;
+import io.smallrye.config.SmallRyeConfig;
+import io.smallrye.config.SmallRyeConfigBuilder;
+import io.smallrye.config.SmallRyeConfigProviderResolver;
+
+public class TestConfigProviderResolver extends SmallRyeConfigProviderResolver {
+ private static final SmallRyeConfigProviderResolver resolver = (SmallRyeConfigProviderResolver) SmallRyeConfigProviderResolver
+ .instance();
+
+ private static final Map configs = new ConcurrentHashMap<>();
+ private static final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+ @Override
+ public Config getConfig() {
+ return resolver.getConfig();
+ }
+
+ public Config getConfig(final LaunchMode mode) {
+ if (classLoader.equals(Thread.currentThread().getContextClassLoader())) {
+ resolver.releaseConfig(classLoader);
+ SmallRyeConfig config = configs.computeIfAbsent(mode, new Function() {
+ @Override
+ public SmallRyeConfig apply(final LaunchMode launchMode) {
+ return ConfigUtils.configBuilder(false, true, mode)
+ .withProfile(mode.getDefaultProfile())
+ .withMapping(TestConfig.class, "quarkus.test")
+ .build();
+ }
+ });
+ resolver.registerConfig(config, classLoader);
+ return config;
+ }
+ throw new IllegalStateException();
+ }
+
+ public void restoreConfig() {
+ if (classLoader.equals(Thread.currentThread().getContextClassLoader())) {
+ resolver.releaseConfig(classLoader);
+ resolver.registerConfig(configs.get(LaunchMode.TEST), classLoader);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ @Override
+ public Config getConfig(final ClassLoader loader) {
+ return resolver.getConfig(loader);
+ }
+
+ @Override
+ public SmallRyeConfigBuilder getBuilder() {
+ return resolver.getBuilder();
+ }
+
+ @Override
+ public void registerConfig(final Config config, final ClassLoader classLoader) {
+ resolver.registerConfig(config, classLoader);
+ }
+
+ @Override
+ public void releaseConfig(final Config config) {
+ resolver.releaseConfig(config);
+ }
+}
diff --git a/test-framework/junit5-config/src/main/resources/META-INF/services/org.junit.jupiter.api.extension.Extension b/test-framework/junit5-config/src/main/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
new file mode 100644
index 00000000000000..a91b69862a876f
--- /dev/null
+++ b/test-framework/junit5-config/src/main/resources/META-INF/services/org.junit.jupiter.api.extension.Extension
@@ -0,0 +1 @@
+io.quarkus.test.config.LoggingSetupExtension
diff --git a/test-framework/junit5-config/src/main/resources/junit-platform.properties b/test-framework/junit5-config/src/main/resources/junit-platform.properties
new file mode 100644
index 00000000000000..d24c3ed5820f5e
--- /dev/null
+++ b/test-framework/junit5-config/src/main/resources/junit-platform.properties
@@ -0,0 +1,2 @@
+junit.jupiter.extensions.autodetection.enabled=true
+junit.jupiter.testclass.order.default=io.quarkus.test.config.QuarkusClassOrderer
diff --git a/test-framework/junit5-internal/pom.xml b/test-framework/junit5-internal/pom.xml
index 526869cab070b5..9bd5cf5b47f477 100644
--- a/test-framework/junit5-internal/pom.xml
+++ b/test-framework/junit5-internal/pom.xml
@@ -39,6 +39,10 @@
junit-jupiter-engine
compile