This is an automated email from the ASF dual-hosted git repository. mattsicker pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 42768fbc70687c152ff227947cda1e80c984ec67 Author: Matt Sicker <[email protected]> AuthorDate: Mon Jan 1 18:06:50 2024 -0600 Refactor ThreadContextDataInjectorTest to use reflection This ensures portability of this test while some internal details of initialization are changed. Signed-off-by: Matt Sicker <[email protected]> --- .../core/impl/ThreadContextDataInjectorTest.java | 113 +++++++++++++-------- 1 file changed, 71 insertions(+), 42 deletions(-) diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java index 0e1f4362e5..16953436b7 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java @@ -16,26 +16,35 @@ */ package org.apache.logging.log4j.core.impl; -import static java.util.Arrays.asList; import static java.util.concurrent.Executors.newSingleThreadExecutor; import static org.apache.logging.log4j.ThreadContext.getThreadContextMap; import static org.apache.logging.log4j.core.impl.ContextDataInjectorFactory.createInjector; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; - -import java.util.Collection; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasEntry; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.reflect.Constructor; import java.util.concurrent.ExecutionException; +import java.util.function.Function; import org.apache.logging.log4j.ThreadContext; import org.apache.logging.log4j.core.ContextDataInjector; -import org.apache.logging.log4j.spi.LoggingSystemProperty; +import org.apache.logging.log4j.spi.DefaultThreadContextMap; +import org.apache.logging.log4j.spi.LoggingSystem; import org.apache.logging.log4j.spi.ReadOnlyThreadContextMap; -import org.apache.logging.log4j.test.ThreadContextUtilityClass; -import org.apache.logging.log4j.util.PropertiesUtil; +import org.apache.logging.log4j.spi.ThreadContextMap; import org.apache.logging.log4j.util.SortedArrayStringMap; import org.apache.logging.log4j.util.StringMap; import org.junit.After; -import org.junit.Before; import org.junit.Test; +import org.junit.platform.commons.function.Try; +import org.junit.platform.commons.support.ReflectionSupport; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameter; @@ -43,38 +52,37 @@ import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class ThreadContextDataInjectorTest { - @Parameters(name = "{0}") - public static Collection<String[]> threadContextMapClassNames() { - return asList(new String[][] { + + public static final String THREAD_LOCAL_MAP_CLASS_NAME = + "org.apache.logging.log4j.spi.CopyOnWriteSortedArrayThreadContextMap"; + public static final String GARBAGE_FREE_MAP_CLASS_NAME = + "org.apache.logging.log4j.spi.GarbageFreeSortedArrayThreadContextMap"; + + @Parameters(name = "{1}") + public static Object[][] threadContextMapConstructorsAndReadOnlyNames() { + return new Object[][] { { - "org.apache.logging.log4j.spi.CopyOnWriteSortedArrayThreadContextMap", - "org.apache.logging.log4j.spi.CopyOnWriteSortedArrayThreadContextMap" + (Function<Boolean, ThreadContextMap>) ThreadContextDataInjectorTest::createThreadLocalMap, + THREAD_LOCAL_MAP_CLASS_NAME }, { - "org.apache.logging.log4j.spi.GarbageFreeSortedArrayThreadContextMap", - "org.apache.logging.log4j.spi.GarbageFreeSortedArrayThreadContextMap" + (Function<Boolean, ThreadContextMap>) ThreadContextDataInjectorTest::createGarbageFreeMap, + GARBAGE_FREE_MAP_CLASS_NAME }, - {"org.apache.logging.log4j.spi.DefaultThreadContextMap", null} - }); + {(Function<Boolean, ThreadContextMap>) ThreadContextDataInjectorTest::createDefaultMap, null} + }; } - @Parameter - public String threadContextMapClassName; + @Parameter(0) + public Function<Boolean, ThreadContextMap> threadContextMapConstructor; - @Parameter(value = 1) - public String readOnlythreadContextMapClassName; - - @Before - public void before() { - System.setProperty(LoggingSystemProperty.Constant.THREAD_CONTEXT_MAP_CLASS, threadContextMapClassName); - } + @Parameter(1) + public String readOnlyThreadContextMapClassName; @After public void after() { ThreadContext.remove("foo"); ThreadContext.remove("baz"); - System.clearProperty(LoggingSystemProperty.Constant.THREAD_CONTEXT_MAP_CLASS); - System.clearProperty(LoggingSystemProperty.Constant.THREAD_CONTEXT_MAP_INHERITABLE); } private void testContextDataInjector() { @@ -84,7 +92,7 @@ public class ThreadContextDataInjectorTest { (readOnlythreadContextMap == null) ? null : readOnlythreadContextMap.getClass().getName(), - is(equalTo(readOnlythreadContextMapClassName))); + is(equalTo(readOnlyThreadContextMapClassName))); final ContextDataInjector contextDataInjector = createInjector(); final StringMap stringMap = contextDataInjector.injectContextData(null, new SortedArrayStringMap()); @@ -116,11 +124,9 @@ public class ThreadContextDataInjectorTest { } private void prepareThreadContext(final boolean isThreadContextMapInheritable) { - System.setProperty( - LoggingSystemProperty.Constant.THREAD_CONTEXT_MAP_INHERITABLE, - Boolean.toString(isThreadContextMapInheritable)); - ((PropertiesUtil) PropertiesUtil.getProperties()).reload(); - ThreadContextUtilityClass.reset(); + LoggingSystem.getInstance() + .setThreadContextMapFactory(() -> threadContextMapConstructor.apply(isThreadContextMapInheritable)); + ThreadContext.init(); ThreadContext.remove("baz"); ThreadContext.put("foo", "bar"); } @@ -135,16 +141,39 @@ public class ThreadContextDataInjectorTest { public void testInheritableThreadContextImmutability() throws Throwable { prepareThreadContext(true); try { - newSingleThreadExecutor() - .submit(new Runnable() { - @Override - public void run() { - testContextDataInjector(); - } - }) - .get(); + newSingleThreadExecutor().submit(this::testContextDataInjector).get(); } catch (ExecutionException ee) { throw ee.getCause(); } } + + private static ThreadContextMap createThreadLocalMap(final boolean inheritable) { + final Try<Class<?>> loadedClass = ReflectionSupport.tryToLoadClass(THREAD_LOCAL_MAP_CLASS_NAME); + final Class<? extends ThreadContextMap> mapClass = + assertDoesNotThrow(loadedClass::get).asSubclass(ThreadContextMap.class); + return newInstanceWithCapacityArg(mapClass, inheritable); + } + + private static ThreadContextMap createGarbageFreeMap(final boolean inheritable) { + final Try<Class<?>> loadedClass = ReflectionSupport.tryToLoadClass(GARBAGE_FREE_MAP_CLASS_NAME); + final Class<? extends ThreadContextMap> mapClass = + assertDoesNotThrow(loadedClass::get).asSubclass(ThreadContextMap.class); + return newInstanceWithCapacityArg(mapClass, inheritable); + } + + private static ThreadContextMap newInstanceWithCapacityArg( + final Class<? extends ThreadContextMap> mapClass, final boolean inheritable) { + final Constructor<? extends ThreadContextMap> constructor = + assertDoesNotThrow(() -> mapClass.getDeclaredConstructor(Boolean.TYPE, Integer.TYPE)); + assertTrue(constructor.trySetAccessible(), () -> "Unable to access constructor for " + mapClass); + return assertDoesNotThrow( + () -> constructor.newInstance(inheritable, LoggingSystem.THREAD_CONTEXT_DEFAULT_INITIAL_CAPACITY)); + } + + private static ThreadContextMap createDefaultMap(final boolean inheritable) { + final Constructor<DefaultThreadContextMap> constructor = assertDoesNotThrow( + () -> DefaultThreadContextMap.class.getDeclaredConstructor(Boolean.TYPE, Boolean.TYPE)); + assertTrue(constructor.trySetAccessible(), "Unable to construct DefaultThreadContextMap"); + return assertDoesNotThrow(() -> constructor.newInstance(true, inheritable)); + } }
