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/01/20 06:54:42 UTC

[logging-log4j2] branch master updated (15c185c62f -> 9f266e107c)

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

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


    from 15c185c62f LOG4J2-3628 Replace `maven-changes-plugin` with `log4j-changelog` (#1146)
     new 4d34d2f856 LOG4J2-3538 Added support for 24 colors in highlighting (#933)
     new 603f260cd3 LOG4J2-3537 Fixes problem with wrong ANSI escape code for bright colors (#935)
     new 3f36f9aa9d [LOG4J2-3561] Support both whitespace and commas in %style
     new 26b55db890 Add JUnit 5 extension to store per-test status messages
     new 9f266e107c Do not interpret "disableAnsi" and "noConsoleNoAnsi" as escapes

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 ...TestProperties.java => ListStatusListener.java} |  26 +--
 .../log4j/test/junit/StatusLoggerExtension.java    | 122 ++++++++++++++
 ...estProperties.java => UsingStatusListener.java} |  21 ++-
 .../log4j/core/pattern/HighlightConverterTest.java |  43 ++++-
 .../log4j/core/pattern/StyleConverterTest.java     |  47 ++++++
 .../logging/log4j/core/pattern/AnsiEscape.java     | 176 ++++++++++++++++++++-
 .../logging/log4j/core/pattern/StyleConverter.java |   2 +-
 .../apache/logging/log4j/core/util/Patterns.java   |   5 +
 8 files changed, 409 insertions(+), 33 deletions(-)
 copy log4j-api-test/src/main/java/org/apache/logging/log4j/test/{TestProperties.java => ListStatusListener.java} (57%)
 create mode 100644 log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/StatusLoggerExtension.java
 copy log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/{UsingTestProperties.java => UsingStatusListener.java} (71%)


[logging-log4j2] 03/05: [LOG4J2-3561] Support both whitespace and commas in %style

Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 3f36f9aa9dafc17bc0e04657fbcc87ff7e4f3f00
Author: Piotr P. Karwasz <pi...@karwasz.org>
AuthorDate: Thu Jul 28 09:22:27 2022 +0200

    [LOG4J2-3561] Support both whitespace and commas in %style
    
    The %style pattern is inconsistent with the %highlight pattern: the
    first separates styles with commas, the second one with spaces. This
    should
---
 .../log4j/core/pattern/HighlightConverterTest.java | 47 ++++++++++------------
 .../log4j/core/pattern/StyleConverterTest.java     | 31 +++++++++++++-
 .../logging/log4j/core/pattern/StyleConverter.java |  2 +-
 .../apache/logging/log4j/core/util/Patterns.java   |  5 +++
 4 files changed, 58 insertions(+), 27 deletions(-)

diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
index 8a44c6096c..c98be60aa1 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
@@ -16,11 +16,16 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.util.stream.Stream;
+
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -77,36 +82,28 @@ public class HighlightConverterTest {
         assertEquals(AnsiEscape.createSequence(colorName), converter.getLevelStyle(Level.DEBUG));
     }
 
-   private void testLevelNames(final String colorName, final String expectedOutput) {
-        final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false, "
-                + PatternParser.DISABLE_ANSI + "=false, " + "INFO=" + colorName};
+    static Stream<Arguments> colors() {
+        return Stream.of(
+                Arguments.of("bright red","\u001B[1;31m"),
+                Arguments.of("red bright", "\u001B[31;1m"),
+                Arguments.of("bright_red", "\u001B[91m"),
+                Arguments.of("#1cd42b", "\u001B[38;2;28;212;43m"),
+                Arguments.of("fg_bright_red bg_bright_blue bold", "\u001B[91;104;1m"),
+                Arguments.of("FG_#1cd42b BG_#000000", "\u001B[38;2;28;212;43;48;2;0;0;0m"));
+    }
+
+    @ParameterizedTest
+    @MethodSource("colors")
+    public void testColors(final String colorName, final String escape) {
+        final String[] options = { "%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false, "
+                + PatternParser.DISABLE_ANSI + "=false, " + "INFO=" + colorName };
         final HighlightConverter converter = HighlightConverter.newInstance(null, options);
         assertNotNull(converter);
 
-        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
-                new SimpleMessage("")).build();
+        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).build();
         final StringBuilder buffer = new StringBuilder();
         converter.format(event, buffer);
