You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by pk...@apache.org on 2023/09/21 15:02:53 UTC

[logging-log4j2] branch main updated: Order test properties before status listener

This is an automated email from the ASF dual-hosted git repository.

pkarwasz pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/main by this push:
     new e3a49bdf0f Order test properties before status listener
e3a49bdf0f is described below

commit e3a49bdf0f5383da16eafbeb1fa7f661447a8cbe
Author: Piotr P. Karwasz <pi...@karwasz.org>
AuthorDate: Thu Sep 21 16:50:43 2023 +0200

    Order test properties before status listener
    
    If the status listener extension is active, it will start the static
    initialization of `StatusLogger`, which means that many constants (like
    IS_WEB_APP) will receive their default value.
---
 .../log4j/test/junit/StatusLoggerExtension.java    | 60 +++++++++++++++++++---
 .../log4j/test/junit/UsingStatusListener.java      |  3 +-
 2 files changed, 54 insertions(+), 9 deletions(-)

diff --git a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/StatusLoggerExtension.java b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/StatusLoggerExtension.java
index cdbc220b49..3cc54a386e 100644
--- a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/StatusLoggerExtension.java
+++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/StatusLoggerExtension.java
@@ -17,12 +17,15 @@
 package org.apache.logging.log4j.test.junit;
 
 import java.io.IOException;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Stream;
 
 import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.status.StatusConsoleListener;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.message.ParameterizedNoReferenceMessageFactory;
+import org.apache.logging.log4j.simple.SimpleLogger;
 import org.apache.logging.log4j.status.StatusData;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.test.ListStatusListener;
@@ -30,15 +33,17 @@ import org.junit.jupiter.api.extension.BeforeAllCallback;
 import org.junit.jupiter.api.extension.BeforeEachCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
 import org.junit.jupiter.api.extension.ExtensionContext.Store.CloseableResource;
+import org.junit.jupiter.api.extension.ExtensionContextException;
 import org.junit.jupiter.api.extension.ParameterContext;
 import org.junit.jupiter.api.extension.ParameterResolutionException;
 import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
+import org.junit.platform.commons.support.HierarchyTraversalMode;
+import org.junit.platform.commons.support.ModifierSupport;
+import org.junit.platform.commons.support.ReflectionSupport;
 
 class StatusLoggerExtension extends TypeBasedParameterResolver<ListStatusListener>
         implements BeforeAllCallback, BeforeEachCallback, TestExecutionExceptionHandler {
 
-    private static final StatusLogger LOGGER = StatusLogger.getLogger();
-    private static final StatusConsoleListener CONSOLE_LISTENER = new StatusConsoleListener(Level.ALL);
     private static final Object KEY = ListStatusListener.class;
 
     public StatusLoggerExtension() {
@@ -51,6 +56,16 @@ class StatusLoggerExtension extends TypeBasedParameterResolver<ListStatusListene
         // `beforeAll` methods and extensions.
         final ListStatusListenerHolder holder = new ListStatusListenerHolder(context, null);
         ExtensionContextAnchor.setAttribute(KEY, holder, context);
+        ReflectionSupport.findFields(context.getRequiredTestClass(),
+                f -> ModifierSupport.isStatic(f) && f.getType().equals(ListStatusListener.class),
+                HierarchyTraversalMode.TOP_DOWN).forEach(f -> {
+            try {
+                f.setAccessible(true);
+                f.set(null, holder.getStatusListener());
+            } catch (final ReflectiveOperationException e) {
+                throw new ExtensionContextException("Failed to inject field.", e);
+            }
+        });
     }
 
     @Override
@@ -61,12 +76,26 @@ class StatusLoggerExtension extends TypeBasedParameterResolver<ListStatusListene
         final ListStatusListener parent = parentHolder != null ? parentHolder.getStatusListener() : null;
         final ListStatusListenerHolder holder = new ListStatusListenerHolder(context, parent);
         ExtensionContextAnchor.setAttribute(KEY, holder, context);
+        ReflectionSupport.findFields(context.getRequiredTestClass(),
+                f -> ModifierSupport.isNotStatic(f) && f.getType().equals(ListStatusListener.class),
+                HierarchyTraversalMode.TOP_DOWN).forEach(f -> {
+            try {
+                f.setAccessible(true);
+                f.set(context.getRequiredTestInstance(), holder.getStatusListener());
+            } catch (final ReflectiveOperationException e) {
+                throw new ExtensionContextException("Failed to inject field.", e);
+            }
+        });
     }
 
     @Override
     public void handleTestExecutionException(final ExtensionContext context, final Throwable throwable) throws Throwable {
-        final ListStatusListener statusListener = resolveParameter(null, context);
-        statusListener.getStatusData().forEach(CONSOLE_LISTENER::log);
+        final ListStatusListenerHolder holder = ExtensionContextAnchor.getAttribute(KEY,
+                ListStatusListenerHolder.class,
+                context);
+        if (holder != null) {
+            holder.handleException(context, throwable);
+        }
         throw throwable;
     }
 
@@ -80,11 +109,13 @@ class StatusLoggerExtension extends TypeBasedParameterResolver<ListStatusListene
 
     private static class ListStatusListenerHolder implements CloseableResource {
 
+        private final StatusLogger statusLogger;
         private final ListStatusListener statusListener;
 
         public ListStatusListenerHolder(final ExtensionContext context, final ListStatusListener parent) {
+            this.statusLogger = StatusLogger.getLogger();
             this.statusListener = new JUnitListStatusListener(context, parent);
-            LOGGER.registerListener(statusListener);
+            statusLogger.registerListener(statusListener);
         }
 
         public ListStatusListener getStatusListener() {
@@ -93,9 +124,24 @@ class StatusLoggerExtension extends TypeBasedParameterResolver<ListStatusListene
 
         @Override
         public void close() throws Throwable {
-            LOGGER.removeListener(statusListener);
+            statusLogger.removeListener(statusListener);
         }
 
+        public void handleException(final ExtensionContext context, final Throwable throwable) {
+            final Logger logger = new SimpleLogger("StatusLoggerExtension",
+                    ParameterizedNoReferenceMessageFactory.INSTANCE,
+                    System.err,
+                    Level.ALL,
+                    new SimpleDateFormat("HH:mm:ss.SSS"),
+                    true);
+            logger.error("Test {} failed.\nDumping status data:", context.getDisplayName());
+            statusListener.getStatusData().forEach(data -> {
+                logger.atLevel(data.getLevel())
+                        .withThrowable(data.getThrowable())
+                        .withLocation(data.getStackTraceElement())
+                        .log(data.getMessage());
+            });
+        }
     }
 
     private static class JUnitListStatusListener implements ListStatusListener {
diff --git a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/UsingStatusListener.java b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/UsingStatusListener.java
index 14ed2e8bd8..a54951f32a 100644
--- a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/UsingStatusListener.java
+++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/UsingStatusListener.java
@@ -17,7 +17,6 @@
 package org.apache.logging.log4j.test.junit;
 
 import java.lang.annotation.Documented;
-import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 
@@ -36,9 +35,9 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
  */
 @Retention(RUNTIME)
 @Target({ TYPE, METHOD })
-@Inherited
 @Documented
 @ExtendWith(ExtensionContextAnchor.class)
+@ExtendWith(TestPropertyResolver.class)
 @ExtendWith(StatusLoggerExtension.class)
 public @interface UsingStatusListener {
 }