You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2020/09/07 19:14:22 UTC
[logging-log4j2] 02/03: Support shutdown timeout in JUnit 5
extension
This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 1fb8aaee0704cafbe074f9b5c180b4a87e2ae096
Author: Matt Sicker <bo...@gmail.com>
AuthorDate: Mon Sep 7 14:13:20 2020 -0500
Support shutdown timeout in JUnit 5 extension
This ports over the previous functionality to specify a custom shutdown timeout when stopping a LoggerContext in unit tests.
Signed-off-by: Matt Sicker <bo...@gmail.com>
---
.../logging/log4j/junit/LoggerContextResolver.java | 95 +++++++++++++++-------
.../logging/log4j/junit/LoggerContextRule.java | 3 +
.../logging/log4j/junit/LoggerContextSource.java | 11 +++
3 files changed, 80 insertions(+), 29 deletions(-)
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextResolver.java b/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextResolver.java
index fb0f367..3a92d3b 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextResolver.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextResolver.java
@@ -18,6 +18,7 @@
package org.apache.logging.log4j.junit;
import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.LoggerContextAccessor;
import org.apache.logging.log4j.core.config.Configurator;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
@@ -29,6 +30,7 @@ import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.support.TypeBasedParameterResolver;
import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
class LoggerContextResolver extends TypeBasedParameterResolver<LoggerContext> implements BeforeAllCallback,
AfterAllCallback, BeforeEachCallback, AfterEachCallback {
@@ -37,59 +39,64 @@ class LoggerContextResolver extends TypeBasedParameterResolver<LoggerContext> im
final Class<?> testClass = context.getRequiredTestClass();
final LoggerContextSource testSource = testClass.getAnnotation(LoggerContextSource.class);
if (testSource != null) {
- final LoggerContext loggerContext =
- Configurator.initialize(context.getDisplayName(), testClass.getClassLoader(), testSource.value());
- getTestClassStore(context).put(LoggerContext.class, loggerContext);
+ final LoggerContextConfig config = new LoggerContextConfig(testSource, context);
+ getTestClassStore(context).put(LoggerContext.class, config);
}
}
@Override
public void afterAll(ExtensionContext context) throws Exception {
- final LoggerContext loggerContext = getTestClassStore(context).get(LoggerContext.class, LoggerContext.class);
- if (loggerContext != null) {
- loggerContext.close();
+ final LoggerContextConfig config =
+ getTestClassStore(context).get(LoggerContext.class, LoggerContextConfig.class);
+ if (config != null) {
+ config.close();
}
}
@Override
public void beforeEach(ExtensionContext context) throws Exception {
final Class<?> testClass = context.getRequiredTestClass();
- final LoggerContextSource testSource = testClass.getAnnotation(LoggerContextSource.class);
- if (testSource != null && testSource.reconfigure() == ReconfigurationPolicy.BEFORE_EACH) {
- final LoggerContext loggerContext = getTestClassStore(context).get(LoggerContext.class, LoggerContext.class);
- if (loggerContext == null) {
+ if (testClass.isAnnotationPresent(LoggerContextSource.class)) {
+ final LoggerContextConfig config = getTestClassStore(context).get(LoggerContext.class, LoggerContextConfig.class);
+ if (config == null) {
throw new IllegalStateException(
- "Specified test class reconfiguration policy of BEFORE_EACH, but no LoggerContext found for test class " +
+ "Specified @LoggerContextSource but no LoggerContext found for test class " +
testClass.getCanonicalName());
}
- loggerContext.reconfigure();
+ if (config.reconfigurationPolicy == ReconfigurationPolicy.BEFORE_EACH) {
+ config.reconfigure();
+ }
}
final LoggerContextSource source = context.getRequiredTestMethod().getAnnotation(LoggerContextSource.class);
if (source != null) {
- final LoggerContext loggerContext = Configurator
- .initialize(context.getDisplayName(), testClass.getClassLoader(), source.value());
- getTestInstanceStore(context).put(LoggerContext.class, loggerContext);
+ final LoggerContextConfig config = new LoggerContextConfig(source, context);
+ if (config.reconfigurationPolicy == ReconfigurationPolicy.BEFORE_EACH) {
+ config.reconfigure();
+ }
+ getTestInstanceStore(context).put(LoggerContext.class, config);
}
}
@Override
public void afterEach(ExtensionContext context) throws Exception {
// method-annotated variant
- final LoggerContext testInstanceContext = getTestInstanceStore(context).get(LoggerContext.class, LoggerContext.class);
- if (testInstanceContext != null) {
- testInstanceContext.close();
+ final LoggerContextConfig testInstanceConfig =
+ getTestInstanceStore(context).get(LoggerContext.class, LoggerContextConfig.class);
+ if (testInstanceConfig != null) {
+ testInstanceConfig.close();
}
// reloadable variant
final Class<?> testClass = context.getRequiredTestClass();
- final LoggerContextSource source = testClass.getAnnotation(LoggerContextSource.class);
- if (source != null && source.reconfigure() == ReconfigurationPolicy.AFTER_EACH) {
- final LoggerContext loggerContext = getTestClassStore(context).get(LoggerContext.class, LoggerContext.class);
- if (loggerContext == null) {
+ if (testClass.isAnnotationPresent(LoggerContextSource.class)) {
+ final LoggerContextConfig config = getTestClassStore(context).get(LoggerContext.class, LoggerContextConfig.class);
+ if (config == null) {
throw new IllegalStateException(
- "Specified test class reconfiguration policy of AFTER_EACH, but no LoggerContext found for test class " +
+ "Specified @LoggerContextSource but no LoggerContext found for test class " +
testClass.getCanonicalName());
}
- loggerContext.reconfigure();
+ if (config.reconfigurationPolicy == ReconfigurationPolicy.AFTER_EACH) {
+ config.reconfigure();
+ }
}
}
@@ -109,12 +116,42 @@ class LoggerContextResolver extends TypeBasedParameterResolver<LoggerContext> im
static LoggerContext getParameterLoggerContext(ParameterContext parameterContext, ExtensionContext extensionContext) {
if (parameterContext.getDeclaringExecutable() instanceof Method) {
- final LoggerContext loggerContext =
- getTestInstanceStore(extensionContext).get(LoggerContext.class, LoggerContext.class);
- return loggerContext != null ? loggerContext :
- getTestClassStore(extensionContext).get(LoggerContext.class, LoggerContext.class);
+ final LoggerContextAccessor accessor =
+ getTestInstanceStore(extensionContext).get(LoggerContext.class, LoggerContextAccessor.class);
+ return accessor != null ? accessor.getLoggerContext() :
+ getTestClassStore(extensionContext).get(LoggerContext.class, LoggerContextAccessor.class).getLoggerContext();
+ }
+ return getTestClassStore(extensionContext).get(LoggerContext.class, LoggerContextAccessor.class).getLoggerContext();
+ }
+
+ private static class LoggerContextConfig implements AutoCloseable, LoggerContextAccessor {
+ private final LoggerContext context;
+ private final ReconfigurationPolicy reconfigurationPolicy;
+ private final long shutdownTimeout;
+ private final TimeUnit unit;
+
+ private LoggerContextConfig(final LoggerContextSource source, final ExtensionContext extensionContext) {
+ final String displayName = extensionContext.getDisplayName();
+ final ClassLoader classLoader = extensionContext.getRequiredTestClass().getClassLoader();
+ context = Configurator.initialize(displayName, classLoader, source.value());
+ reconfigurationPolicy = source.reconfigure();
+ shutdownTimeout = source.timeout();
+ unit = source.unit();
+ }
+
+ @Override
+ public LoggerContext getLoggerContext() {
+ return context;
+ }
+
+ public void reconfigure() {
+ context.reconfigure();
+ }
+
+ @Override
+ public void close() {
+ context.stop(shutdownTimeout, unit);
}
- return getTestClassStore(extensionContext).get(LoggerContext.class, LoggerContext.class);
}
}
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextRule.java b/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextRule.java
index 2215350..73a994a 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextRule.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextRule.java
@@ -42,6 +42,9 @@ import static org.junit.Assert.*;
* property {@code EBUG} is set (e.g., through the command line option {@code -DEBUG}), then the StatusLogger will be
* set to the debug level. This allows for more debug messages as the StatusLogger will be in the error level until a
* configuration file has been read and parsed into a tree of Nodes.
+ *
+ * @see LoggerContextSource
+ * @see Named
*/
public class LoggerContextRule implements TestRule, LoggerContextAccessor {
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextSource.java b/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextSource.java
index a6cedfb..e0cba27 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextSource.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextSource.java
@@ -29,6 +29,7 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.util.concurrent.TimeUnit;
/**
* Specifies a configuration file to use for unit tests. This configuration file will be loaded once and used for all tests
@@ -65,4 +66,14 @@ public @interface LoggerContextSource {
* Specifies when to {@linkplain LoggerContext#reconfigure() reconfigure} the logging system.
*/
ReconfigurationPolicy reconfigure() default ReconfigurationPolicy.NEVER;
+
+ /**
+ * Specifies the shutdown timeout limit. Defaults to 0 to mean no limit.
+ */
+ long timeout() default 0L;
+
+ /**
+ * Specifies the time unit {@link #timeout()} is measured in.
+ */
+ TimeUnit unit() default TimeUnit.SECONDS;
}