blob: 9acafadc62ce14f86051c9366917597ea1525828 [file] [log] [blame]
/*
* 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;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceAccessMode;
import org.junit.jupiter.api.parallel.ResourceLock;
import org.junit.jupiter.api.parallel.Resources;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests {@link CloseableThreadContext}.
*
* @since 2.6
*/
@ResourceLock(value = Resources.SYSTEM_PROPERTIES, mode = ResourceAccessMode.READ)
public class CloseableThreadContextTest {
private final String key = "key";
private final String value = "value";
@BeforeEach
@AfterEach
void clearThreadContext() {
ThreadContext.clearAll();
}
@Test
public void shouldAddAnEntryToTheMap() {
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
assertNotNull(ignored);
assertEquals(value, ThreadContext.get(key));
}
}
@Test
public void shouldAddTwoEntriesToTheMap() {
final String key2 = "key2";
final String value2 = "value2";
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value).put(key2, value2)) {
assertNotNull(ignored);
assertEquals(value, ThreadContext.get(key));
assertEquals(value2, ThreadContext.get(key2));
}
}
@Test
public void shouldNestEntries() {
final String oldValue = "oldValue";
final String innerValue = "innerValue";
ThreadContext.put(key, oldValue);
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
assertNotNull(ignored);
assertEquals(value, ThreadContext.get(key));
try (final CloseableThreadContext.Instance ignored2 = CloseableThreadContext.put(key, innerValue)) {
assertNotNull(ignored2);
assertEquals(innerValue, ThreadContext.get(key));
}
assertEquals(value, ThreadContext.get(key));
}
assertEquals(oldValue, ThreadContext.get(key));
}
@Test
public void shouldPreserveOldEntriesFromTheMapWhenAutoClosed() {
final String oldValue = "oldValue";
ThreadContext.put(key, oldValue);
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
assertNotNull(ignored);
assertEquals(value, ThreadContext.get(key));
}
assertEquals(oldValue, ThreadContext.get(key));
}
@Test
public void ifTheSameKeyIsAddedTwiceTheOriginalShouldBeUsed() {
final String oldValue = "oldValue";
final String secondValue = "innerValue";
ThreadContext.put(key, oldValue);
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value).put(key, secondValue)) {
assertNotNull(ignored);
assertEquals(secondValue, ThreadContext.get(key));
}
assertEquals(oldValue, ThreadContext.get(key));
}
@Test
public void shouldPushAndPopAnEntryToTheStack() {
final String message = "message";
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.push(message)) {
assertNotNull(ignored);
assertEquals(message, ThreadContext.peek());
}
assertEquals("", ThreadContext.peek());
}
@Test
public void shouldPushAndPopTwoEntriesToTheStack() {
final String message1 = "message1";
final String message2 = "message2";
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.push(message1).push(message2)) {
assertNotNull(ignored);
assertEquals(message2, ThreadContext.peek());
}
assertEquals("", ThreadContext.peek());
}
@Test
public void shouldPushAndPopAParameterizedEntryToTheStack() {
final String parameterizedMessage = "message {}";
final String parameterizedMessageParameter = "param";
final String formattedMessage = parameterizedMessage.replace("{}", parameterizedMessageParameter);
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.push(parameterizedMessage,
parameterizedMessageParameter)) {
assertNotNull(ignored);
assertEquals(formattedMessage, ThreadContext.peek());
}
assertEquals("", ThreadContext.peek());
}
@Test
public void shouldRemoveAnEntryFromTheMapWhenAutoClosed() {
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value)) {
assertNotNull(ignored);
assertEquals(value, ThreadContext.get(key));
}
assertFalse(ThreadContext.containsKey(key));
}
@Test
public void shouldAddEntriesToBothStackAndMap() {
final String stackValue = "something";
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.put(key, value).push(stackValue)) {
assertNotNull(ignored);
assertEquals(value, ThreadContext.get(key));
assertEquals(stackValue, ThreadContext.peek());
}
assertFalse(ThreadContext.containsKey(key));
assertEquals("", ThreadContext.peek());
}
@Test
public void canReuseCloseableThreadContext() {
final String stackValue = "something";
// Create a ctc and close it
final CloseableThreadContext.Instance ctc = CloseableThreadContext.push(stackValue).put(key, value);
assertNotNull(ctc);
assertEquals(value, ThreadContext.get(key));
assertEquals(stackValue, ThreadContext.peek());
ctc.close();
assertFalse(ThreadContext.containsKey(key));
assertEquals("", ThreadContext.peek());
final String anotherKey = "key2";
final String anotherValue = "value2";
final String anotherStackValue = "something else";
// Use it again
ctc.push(anotherStackValue).put(anotherKey, anotherValue);
assertEquals(anotherValue, ThreadContext.get(anotherKey));
assertEquals(anotherStackValue, ThreadContext.peek());
ctc.close();
assertFalse(ThreadContext.containsKey(anotherKey));
assertEquals("", ThreadContext.peek());
}
@Test
public void closeIsIdempotent() {
final String originalMapValue = "map to keep";
final String originalStackValue = "stack to keep";
ThreadContext.put(key, originalMapValue);
ThreadContext.push(originalStackValue);
final String newMapValue = "temp map value";
final String newStackValue = "temp stack to keep";
final CloseableThreadContext.Instance ctc = CloseableThreadContext.push(newStackValue).put(key, newMapValue);
assertNotNull(ctc);
ctc.close();
assertEquals(originalMapValue, ThreadContext.get(key));
assertEquals(originalStackValue, ThreadContext.peek());
ctc.close();
assertEquals(originalMapValue, ThreadContext.get(key));
assertEquals(originalStackValue, ThreadContext.peek());
}
@Test
public void putAllWillPutAllValues() {
final String oldValue = "oldValue";
ThreadContext.put(key, oldValue);
final Map<String, String> valuesToPut = new HashMap<>();
valuesToPut.put(key, value);
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.putAll(valuesToPut)) {
assertNotNull(ignored);
assertEquals(value, ThreadContext.get(key));
}
assertEquals(oldValue, ThreadContext.get(key));
}
@Test
public void pushAllWillPushAllValues() {
ThreadContext.push(key);
final List<String> messages = ThreadContext.getImmutableStack().asList();
ThreadContext.pop();
try (final CloseableThreadContext.Instance ignored = CloseableThreadContext.pushAll(messages)) {
assertNotNull(ignored);
assertEquals(key, ThreadContext.peek());
}
assertEquals("", ThreadContext.peek());
}
}