-        assertEquals(expectedOutput, buffer.toString());
-   }
-
-    @Test
-    public void testLevelNamesBrightShort() {
-        testLevelNames("bright_red", "\u001B[91mINFO : \u001B[m");
-    }
-
-    public void testLevelNamesHexShort() {
-        testLevelNames("#1cd42b", "\u001B[38;2;28;212;43mINFO : \u001B[m");
-    }
-
-    @Test
-    public void testLevelNamesBrightFull() {
-        testLevelNames("fg_bright_red bg_bright_blue bold", "\u001B[91;104;1mINFO : \u001B[m");
-    }
-
-    @Test
-    public void testLevelNamesHexFull() {
-        testLevelNames("FG_#1cd42b BG_#000000", "\u001B[38;2;28;212;43;48;2;0;0;0mINFO : \u001B[m");
+        assertEquals(escape + "INFO : \u001B[m", buffer.toString());
     }
 
     @Test
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java
index fefd76f669..db9d5ea358 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java
@@ -18,17 +18,25 @@ package org.apache.logging.log4j.core.pattern;
 
 import java.util.List;
 
+import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.core.impl.Log4jProperties;
 import org.apache.logging.log4j.core.test.appender.ListAppender;
 import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
 import org.apache.logging.log4j.core.test.junit.Named;
 import org.apache.logging.log4j.util.Strings;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.junitpioneer.jupiter.SetSystemProperty;
 
-import static org.junit.jupiter.api.Assertions.*;
+import static org.junit.Assert.assertNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @SetSystemProperty(key = Log4jProperties.JANSI_DISABLED, value = "false")
 public class StyleConverterTest {
@@ -54,4 +62,25 @@ public class StyleConverterTest {
     public void testNull() {
         assertNull(StyleConverter.newInstance(null, null));
     }
+
+    @ParameterizedTest
+    @MethodSource("org.apache.logging.log4j.core.pattern.HighlightConverterTest#colors")
+    public void testHighlightConverterCompatibility(final String color, final String escape) {
+        final StyleConverter converter = StyleConverter.newInstance(null, new String[] { "Hello!", color });
+        final StringBuilder sb = new StringBuilder();
+        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).build();
+        converter.format(event, sb);
+        assertEquals(escape + "Hello!" + AnsiEscape.getDefaultStyle(), sb.toString());
+    }
+
+    @ParameterizedTest
+    @MethodSource("org.apache.logging.log4j.core.pattern.HighlightConverterTest#colors")
+    public void testLegacyCommaSeparator(final String color, final String escape) {
+        final StyleConverter converter = StyleConverter.newInstance(null,
+                new String[] { "Hello!", color.replaceAll("\\s+", ",") });
+        final StringBuilder sb = new StringBuilder();
+        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).build();
+        converter.format(event, sb);
+        assertEquals(escape + "Hello!" + AnsiEscape.getDefaultStyle(), sb.toString());
+    }
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
index e102f7306a..bad779148e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/StyleConverter.java
@@ -95,7 +95,7 @@ public final class StyleConverter extends LogEventPatternConverter implements An
         }
         final PatternParser parser = PatternLayout.createPatternParser(config);
         final List<PatternFormatter> formatters = parser.parse(options[0]);
