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 1d533574162c51e40f0bef16d1f73b15f9e3f59e
Author: Matt Sicker <[email protected]>
AuthorDate: Fri May 27 19:02:27 2022 -0500

    Add TestProperties JUnit 5 extension
    
    This also updates several tests that were using system properties to use 
this extension instead.
    
    Signed-off-by: Matt Sicker <[email protected]>
---
 .../logging/log4j/test/junit/PropertyTester.java   | 67 ++++++++++++++++++++++
 .../logging/log4j/test/junit/TestProperties.java   | 45 +++++++++++++++
 .../logging/log4j/NoopThreadContextTest.java       | 30 +++-------
 .../log4j/ThreadContextInheritanceTest.java        | 56 ++++++------------
 .../log4j/spi/DefaultThreadContextMapTest.java     | 17 ++----
 .../logging/log4j/spi/ThreadContextMapFactory.java |  5 +-
 .../log4j/core/EventParameterMemoryLeakTest.java   | 25 +++-----
 .../apache/logging/log4j/core/Log4j1222Test.java   | 10 ++--
 .../logging/log4j/core/LogbackSubstitution.java    | 20 +------
 .../log4j/core/appender/ConsoleAppenderTest.java   | 23 ++------
 ...ollingRandomAccessFileAppenderRolloverTest.java | 10 +---
 .../async/AsyncAppenderConfigTest_LOG4J2_2032.java | 34 +++++------
 .../log4j/core/async/AsyncLoggerConfig4Test.java   |  9 +--
 .../core/async/AsyncLoggerConfigAutoFlushTest.java | 38 +++++-------
 .../core/async/AsyncLoggerConfigErrorOnFormat.java | 49 ++++++----------
 .../logging/log4j/core/time/ClockFactoryTest.java  | 22 +++----
 16 files changed, 224 insertions(+), 236 deletions(-)

diff --git 
a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/PropertyTester.java
 
b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/PropertyTester.java
new file mode 100644
index 0000000000..2fc401f5dc
--- /dev/null
+++ 
b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/PropertyTester.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Properties;
+
+class PropertyTester implements BeforeAllCallback, BeforeEachCallback {
+    @Override
+    public void beforeAll(final ExtensionContext context) throws Exception {
+        final TestProperties testProperties = 
context.getRequiredTestClass().getAnnotation(TestProperties.class);
+        if (testProperties != null) {
+            
context.getStore(ExtensionContext.Namespace.create(TestProperties.class, 
context.getRequiredTestClass()))
+                    .put(PropertiesSession.class, new 
PropertiesSession(testProperties));
+        }
+    }
+
+    @Override
+    public void beforeEach(final ExtensionContext context) throws Exception {
+        final TestProperties testProperties = 
context.getRequiredTestMethod().getAnnotation(TestProperties.class);
+        if (testProperties != null) {
+            
context.getStore(ExtensionContext.Namespace.create(TestProperties.class, 
context.getRequiredTestInstance()))
+                    .put(PropertiesSession.class, new 
PropertiesSession(testProperties));
+        }
+    }
+
+    private static class PropertiesSession implements 
ExtensionContext.Store.CloseableResource {
+        private final Properties properties = new Properties();
+
+        private PropertiesSession(final TestProperties testProperties) throws 
IOException {
+            for (final String testProperty : testProperties.value()) {
+                properties.load(new StringReader(testProperty));
+            }
+            for (final String propertyName : properties.stringPropertyNames()) 
{
+                System.setProperty(propertyName, 
properties.getProperty(propertyName));
+            }
+        }
+
+        @Override
+        public void close() throws Throwable {
+            for (final String propertyName : properties.stringPropertyNames()) 
{
+                System.clearProperty(propertyName);
+            }
+            properties.clear();
+        }
+    }
+}
diff --git 
a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/TestProperties.java
 
b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/TestProperties.java
new file mode 100644
index 0000000000..c1ded404ae
--- /dev/null
+++ 
b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/TestProperties.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 org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.parallel.ResourceLock;
+import org.junit.jupiter.api.parallel.Resources;
+
+import java.io.Reader;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * JUnit 5 extension for setting Log4j properties for an annotated test class 
or test method.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Documented
+@ExtendWith(PropertyTester.class)
+@ResourceLock(Resources.SYSTEM_PROPERTIES)
+public @interface TestProperties {
+    /**
+     * Properties to set in the test provided in a {@link 
java.util.Properties#load(Reader)}-compatible syntax.
+     * This syntax includes key/value pairs as {@code key=value}, {@code 
key:value}, and {@code key value}.
+     */
+    String[] value();
+}
diff --git 
a/log4j-api-test/src/test/java/org/apache/logging/log4j/NoopThreadContextTest.java
 
