001/** 002 * Copyright (c) 2004-2013 QOS.ch, Copyright (C) 2015 Google Inc. 003 * All rights reserved. 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining 006 * a copy of this software and associated documentation files (the 007 * "Software"), to deal in the Software without restriction, including 008 * without limitation the rights to use, copy, modify, merge, publish, 009 * distribute, sublicense, and/or sell copies of the Software, and to 010 * permit persons to whom the Software is furnished to do so, subject to 011 * the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be 014 * included in all copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 023 */ 024 025package org.slf4j.helpers; 026 027import static org.junit.Assert.assertEquals; 028import static org.junit.Assert.assertFalse; 029import static org.junit.Assert.assertNull; 030import static org.junit.Assert.fail; 031 032import java.lang.Thread.UncaughtExceptionHandler; 033import java.util.Map; 034 035import org.junit.After; 036import org.junit.Test; 037import org.slf4j.spi.MDCAdapter; 038 039/** 040 * Tests for {@link BasicMDCAdapter} 041 * 042 * @author Lukasz Cwik 043 */ 044public class MDCAdapterTestBase { 045 046 protected MDCAdapter mdc = instantiateMDC(); 047 048 049 050 protected MDCAdapter instantiateMDC() { 051 return new BasicMDCAdapter(); 052 } 053 054 // leave MDC clean 055 @After 056 public void tearDown() throws Exception { 057 mdc.clear(); 058 } 059 060 @Test 061 public void testSettingAndGettingWithMDC() { 062 assertNull(mdc.get("testKey")); 063 mdc.put("testKey", "testValue"); 064 assertEquals(mdc.get("testKey"), "testValue"); 065 } 066 067 @Test 068 public void testOverwritingAKeyInMDC() { 069 assertNull(mdc.get("testKey")); 070 mdc.put("testKey", "testValue"); 071 mdc.put("testKey", "differentTestValue"); 072 assertEquals(mdc.get("testKey"), "differentTestValue"); 073 } 074 075 @Test 076 public void testGetCopyOfContextMapFromMDC() { 077 mdc.put("testKey", "testValue"); 078 Map<String, String> copy = mdc.getCopyOfContextMap(); 079 mdc.put("anotherTestKey", "anotherTestValue"); 080 assertFalse(copy.size() == mdc.getCopyOfContextMap().size()); 081 } 082 083 @Test 084 public void testMDCInheritsValuesFromParentThread() throws Exception { 085 mdc.put("parentKey", "parentValue"); 086 runAndWait(() -> { 087 mdc.put("childKey", "childValue"); 088 assertEquals("parentValue", mdc.get("parentKey")); 089 }); 090 } 091 092 @Test 093 public void testMDCDoesntGetValuesFromChildThread() throws Exception { 094 mdc.put("parentKey", "parentValue"); 095 runAndWait(() -> mdc.put("childKey", "childValue")); 096 assertEquals("parentValue", mdc.get("parentKey")); 097 assertNull(mdc.get("childKey")); 098 } 099 100 101 @Test 102 public void testInvokingSetContextMap_WithANullMap_SLF4J_414() { 103 mdc.setContextMap(null); 104 } 105 106 @Test 107 public void testMDCChildThreadCanOverwriteParentThread() throws Exception { 108 mdc.put("sharedKey", "parentValue"); 109 runAndWait(() -> { 110 assertEquals("parentValue", mdc.get("sharedKey")); 111 mdc.put("sharedKey", "childValue"); 112 assertEquals("childValue", mdc.get("sharedKey")); 113 }); 114 assertEquals("parentValue", mdc.get("sharedKey")); 115 } 116 117 private void runAndWait(Runnable runnable) { 118 RecordingExceptionHandler handler = new RecordingExceptionHandler(); 119 Thread thread = new Thread(runnable); 120 thread.setUncaughtExceptionHandler(handler); 121 thread.start(); 122 try { 123 thread.join(); 124 } catch (Throwable t) { 125 fail("Unexpected failure in child thread:" + t.getMessage()); 126 } 127 assertFalse(handler.getMessage(), handler.hadException()); 128 } 129 130 /** A {@link UncaughtExceptionHandler} that records whether the thread threw an exception. */ 131 private static class RecordingExceptionHandler implements UncaughtExceptionHandler { 132 private Throwable exception; 133 134 @Override 135 public void uncaughtException(Thread t, Throwable e) { 136 exception = e; 137 } 138 139 boolean hadException() { 140 return exception != null; 141 } 142 143 String getMessage() { 144 return exception != null ? exception.getMessage() : ""; 145 } 146 } 147}