-        final String style = AnsiEscape.createSequence(options[1].split(Patterns.COMMA_SEPARATOR));
+        final String style = AnsiEscape.createSequence(options[1].split(Patterns.COMMA_SPACE_SEPARATOR));
         final boolean disableAnsi = Arrays.toString(options).contains(PatternParser.DISABLE_ANSI + "=true");
         final boolean noConsoleNoAnsi = Arrays.toString(options).contains(PatternParser.NO_CONSOLE_NO_ANSI + "=true");
         final boolean hideAnsi = disableAnsi || (noConsoleNoAnsi && System.console() == null);
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Patterns.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Patterns.java
index 5427197072..cd329f9307 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Patterns.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Patterns.java
@@ -28,6 +28,11 @@ public final class Patterns {
      */
     public static final String COMMA_SEPARATOR = toWhitespaceSeparator(",");
 
+    /**
+     * A pattern string for lists separated by commas with optional whitespace or just whitespace.
+     */
+    public static final String COMMA_SPACE_SEPARATOR = toWhitespaceSeparator("[,\\s]");
+
     /**
      * The whitespace pattern string.
      */


[logging-log4j2] 05/05: Do not interpret "disableAnsi" and "noConsoleNoAnsi" as escapes

Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9f266e107c179cccb4c5e9bf6228c45435649c2d
Author: Piotr P. Karwasz <pi...@karwasz.org>
AuthorDate: Sat Jan 14 15:21:21 2023 +0100

    Do not interpret "disableAnsi" and "noConsoleNoAnsi" as escapes
    
    By explitly ignoring "disableAnsi=..." and "noConsoleNoAnsi=..." in
    `AnsiEscape`, this closes #1202.
---
 .../log4j/core/pattern/HighlightConverterTest.java     | 11 +++++++++--
 .../logging/log4j/core/pattern/StyleConverterTest.java | 18 ++++++++++++++++++
 .../apache/logging/log4j/core/pattern/AnsiEscape.java  |  4 ++++
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
index c98be60aa1..50192ccacc 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
@@ -22,11 +22,14 @@ import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.test.ListStatusListener;
+import org.apache.logging.log4j.test.junit.UsingStatusListener;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.*;
 
 /**
@@ -139,10 +142,12 @@ public class HighlightConverterTest {
     }
 
     @Test
-    public void testNoAnsiEmpty() {
+    @UsingStatusListener
+    public void testNoAnsiEmpty(ListStatusListener listener) {
         final String[] options = {"", PatternParser.DISABLE_ANSI + "=true"};
         final HighlightConverter converter = HighlightConverter.newInstance(null, options);
         assertNotNull(converter);
+        assertThat(listener.findStatusData(Level.WARN)).isEmpty();
 
         final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
                 new SimpleMessage("message in a bottle")).build();
@@ -152,10 +157,12 @@ public class HighlightConverterTest {
     }
 
     @Test
-    public void testNoAnsiNonEmpty() {
+    @UsingStatusListener
+    public void testNoAnsiNonEmpty(ListStatusListener listener) {
         final String[] options = {"%-5level: %msg", PatternParser.DISABLE_ANSI + "=true"};
         final HighlightConverter converter = HighlightConverter.newInstance(null, options);
         assertNotNull(converter);
+        assertThat(listener.findStatusData(Level.WARN)).isEmpty();
 
         final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
                 new SimpleMessage("message in a bottle")).build();
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java
index db9d5ea358..5794091bcf 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/StyleConverterTest.java
@@ -27,13 +27,17 @@ import org.apache.logging.log4j.core.impl.Log4jProperties;
 import org.apache.logging.log4j.core.test.appender.ListAppender;
 import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
 import org.apache.logging.log4j.core.test.junit.Named;
+import org.apache.logging.log4j.test.ListStatusListener;
+import org.apache.logging.log4j.test.junit.UsingStatusListener;
 import org.apache.logging.log4j.util.Strings;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
 import org.junitpioneer.jupiter.SetSystemProperty;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertNull;
+import static org.junit.jupiter.api.Assertions.*;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -83,4 +87,18 @@ public class StyleConverterTest {
         converter.format(event, sb);
         assertEquals(escape + "Hello!" + AnsiEscape.getDefaultStyle(), sb.toString());
     }
+
+    @Test
+    @UsingStatusListener
+    public void testNoAnsiNoWarnings(ListStatusListener listener) {
+        StyleConverter converter = StyleConverter.newInstance(null, new String[] { "", "disableAnsi=true" });
+        assertThat(converter).isNotNull();
+        converter = StyleConverter.newInstance(null, new String[] { "", "noConsoleNoAnsi=true" });
+        assertThat(converter).isNotNull();
+        converter = StyleConverter.newInstance(null, new String[] { "", "INVALID_STYLE" });
+        assertThat(converter).isNotNull();
+        assertThat(listener.findStatusData(Level.WARN)).hasSize(1)
+                .extracting(data -> data.getMessage().getFormattedMessage())
+                .containsExactly("The style attribute INVALID_STYLE is incorrect.");
+    }
 }
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
index c7f8cca9e5..5cdcfed6e5 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
@@ -451,6 +451,10 @@ public enum AnsiEscape {
         boolean first = true;
         for (final String name : names) {
             try {
+                // GitHub Issue #1202
+                if (name.startsWith(PatternParser.DISABLE_ANSI) || name.startsWith(PatternParser.NO_CONSOLE_NO_ANSI)) {
+                    continue;
+                }
                 if (!first) {
                     sb.append(AnsiEscape.SEPARATOR.getCode());
                 }


[logging-log4j2] 02/05: LOG4J2-3537 Fixes problem with wrong ANSI escape code for bright colors (#935)

Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 603f260cd3d17d46526b75646f5a7b1acdd63e8f
Author: PashaTurok <oo...@mail.ru>
AuthorDate: Sun Jun 19 12:26:14 2022 +0300

    LOG4J2-3537 Fixes problem with wrong ANSI escape code for bright colors (#935)
    
    Fixes problem with wrong ANSI escape code for bright colors
---
 .../log4j/core/pattern/HighlightConverterTest.java |  32 ++---
 .../logging/log4j/core/pattern/AnsiEscape.java     | 131 ++++++++++++++++++++-
 2 files changed, 147 insertions(+), 16 deletions(-)

diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
index a704d44c6a..8a44c6096c 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
@@ -77,9 +77,7 @@ public class HighlightConverterTest {
         assertEquals(AnsiEscape.createSequence(colorName), converter.getLevelStyle(Level.DEBUG));
     }
 
-    @Test
-    public void testLevelNamesHexShort() {
-        final String colorName = "#1cd42b";
+   private void testLevelNames(final String colorName, final String expectedOutput) {
         final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false, "
                 + PatternParser.DISABLE_ANSI + "=false, " + "INFO=" + colorName};
         final HighlightConverter converter = HighlightConverter.newInstance(null, options);
@@ -89,22 +87,26 @@ public class HighlightConverterTest {
                 new SimpleMessage("")).build();
         final StringBuilder buffer = new StringBuilder();
         converter.format(event, buffer);
-        assertEquals("\u001B[38;2;28;212;43mINFO : \u001B[m", buffer.toString());
+        assertEquals(expectedOutput, buffer.toString());
+   }
+
+    @Test
+    public void testLevelNamesBrightShort() {
+        testLevelNames("bright_red", "\u001B[91mINFO : \u001B[m");
+    }
+
+    public void testLevelNamesHexShort() {
+        testLevelNames("#1cd42b", "\u001B[38;2;28;212;43mINFO : \u001B[m");
     }
 
     @Test
-    public void testLevelNamesHexFull() {
-        final String colorName = "FG_#1cd42b BG_#000000";
-        final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false, "
-                + PatternParser.DISABLE_ANSI + "=false, " + "INFO=" + colorName};
-        final HighlightConverter converter = HighlightConverter.newInstance(null, options);
-        assertNotNull(converter);
+    public void testLevelNamesBrightFull() {
+        testLevelNames("fg_bright_red bg_bright_blue bold", "\u001B[91;104;1mINFO : \u001B[m");
+    }
 
-        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
-                new SimpleMessage("")).build();
-        final StringBuilder buffer = new StringBuilder();
-        converter.format(event, buffer);
-        assertEquals("\u001B[38;2;28;212;43;48;2;0;0;0mINFO : \u001B[m", buffer.toString());
+    @Test
+    public void testLevelNamesHexFull() {
+        testLevelNames("FG_#1cd42b BG_#000000", "\u001B[38;2;28;212;43;48;2;0;0;0mINFO : \u001B[m");
     }
 
     @Test
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
index b7f703fa63..c7f8cca9e5 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
@@ -61,9 +61,18 @@ public enum AnsiEscape {
 
     /**
      * Bright general attribute.
+     *
+     * @deprecated This attribute sets font-weight as "bold" and doesn't set color brightness. Use BOLD if you
+     * need to change font-weight and BRIGHT_* to use a bright color.
+     *
      */
     BRIGHT("1"),
 
+    /**
+     * Bold general attribute.
+     */
+    BOLD("1"),
+
     /**
      * Dim general attribute.
      */
@@ -217,7 +226,127 @@ public enum AnsiEscape {
     /**
      * White background color.
      */
-    BG_WHITE("47");
+    BG_WHITE("47"),
+
+    /**
+     * Bright black foreground color.
+     */
+    BRIGHT_BLACK("90"),
+
+    /**
+     * Bright black foreground color.
+     */
+    FG_BRIGHT_BLACK("90"),
+
+    /**
+     * Bright red foreground color.
+     */
+    BRIGHT_RED("91"),
+
+    /**
+     * Bright red foreground color.
+     */
+    FG_BRIGHT_RED("91"),
+
+    /**
+     * Bright green foreground color.
+     */
+    BRIGHT_GREEN("92"),
+
+    /**
+     * Bright green foreground color.
+     */
+    FG_BRIGHT_GREEN("92"),
+
+    /**
+     * Bright yellow foreground color.
+     */
+    BRIGHT_YELLOW("93"),
+
+    /**
+     * Bright yellow foreground color.
+     */
+    FG_BRIGHT_YELLOW("93"),
+
+    /**
+     * Bright blue foreground color.
+     */
+    BRIGHT_BLUE("94"),
+
+    /**
+     * Bright blue foreground color.
+     */
+    FG_BRIGHT_BLUE("94"),
+
+    /**
+     * Bright magenta foreground color.
+     */
+    BRIGHT_MAGENTA("95"),
+
+    /**
+     * Bright magenta foreground color.
+     */
+    FG_BRIGHT_MAGENTA("95"),
+
+    /**
+     * Bright cyan foreground color.
+     */
+    BRIGHT_CYAN("96"),
+
+    /**
+     * Bright cyan foreground color.
+     */
+    FG_BRIGHT_CYAN("96"),
+
+    /**
+     * Bright white foreground color.
+     */
+    BRIGHT_WHITE("97"),
+
+    /**
+     * Bright white foreground color.
+     */
+    FG_BRIGHT_WHITE("97"),
+
+    /**
+     * Bright black background color.
+     */
+    BG_BRIGHT_BLACK("100"),
+
+    /**
+     * Bright red background color.
+     */
+    BG_BRIGHT_RED("101"),
+
+    /**
+     * Bright green background color.
+     */
+    BG_BRIGHT_GREEN("102"),
+
+    /**
+     * Bright yellow background color.
+     */
+    BG_BRIGHT_YELLOW("103"),
+
+    /**
+     * Bright blue background color.
+     */
+    BG_BRIGHT_BLUE("104"),
+
+    /**
+     * Bright magenta background color.
+     */
+    BG_BRIGHT_MAGENTA("105"),
+
+    /**
+     * Bright cyan background color.
+     */
+    BG_BRIGHT_CYAN("106"),
+
+    /**
+     * Bright white background color.
+     */
+    BG_BRIGHT_WHITE("107");
 
     private static final String DEFAULT_STYLE = CSI.getCode() + SUFFIX.getCode();
 


[logging-log4j2] 04/05: Add JUnit 5 extension to store per-test status messages

Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 26b55db8909ac44669b7d5de1907e56947b20931
Author: Piotr P. Karwasz <pi...@karwasz.org>
AuthorDate: Sat Jan 14 15:16:57 2023 +0100

    Add JUnit 5 extension to store per-test status messages
    
    The `@UsingStatusListener` annotation on a test or class resolves
    parameters of type `ListStatusListener`. These can be used to retrieve
    status messages that were generated by a single test.
---
 .../logging/log4j/test/ListStatusListener.java     |  39 +++++++
 .../log4j/test/junit/StatusLoggerExtension.java    | 122 +++++++++++++++++++++
 .../log4j/test/junit/UsingStatusListener.java      |  45 ++++++++
 3 files changed, 206 insertions(+)

diff --git a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/ListStatusListener.java b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/ListStatusListener.java
new file mode 100644
index 0000000000..08d68b4f7b
--- /dev/null
+++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/ListStatusListener.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.test;
+
+import java.util.stream.Stream;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.status.StatusData;
+import org.apache.logging.log4j.status.StatusListener;
+
+/**
+ * A {@link StatusListener}
+ */
+public interface ListStatusListener extends StatusListener {
+
+    Stream<StatusData> getStatusData();
+
+    default Stream<StatusData> findStatusData(Level level) {
+        return getStatusData().filter(data -> level.isLessSpecificThan(data.getLevel()));
+    }
+
+    default Stream<StatusData> findStatusData(Level level, String regex) {
+        return findStatusData(level).filter(data -> data.getMessage().getFormattedMessage().matches(regex));
+    }
+}
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
new file mode 100644
index 0000000000..2ad80bc33a
--- /dev/null
+++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/StatusLoggerExtension.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.test.junit;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collections;
+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.status.StatusData;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.test.ListStatusListener;
+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.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
+
+class StatusLoggerExtension extends TypeBasedParameterResolver<ListStatusListener>
+        implements 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() {
+        super(ListStatusListener.class);
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext context) throws Exception {
+        final ListStatusListenerHolder holder = new ListStatusListenerHolder(context);
+        ExtensionContextAnchor.setAttribute(KEY, holder, context);
+    }
+
+    @Override
+    public void handleTestExecutionException(ExtensionContext context, Throwable throwable) throws Throwable {
+        final ListStatusListener statusListener = resolveParameter(null, context);
+        statusListener.getStatusData().forEach(CONSOLE_LISTENER::log);
+        throw throwable;
+    }
+
+    @Override
+    public ListStatusListener resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
+            throws ParameterResolutionException {
+        final ListStatusListenerHolder holder = ExtensionContextAnchor.getAttribute(KEY, ListStatusListenerHolder.class,
+                extensionContext);
+        return holder.getStatusListener();
+    }
+
+    private static class ListStatusListenerHolder implements CloseableResource {
+
+        private final ListStatusListener statusListener;
+
+        public ListStatusListenerHolder(ExtensionContext context) {
+            this.statusListener = new JUnitListStatusListener(context);
+            LOGGER.registerListener(statusListener);
+        }
+
+        public ListStatusListener getStatusListener() {
+            return statusListener;
+        }
+
+        @Override
+        public void close() throws Throwable {
+            LOGGER.removeListener(statusListener);
+        }
+
+    }
+
+    private static class JUnitListStatusListener implements ListStatusListener {
+
+        private final ExtensionContext context;
+        private final List<StatusData> statusData = Collections.synchronizedList(new ArrayList<StatusData>());
+
+        public JUnitListStatusListener(ExtensionContext context) {
+            this.context = context;
+        }
+
+        @Override
+        public void log(StatusData data) {
+            if (context.equals(ExtensionContextAnchor.getContext())) {
+                statusData.add(data);
+            }
+        }
+
+        @Override
+        public Level getStatusLevel() {
+            return Level.DEBUG;
+        }
+
+        @Override
+        public void close() throws IOException {
+            // NOP
+        }
+
+        @Override
+        public Stream<StatusData> getStatusData() {
+            return statusData.stream();
+        }
+
+    }
+}
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
new file mode 100644
index 0000000000..c06fb67515
--- /dev/null
+++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/UsingStatusListener.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+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;
+import java.util.Properties;
+
+import org.apache.logging.log4j.status.StatusListener;
+import org.apache.logging.log4j.test.ListStatusListener;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Configures and injects a {@link StatusListener} of type
+ * {@link ListStatusListener}, that will collect status messages for the test
+ * context.
+ */
+@Retention(RUNTIME)
+@Target({ FIELD, METHOD })
+@Inherited
+@Documented
+@ExtendWith(ExtensionContextAnchor.class)
+@ExtendWith(StatusLoggerExtension.class)
+public @interface UsingStatusListener {
+}


[logging-log4j2] 01/05: LOG4J2-3538 Added support for 24 colors in highlighting (#933)

Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 4d34d2f85631e9025e723dc99d9fe6b6c950735d
Author: PashaTurok <oo...@mail.ru>
AuthorDate: Sun Jun 19 10:30:55 2022 +0300

    LOG4J2-3538 Added support for 24 colors in highlighting (#933)
    
    Adds support for 24-bit colors in `HighlightConverter`.
---
 .../log4j/core/pattern/HighlightConverterTest.java | 33 ++++++++++++++++-
 .../logging/log4j/core/pattern/AnsiEscape.java     | 41 +++++++++++++++++++---
 2 files changed, 69 insertions(+), 5 deletions(-)

diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
index c62889543a..a704d44c6a 100644
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/pattern/HighlightConverterTest.java
@@ -1,4 +1,4 @@
-package org.apache.logging.log4j.core.pattern;/*
+/*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements. See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
@@ -14,6 +14,7 @@ package org.apache.logging.log4j.core.pattern;/*
  * See the license for the specific language governing permissions and
  * limitations under the license.
  */
+package org.apache.logging.log4j.core.pattern;
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.LogEvent;
@@ -76,6 +77,36 @@ public class HighlightConverterTest {
         assertEquals(AnsiEscape.createSequence(colorName), converter.getLevelStyle(Level.DEBUG));
     }
 
+    @Test
+    public void testLevelNamesHexShort() {
+        final String colorName = "#1cd42b";
+        final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false, "
+                + PatternParser.DISABLE_ANSI + "=false, " + "INFO=" + colorName};
+        final HighlightConverter converter = HighlightConverter.newInstance(null, options);
+        assertNotNull(converter);
+
+        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
+                new SimpleMessage("")).build();
+        final StringBuilder buffer = new StringBuilder();
+        converter.format(event, buffer);
+        assertEquals("\u001B[38;2;28;212;43mINFO : \u001B[m", buffer.toString());
+    }
+
+    @Test
+    public void testLevelNamesHexFull() {
+        final String colorName = "FG_#1cd42b BG_#000000";
+        final String[] options = {"%-5level: %msg", PatternParser.NO_CONSOLE_NO_ANSI + "=false, "
+                + PatternParser.DISABLE_ANSI + "=false, " + "INFO=" + colorName};
+        final HighlightConverter converter = HighlightConverter.newInstance(null, options);
+        assertNotNull(converter);
+
+        final LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.INFO).setLoggerName("a.b.c").setMessage(
+                new SimpleMessage("")).build();
+        final StringBuilder buffer = new StringBuilder();
+        converter.format(event, buffer);
+        assertEquals("\u001B[38;2;28;212;43;48;2;0;0;0mINFO : \u001B[m", buffer.toString());
+    }
+
     @Test
     public void testLevelNamesUnknown() {
         String colorName = "blue";
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
index c83123453e..b7f703fa63 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AnsiEscape.java
@@ -16,13 +16,16 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.awt.datatransfer.StringSelection;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
 
 import org.apache.logging.log4j.core.util.Patterns;
+import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.EnglishEnums;
+import org.apache.logging.log4j.util.Strings;
 
 /**
  * Converts text into ANSI escape sequences.
@@ -289,7 +292,7 @@ public enum AnsiEscape {
      * @return a new map
      */
     public static Map<String, String> createMap(final String[] values, final String[] dontEscapeKeys) {
-        final String[] sortedIgnoreKeys = dontEscapeKeys != null ? dontEscapeKeys.clone() : new String[0];
+        final String[] sortedIgnoreKeys = dontEscapeKeys != null ? dontEscapeKeys.clone() : Strings.EMPTY_ARRAY;
         Arrays.sort(sortedIgnoreKeys);
         final Map<String, String> map = new HashMap<>();
         for (final String string : values) {
@@ -319,14 +322,44 @@ public enum AnsiEscape {
         boolean first = true;
         for (final String name : names) {
             try {
-                final AnsiEscape escape = EnglishEnums.valueOf(AnsiEscape.class, name.trim());
                 if (!first) {
                     sb.append(AnsiEscape.SEPARATOR.getCode());
                 }
                 first = false;
-                sb.append(escape.getCode());
+                String hexColor = null;
+                final String trimmedName = name.trim().toUpperCase(Locale.ENGLISH);
+                if (trimmedName.startsWith("#")) {
+                    sb.append("38");
+                    sb.append(SEPARATOR.getCode());
+                    sb.append("2");
+                    sb.append(SEPARATOR.getCode());
+                    hexColor = trimmedName;
+                } else if (trimmedName.startsWith("FG_#")) {
+                    sb.append("38");
+                    sb.append(SEPARATOR.getCode());
+                    sb.append("2");
+                    sb.append(SEPARATOR.getCode());
+                    hexColor = trimmedName.substring(3);
+                } else if (trimmedName.startsWith("BG_#")) {
+                    sb.append("48");
+                    sb.append(SEPARATOR.getCode());
+                    sb.append("2");
+                    sb.append(SEPARATOR.getCode());
+                    hexColor = trimmedName.substring(3);
+                }
+                if (hexColor != null) {
+                    sb.append(Integer.valueOf(hexColor.substring(1, 3), 16));//r
+                    sb.append(SEPARATOR.getCode());
+                    sb.append(Integer.valueOf(hexColor.substring(3, 5), 16));//g
+                    sb.append(SEPARATOR.getCode());
+                    sb.append(Integer.valueOf(hexColor.substring(5, 7), 16));//b
+                    //no separator at the end
+                } else {
+                    final AnsiEscape escape = EnglishEnums.valueOf(AnsiEscape.class, trimmedName);
+                    sb.append(escape.getCode());
+                }
             } catch (final Exception ex) {
-                // Ignore the error.
+                StatusLogger.getLogger().warn("The style attribute {} is incorrect.", name, ex);
             }
         }
         sb.append(AnsiEscape.SUFFIX.getCode());