b/log4j-api-test/src/test/java/org/apache/logging/log4j/NoopThreadContextTest.java
index 6a3859884b..fdf40b740c 100644
--- 
a/log4j-api-test/src/test/java/org/apache/logging/log4j/NoopThreadContextTest.java
+++ 
b/log4j-api-test/src/test/java/org/apache/logging/log4j/NoopThreadContextTest.java
@@ -16,37 +16,24 @@
  */
 package org.apache.logging.log4j;
 
+import org.apache.logging.log4j.test.junit.TestProperties;
 import org.apache.logging.log4j.test.junit.UsingThreadContextMap;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.parallel.ResourceLock;
-import org.junit.jupiter.api.parallel.Resources;
 
 import static org.junit.jupiter.api.Assertions.assertNull;
 
 /**
  * Tests {@link ThreadContext}.
  */
-@ResourceLock(Resources.SYSTEM_PROPERTIES)
 @UsingThreadContextMap
+@TestProperties({
+        "disableThreadContext = true",
+        "disableThreadContextMap = true"
+})
 public class NoopThreadContextTest {
-
-    private static final String TRUE = "true";
-    private static final String PROPERY_KEY_ALL = "disableThreadContext";
-    private static final String PROPERY_KEY_MAP = "disableThreadContextMap";
-
-    @BeforeAll
-    public static void before() {
-        System.setProperty(PROPERY_KEY_ALL, TRUE);
-        System.setProperty(PROPERY_KEY_MAP, TRUE);
-        ThreadContext.init();
-    }
-
-    @AfterAll
-    public static void after() {
-        System.clearProperty(PROPERY_KEY_ALL);
-        System.clearProperty(PROPERY_KEY_MAP);
+    @BeforeEach
+    void setUp() {
         ThreadContext.init();
     }
 
@@ -57,5 +44,4 @@ public class NoopThreadContextTest {
         assertNull(value, "value was saved");
     }
 
-
 }
diff --git 
a/log4j-api-test/src/test/java/org/apache/logging/log4j/ThreadContextInheritanceTest.java
 
b/log4j-api-test/src/test/java/org/apache/logging/log4j/ThreadContextInheritanceTest.java
index 51f8a5966e..87f993a37c 100644
--- 
a/log4j-api-test/src/test/java/org/apache/logging/log4j/ThreadContextInheritanceTest.java
+++ 
b/log4j-api-test/src/test/java/org/apache/logging/log4j/ThreadContextInheritanceTest.java
@@ -16,15 +16,12 @@
  */
 package org.apache.logging.log4j;
 
+import org.apache.logging.log4j.spi.DefaultThreadContextMap;
 import org.apache.logging.log4j.test.ThreadContextUtilityClass;
+import org.apache.logging.log4j.test.junit.TestProperties;
 import org.apache.logging.log4j.test.junit.UsingAnyThreadContext;
-import org.apache.logging.log4j.spi.DefaultThreadContextMap;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Tag;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.parallel.ResourceLock;
-import org.junit.jupiter.api.parallel.Resources;
 
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -32,21 +29,9 @@ import static org.junit.jupiter.api.Assertions.*;
  * Tests {@link ThreadContext}.
  */
 @UsingAnyThreadContext
-@ResourceLock(Resources.SYSTEM_PROPERTIES)
+@TestProperties(DefaultThreadContextMap.INHERITABLE_MAP + " = true")
 public class ThreadContextInheritanceTest {
 
-    @BeforeAll
-    public static void setupClass() {
-        System.setProperty(DefaultThreadContextMap.INHERITABLE_MAP, "true");
-        ThreadContext.init();
-    }
-
-    @AfterAll
-    public static void tearDownClass() {
-        System.clearProperty(DefaultThreadContextMap.INHERITABLE_MAP);
-        ThreadContext.init();
-    }
-
     @Test
     public void testPush() {
         ThreadContext.push("Hello");
@@ -58,26 +43,19 @@ public class ThreadContextInheritanceTest {
 
     @Test
     public void testInheritanceSwitchedOn() throws Exception {
-        System.setProperty(DefaultThreadContextMap.INHERITABLE_MAP, "true");
-        ThreadContext.init();
-        try {
-            ThreadContext.clearMap();
-            ThreadContext.put("Greeting", "Hello");
-            StringBuilder sb = new StringBuilder();
-            TestThread thread = new TestThread(sb);
-            thread.start();
-            thread.join();
-            String str = sb.toString();
-            assertEquals("Hello", str, "Unexpected ThreadContext value. 
Expected Hello. Actual " + str);
-            sb = new StringBuilder();
-            thread = new TestThread(sb);
-            thread.start();
-            thread.join();
-            str = sb.toString();
-            assertEquals("Hello", str, "Unexpected ThreadContext value. 
Expected Hello. Actual " + str);
-        } finally {
-            System.clearProperty(DefaultThreadContextMap.INHERITABLE_MAP);
-        }
+        ThreadContext.put("Greeting", "Hello");
+        StringBuilder sb = new StringBuilder();
+        TestThread thread = new TestThread(sb);
+        thread.start();
+        thread.join();
+        String str = sb.toString();
+        assertEquals("Hello", str, "Unexpected ThreadContext value. Expected 
Hello. Actual " + str);
+        sb = new StringBuilder();
+        thread = new TestThread(sb);
+        thread.start();
+        thread.join();
+        str = sb.toString();
+        assertEquals("Hello", str, "Unexpected ThreadContext value. Expected 
Hello. Actual " + str);
     }
 
     @Test
@@ -123,7 +101,6 @@ public class ThreadContextInheritanceTest {
 
     @Test
     public void testRemove() {
-        ThreadContext.clearMap();
         assertNull(ThreadContext.get("testKey"));
         ThreadContext.put("testKey", "testValue");
         assertEquals("testValue", ThreadContext.get("testKey"));
@@ -135,7 +112,6 @@ public class ThreadContextInheritanceTest {
 
     @Test
     public void testContainsKey() {
-        ThreadContext.clearMap();
         assertFalse(ThreadContext.containsKey("testKey"));
         ThreadContext.put("testKey", "testValue");
         assertTrue(ThreadContext.containsKey("testKey"));
diff --git 
a/log4j-api-test/src/test/java/org/apache/logging/log4j/spi/DefaultThreadContextMapTest.java
 
b/log4j-api-test/src/test/java/org/apache/logging/log4j/spi/DefaultThreadContextMapTest.java
index a7a12147ab..621d381c46 100644
--- 
a/log4j-api-test/src/test/java/org/apache/logging/log4j/spi/DefaultThreadContextMapTest.java
+++ 
b/log4j-api-test/src/test/java/org/apache/logging/log4j/spi/DefaultThreadContextMapTest.java
@@ -16,10 +16,9 @@
  */
 package org.apache.logging.log4j.spi;
 
+import org.apache.logging.log4j.test.junit.TestProperties;
 import org.apache.logging.log4j.test.junit.UsingThreadContextMap;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.parallel.ResourceLock;
-import org.junit.jupiter.api.parallel.Resources;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -215,23 +214,17 @@ public class DefaultThreadContextMapTest {
     }
 
     @Test
-    @ResourceLock(Resources.SYSTEM_PROPERTIES)
+    @TestProperties(DefaultThreadContextMap.INHERITABLE_MAP + " = false")
     public void testThreadLocalNotInheritableByDefault() {
-        System.clearProperty(DefaultThreadContextMap.INHERITABLE_MAP);
         final ThreadLocal<Map<String, String>> threadLocal = 
DefaultThreadContextMap.createThreadLocalMap(true);
         assertFalse(threadLocal instanceof InheritableThreadLocal<?>);
     }
     
     @Test
-    @ResourceLock(Resources.SYSTEM_PROPERTIES)
+    @TestProperties(DefaultThreadContextMap.INHERITABLE_MAP + " = true")
     public void testThreadLocalInheritableIfConfigured() {
-        System.setProperty(DefaultThreadContextMap.INHERITABLE_MAP, "true");
         ThreadContextMapFactory.init();
-        try {
-            final ThreadLocal<Map<String, String>> threadLocal = 
DefaultThreadContextMap.createThreadLocalMap(true);
-            assertTrue(threadLocal instanceof InheritableThreadLocal<?>);
-        } finally {
-            System.clearProperty(DefaultThreadContextMap.INHERITABLE_MAP);
-        }
+        final ThreadLocal<Map<String, String>> threadLocal = 
DefaultThreadContextMap.createThreadLocalMap(true);
+        assertTrue(threadLocal instanceof InheritableThreadLocal<?>);
     }
 }
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMapFactory.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMapFactory.java
index edbe49d23e..60d69b35b8 100644
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMapFactory.java
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMapFactory.java
@@ -23,6 +23,7 @@ import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.Constants;
 import org.apache.logging.log4j.util.PropertiesUtil;
 import org.apache.logging.log4j.util.ProviderUtil;
+import org.apache.logging.log4j.util.ReflectionUtil;
 
 /**
  * Creates the ThreadContextMap instance used by the ThreadContext.
@@ -88,7 +89,7 @@ public final class ThreadContextMapFactory {
             try {
                 final Class<?> clazz = cl.loadClass(ThreadContextMapName);
                 if (ThreadContextMap.class.isAssignableFrom(clazz)) {
-                    result = (ThreadContextMap) clazz.newInstance();
+                    result = 
ReflectionUtil.instantiate(clazz.asSubclass(ThreadContextMap.class));
                 }
             } catch (final ClassNotFoundException cnfe) {
                 LOGGER.error("Unable to locate configured ThreadContextMap 
{}", ThreadContextMapName);
@@ -103,7 +104,7 @@ public final class ThreadContextMapFactory {
                     final Class<? extends ThreadContextMap> clazz = 
provider.loadThreadContextMap();
                     if (clazz != null) {
                         try {
-                            result = clazz.newInstance();
+                            result = ReflectionUtil.instantiate(clazz);
                             break;
                         } catch (final Exception e) {
                             LOGGER.error("Unable to locate or load configured 
ThreadContextMap {}",
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/EventParameterMemoryLeakTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/EventParameterMemoryLeakTest.java
index 9caa340acb..f39da32001 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/EventParameterMemoryLeakTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/EventParameterMemoryLeakTest.java
@@ -18,15 +18,15 @@ package org.apache.logging.log4j.core;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
 import org.apache.logging.log4j.core.test.CoreLoggerContexts;
-import org.junit.jupiter.api.BeforeAll;
+import org.apache.logging.log4j.test.junit.TestProperties;
 import org.junit.jupiter.api.Tag;
 import org.junit.jupiter.api.Test;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
+import java.lang.ref.Cleaner;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -36,14 +36,9 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @Tag("functional")
+@TestProperties({"log4j2.enable.direct.encoders = true", 
"log4j.configurationFile = EventParameterMemoryLeakTest.xml"})
 public class EventParameterMemoryLeakTest {
 
-    @BeforeAll
-    public static void beforeClass() {
-        System.setProperty("log4j2.enable.direct.encoders", "true");
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, 
"EventParameterMemoryLeakTest.xml");
-    }
-
     @Test
     @SuppressWarnings("UnusedAssignment") // parameter set to null to allow 
garbage collection
     public void testParametersAreNotLeaked() throws Exception {
@@ -52,7 +47,9 @@ public class EventParameterMemoryLeakTest {
 
         final Logger log = LogManager.getLogger("com.foo.Bar");
         CountDownLatch latch = new CountDownLatch(1);
-        Object parameter = new ParameterObject("paramValue", latch);
+        final Cleaner cleaner = Cleaner.create();
+        Object parameter = new ParameterObject("paramValue");
+        cleaner.register(parameter, latch::countDown);
         log.info("Message with parameter {}", parameter);
         log.info(parameter);
         log.info("test", new ObjectThrowable(parameter));
@@ -80,22 +77,14 @@ public class EventParameterMemoryLeakTest {
 
     private static final class ParameterObject {
         private final String value;
-        private final CountDownLatch latch;
-        ParameterObject(String value, CountDownLatch latch) {
+        ParameterObject(String value) {
             this.value = value;
-            this.latch = latch;
         }
 
         @Override
         public String toString() {
             return value;
         }
-
-        @Override
-        protected void finalize() throws Throwable {
-            latch.countDown();
-            super.finalize();
-        }
     }
 
     private static final class ObjectThrowable extends RuntimeException {
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/Log4j1222Test.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/Log4j1222Test.java
index b22b2d0f1d..36d1bd2f3a 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/Log4j1222Test.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/Log4j1222Test.java
@@ -19,10 +19,11 @@ package org.apache.logging.log4j.core;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.test.TestLogger;
+import org.apache.logging.log4j.test.junit.TestProperties;
 import org.junit.jupiter.api.Tag;
 import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * Tests logging during shutdown.
@@ -32,9 +33,8 @@ public class Log4j1222Test
 {
 
        @Test
-       public void homepageRendersSuccessfully()
-       {
-        System.setProperty("log4j.configurationFile", "log4j2-console.xml");
+       @TestProperties("log4j.configurationFile = log4j2-console.xml")
+       public void homepageRendersSuccessfully() {
                Runtime.getRuntime().addShutdownHook(new ShutdownHook());
        }
 
@@ -53,7 +53,7 @@ public class Log4j1222Test
 
                private void trigger() {
                        Holder.LOGGER.info("Attempt to trigger");
-                       assertTrue("Logger is of type " + 
Holder.LOGGER.getClass().getName(), Holder.LOGGER instanceof TestLogger);
+                       assertTrue(Holder.LOGGER instanceof TestLogger, "Logger 
is of type " + Holder.LOGGER.getClass().getName());
                        if (((TestLogger) Holder.LOGGER).getEntries().size() == 
0) {
                                System.out.println("Logger contains no 
messages");
                        }
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/LogbackSubstitution.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/LogbackSubstitution.java
index 570340df07..4b9549fd90 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/LogbackSubstitution.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/LogbackSubstitution.java
@@ -16,32 +16,18 @@
  */
 package org.apache.logging.log4j.core;
 
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.apache.logging.log4j.test.junit.TestProperties;
+import org.junit.jupiter.api.Test;
 import org.slf4j.LoggerFactory;
 
 /**
  *
  */
+@TestProperties("logback.configurationFile = logback-subst.xml")
 public class LogbackSubstitution {
 
-    private static final String LOGBACK_CONF = "logback.configurationFile";
-    private static final String LOGBACK_CONFIG = "logback-subst.xml";
     private final org.slf4j.Logger logger = 
LoggerFactory.getLogger(LogbackSubstitution.class);
 
-
-
-    @BeforeClass
-    public static void setupClass() {
-        System.setProperty(LOGBACK_CONF, LOGBACK_CONFIG);
-    }
-
-    @AfterClass
-    public static void cleanupClass() {
-        System.clearProperty(LOGBACK_CONF);
-    }
-
     @Test
     public void testSubst() {
         logger.debug("Hello, {}", "Log4j {}");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
index 7582c287c8..85ec10c271 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
@@ -16,9 +16,6 @@
  */
 package org.apache.logging.log4j.core.appender;
 
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
@@ -26,15 +23,17 @@ import 
org.apache.logging.log4j.core.appender.ConsoleAppender.Target;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.test.junit.TestProperties;
 import org.apache.logging.log4j.util.Strings;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -42,20 +41,9 @@ import static org.mockito.BDDMockito.then;
 import static org.mockito.Mockito.atLeastOnce;
 
 @ExtendWith(MockitoExtension.class)
+@TestProperties("log4j.skipJansi = true")
 public class ConsoleAppenderTest {
 
-    private static final String LOG4J_SKIP_JANSI = "log4j.skipJansi";
-
-    @AfterAll
-    public static void afterClass() {
-        System.clearProperty(LOG4J_SKIP_JANSI);
-    }
-
-    @BeforeAll
-    public static void beforeClass() {
-        System.setProperty(LOG4J_SKIP_JANSI, "true");
-    }
-
     ByteArrayOutputStream baos;
 
     @Mock
@@ -63,7 +51,6 @@ public class ConsoleAppenderTest {
 
     @BeforeEach
     public void before() {
-        System.setProperty(LOG4J_SKIP_JANSI, "true");
         baos = new ByteArrayOutputStream();
     }
 
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/RollingRandomAccessFileAppenderRolloverTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/RollingRandomAccessFileAppenderRolloverTest.java
index 5b12f52f6a..203634b79f 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/RollingRandomAccessFileAppenderRolloverTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/appender/RollingRandomAccessFileAppenderRolloverTest.java
@@ -18,9 +18,8 @@ package org.apache.logging.log4j.core.appender;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
 import org.apache.logging.log4j.core.test.CoreLoggerContexts;
-import org.junit.jupiter.api.BeforeAll;
+import org.apache.logging.log4j.test.junit.TestProperties;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Tag;
 import org.junit.jupiter.api.Test;
@@ -33,14 +32,9 @@ import java.util.Arrays;
 import static org.junit.jupiter.api.Assertions.*;
 
 @Tag("sleepy")
+@TestProperties("log4j.configurationFile = 
RollingRandomAccessFileAppenderTest.xml")
 public class RollingRandomAccessFileAppenderRolloverTest {
 
-    @BeforeAll
-    public static void beforeClass() {
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
-                "RollingRandomAccessFileAppenderTest.xml");
-    }
-
     @Test
     @Disabled
     public void testRollover() throws Exception {
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncAppenderConfigTest_LOG4J2_2032.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncAppenderConfigTest_LOG4J2_2032.java
index f0e1685cb9..ac947f62c5 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncAppenderConfigTest_LOG4J2_2032.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncAppenderConfigTest_LOG4J2_2032.java
@@ -16,35 +16,33 @@
  */
 package org.apache.logging.log4j.core.async;
 
-import static org.junit.Assert.assertTrue;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.test.categories.AsyncLoggers;
 import org.apache.logging.log4j.core.test.CoreLoggerContexts;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
+import org.apache.logging.log4j.test.junit.CleanUpFiles;
+import org.apache.logging.log4j.test.junit.TestProperties;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 
-@Category(AsyncLoggers.class)
-public class AsyncAppenderConfigTest_LOG4J2_2032 {
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-    @BeforeClass
-    public static void beforeClass() {
-        System.setProperty("Log4jLogEventFactory", 
"org.apache.logging.log4j.core.impl.ReusableLogEventFactory");
-        System.setProperty("log4j2.messageFactory", 
"org.apache.logging.log4j.message.ReusableMessageFactory");
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, 
"AsyncAppenderConfigTest-LOG4J2-2032.xml");
-    }
+@Tag("async")
+@TestProperties({
+        "log4j2.logEventFactory = 
org.apache.logging.log4j.core.impl.ReusableLogEventFactory",
+        "log4j2.messageFactory = 
org.apache.logging.log4j.message.ReusableMessageFactory",
+        "log4j2.configurationFile = AsyncAppenderConfigTest-LOG4J2-2032.xml"
+})
+public class AsyncAppenderConfigTest_LOG4J2_2032 {
 
     @Test
+    @CleanUpFiles("target/AsyncAppenderConfigTest-LOG4J2-2032.log")
     public void doNotProcessPlaceholdersTwice() throws Exception {
         final File file = new File("target", 
"AsyncAppenderConfigTest-LOG4J2-2032.log");
-        assertTrue("Deleted old file before test", !file.exists() || 
file.delete());
+        assertTrue(!file.exists() || file.delete(), "Deleted old file before 
test");
 
         final Logger log = LogManager.getLogger("com.foo.Bar");
         log.info("Text containing curly braces: {}", "Curly{}");
@@ -53,9 +51,7 @@ public class AsyncAppenderConfigTest_LOG4J2_2032 {
         try (BufferedReader reader = new BufferedReader(new FileReader(file))) 
{
             final String line1 = reader.readLine();
             System.out.println(line1);
-            assertTrue("line1 correct", line1.contains(" Text containing curly 
braces: Curly{} "));
-        } finally {
-            file.delete();
+            assertTrue(line1.contains(" Text containing curly braces: Curly{} 
"), "line1 correct");
         }
     }
 
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfig4Test.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfig4Test.java
index 70f3402675..5d8d98811b 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfig4Test.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfig4Test.java
@@ -18,9 +18,8 @@ package org.apache.logging.log4j.core.async;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
 import org.apache.logging.log4j.core.test.CoreLoggerContexts;
-import org.junit.jupiter.api.BeforeAll;
+import org.apache.logging.log4j.test.junit.TestProperties;
 import org.junit.jupiter.api.Tag;
 import org.junit.jupiter.api.Test;
 
@@ -34,13 +33,9 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @Tag("async")
+@TestProperties("log4j2.configurationFile = AsyncLoggerConfigTest4.xml")
 public class AsyncLoggerConfig4Test {
 
-    @BeforeAll
-    public static void beforeClass() {
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, 
"AsyncLoggerConfigTest4.xml");
-    }
-
     @Test
     public void testParameters() throws Exception {
         final File file = new File("target", "AsyncLoggerConfigTest4.log");
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigAutoFlushTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigAutoFlushTest.java
index 71c4df4eec..17cca4bdc5 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigAutoFlushTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigAutoFlushTest.java
@@ -16,44 +16,34 @@
  */
 package org.apache.logging.log4j.core.async;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.test.categories.AsyncLoggers;
 import org.apache.logging.log4j.core.test.CoreLoggerContexts;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
+import org.apache.logging.log4j.test.junit.CleanUpFiles;
+import org.apache.logging.log4j.test.junit.TestProperties;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.nio.file.Files;
 
-import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@Category(AsyncLoggers.class)
+@Tag("async")
+@TestProperties("log4j2.configurationFile = 
AsyncLoggerConfigAutoFlushTest.xml")
 public class AsyncLoggerConfigAutoFlushTest {
 
-    @BeforeClass
-    public static void beforeClass() {
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
-                "AsyncLoggerConfigAutoFlushTest.xml");
-    }
-
     @Test
+    @CleanUpFiles("target/AsyncLoggerConfigAutoFlushTest.log")
     public void testFlushAtEndOfBatch() throws Exception {
         final File file = new File("target", 
"AsyncLoggerConfigAutoFlushTest.log");
-        assertTrue("Deleted old file before test", !file.exists() || 
file.delete());
+        assertTrue(!file.exists() || file.delete(), "Deleted old file before 
test");
 
         final Logger log = LogManager.getLogger("com.foo.Bar");
         final String msg = "Message flushed with immediate flush=false";
         log.info(msg);
         CoreLoggerContexts.stopLoggerContext(file); // stop async thread
-        final BufferedReader reader = new BufferedReader(new FileReader(file));
-        final String line1 = reader.readLine();
-        reader.close();
-        file.delete();
-        assertNotNull("line1", line1);
-        assertTrue("line1 correct", line1.contains(msg));
+        final String contents = Files.readString(file.toPath());
+        assertTrue(contents.contains(msg), "line1 correct");
     }
 }
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigErrorOnFormat.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigErrorOnFormat.java
index 3602a6eb61..4c3c90762b 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigErrorOnFormat.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigErrorOnFormat.java
@@ -18,57 +18,46 @@ package org.apache.logging.log4j.core.async;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.apache.logging.log4j.core.impl.DefaultLogEventFactory;
 import org.apache.logging.log4j.core.test.CoreLoggerContexts;
-import org.apache.logging.log4j.core.test.categories.AsyncLoggers;
 import org.apache.logging.log4j.message.AsynchronouslyFormattable;
 import org.apache.logging.log4j.message.Message;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
+import org.apache.logging.log4j.test.junit.CleanUpFiles;
+import org.apache.logging.log4j.test.junit.TestProperties;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
 
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileReader;
+import java.nio.file.Files;
+import java.util.List;
 
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.*;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@Category(AsyncLoggers.class)
+@Tag("async")
+@TestProperties({
+        "log4j2.configurationFile = AsyncLoggerConfigErrorOnFormat.xml",
+        "log4j2.logEventFactory = 
org.apache.logging.log4j.core.impl.DefaultLogEventFactory"
+})
 public class AsyncLoggerConfigErrorOnFormat {
 
-    @BeforeClass
-    public static void beforeClass() {
-        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, 
"AsyncLoggerConfigErrorOnFormat.xml");
-        // Log4jLogEvent.toString invokes message.toString
-        System.setProperty("log4j2.logEventFactory", 
DefaultLogEventFactory.class.getName());
-    }
-
-    @AfterClass
-    public static void afterClass() {
-        System.clearProperty("log4j2.logEventFactory");
-    }
-
     @Test
+    @CleanUpFiles("target/AsyncLoggerConfigErrorOnFormat.log")
     public void testError() throws Exception {
         final File file = new File("target", 
"AsyncLoggerConfigErrorOnFormat.log");
-        assertTrue("Deleted old file before test", !file.exists() || 
file.delete());
+        assertTrue(!file.exists() || file.delete(), "Deleted old file before 
test");
 
         final Logger log = LogManager.getLogger("com.foo.Bar");
         log.info(new ThrowsErrorOnFormatMessage());
         log.info("Second message");
         CoreLoggerContexts.stopLoggerContext(file); // stop async thread
 
-        final BufferedReader reader = new BufferedReader(new FileReader(file));
-        final String line1 = reader.readLine();
-        final String line2 = reader.readLine();
-        reader.close();
-        file.delete();
+        final List<String> lines = Files.readAllLines(file.toPath());
+        final String line1 = lines.get(0);
 
         assertThat(line1, containsString("Second message"));
-        assertNull("Expected only one line", line2);
+        assertThat(lines, hasSize(1));
     }
 
     @AsynchronouslyFormattable // Shouldn't call getFormattedMessage early
diff --git 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/time/ClockFactoryTest.java
 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/time/ClockFactoryTest.java
index 3e10ee30e6..5f4773b2b3 100644
--- 
a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/time/ClockFactoryTest.java
+++ 
b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/time/ClockFactoryTest.java
@@ -21,7 +21,7 @@ import 
org.apache.logging.log4j.core.time.internal.CoarseCachedClock;
 import org.apache.logging.log4j.core.time.internal.SystemClock;
 import org.apache.logging.log4j.plugins.di.DI;
 import org.apache.logging.log4j.plugins.di.Injector;
-import org.junit.jupiter.api.BeforeEach;
+import org.apache.logging.log4j.test.junit.TestProperties;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledOnOs;
 import org.junit.jupiter.api.condition.OS;
@@ -33,56 +33,50 @@ public class ClockFactoryTest {
 
     private final Injector injector = DI.createInjector();
 
-    @BeforeEach
-    public void setUp() throws Exception {
-        System.clearProperty(ClockFactory.PROPERTY_NAME);
-    }
-
     @Test
     public void testDefaultIsSystemClock() {
-        System.clearProperty(ClockFactory.PROPERTY_NAME);
         injector.init();
         
assertThat(injector.getInstance(Clock.class)).isInstanceOf(SystemClock.class);
     }
 
     @Test
+    @TestProperties("log4j.Clock = SystemClock")
     public void testSpecifySystemClockShort() {
-        System.setProperty(ClockFactory.PROPERTY_NAME, "SystemClock");
         injector.init();
         
assertThat(injector.getInstance(Clock.class)).isInstanceOf(SystemClock.class);
     }
 
     @Test
+    @TestProperties("log4j.Clock = 
org.apache.logging.log4j.core.time.internal.SystemClock")
     public void testSpecifySystemClockLong() {
-        System.setProperty(ClockFactory.PROPERTY_NAME, 
SystemClock.class.getName());
         injector.init();
         
assertThat(injector.getInstance(Clock.class)).isInstanceOf(SystemClock.class);
     }
 
     @Test
+    @TestProperties("log4j.Clock = CachedClock")
     public void testSpecifyCachedClockShort() {
-        System.setProperty(ClockFactory.PROPERTY_NAME, "CachedClock");
         injector.init();
         
assertThat(injector.getInstance(Clock.class)).isInstanceOf(CachedClock.class);
     }
 
     @Test
+    @TestProperties("log4j.Clock = 
org.apache.logging.log4j.core.time.internal.CachedClock")
     public void testSpecifyCachedClockLong() {
-        System.setProperty(ClockFactory.PROPERTY_NAME, 
CachedClock.class.getName());
         injector.init();
         
assertThat(injector.getInstance(Clock.class)).isInstanceOf(CachedClock.class);
     }
 
     @Test
+    @TestProperties("log4j.Clock = CoarseCachedClock")
     public void testSpecifyCoarseCachedClockShort() {
-        System.setProperty(ClockFactory.PROPERTY_NAME, "CoarseCachedClock");
         injector.init();
         
assertThat(injector.getInstance(Clock.class)).isInstanceOf(CoarseCachedClock.class);
     }
 
     @Test
+    @TestProperties("log4j.Clock = 
org.apache.logging.log4j.core.time.internal.CoarseCachedClock")
     public void testSpecifyCoarseCachedClockLong() {
-        System.setProperty(ClockFactory.PROPERTY_NAME, 
CoarseCachedClock.class.getName());
         injector.init();
         
assertThat(injector.getInstance(Clock.class)).isInstanceOf(CoarseCachedClock.class);
     }
@@ -95,8 +89,8 @@ public class ClockFactoryTest {
     }
 
     @Test
+    @TestProperties("log4j.Clock = 
org.apache.logging.log4j.core.time.ClockFactoryTest$MyClock")
     public void testCustomClock() {
-        System.setProperty(ClockFactory.PROPERTY_NAME, 
MyClock.class.getName());
         injector.init();
         
assertThat(injector.getInstance(Clock.class)).isInstanceOf(MyClock.class);
     }

Reply via email to