001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.classic; 015 016import ch.qos.logback.classic.joran.JoranConfigurator; 017import ch.qos.logback.classic.pattern.ConverterTest; 018import ch.qos.logback.classic.spi.ILoggingEvent; 019import ch.qos.logback.classic.spi.LoggingEvent; 020import ch.qos.logback.classic.testUtil.SampleConverter; 021import ch.qos.logback.core.Context; 022import ch.qos.logback.core.joran.spi.JoranException; 023import ch.qos.logback.core.pattern.PatternLayoutBase; 024import ch.qos.logback.core.pattern.parser.test.AbstractPatternLayoutBaseTest; 025import ch.qos.logback.core.testUtil.StringListAppender; 026import ch.qos.logback.core.util.OptionHelper; 027import ch.qos.logback.core.util.StatusPrinter; 028import org.junit.Before; 029import org.junit.Test; 030import org.slf4j.MDC; 031 032import static ch.qos.logback.classic.ClassicTestConstants.ISO_REGEX; 033import static ch.qos.logback.classic.ClassicTestConstants.MAIN_REGEX; 034import static org.junit.Assert.*; 035 036public class PatternLayoutTest extends AbstractPatternLayoutBaseTest<ILoggingEvent> { 037 038 private PatternLayout pl = new PatternLayout(); 039 private LoggerContext lc = new LoggerContext(); 040 Logger logger = lc.getLogger(ConverterTest.class); 041 Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); 042 043 String aMessage = "Some message"; 044 045 ILoggingEvent le; 046 047 public PatternLayoutTest() { 048 super(); 049 Exception ex = new Exception("Bogus exception"); 050 le = makeLoggingEvent(aMessage, ex); 051 } 052 053 @Before 054 public void setUp() { 055 pl.setContext(lc); 056 } 057 058 ILoggingEvent makeLoggingEvent(String msg, Exception ex) { 059 return new LoggingEvent(ch.qos.logback.core.pattern.FormattingConverter.class.getName(), logger, Level.INFO, msg, ex, null); 060 } 061 062 063 public ILoggingEvent getEventObject() { 064 return makeLoggingEvent("Some message", null); 065 } 066 067 public PatternLayoutBase<ILoggingEvent> getPatternLayoutBase() { 068 return new PatternLayout(); 069 } 070 071 @Test 072 public void testOK() { 073 pl.setPattern("%d %le [%t] %lo{30} - %m%n"); 074 pl.start(); 075 String val = pl.doLayout(getEventObject()); 076 // 2006-02-01 22:38:06,212 INFO [main] c.q.l.pattern.ConverterTest - Some 077 // message 078 // 2010-12-29 19:04:26,137 INFO [pool-1-thread-47] c.q.l.c.pattern.ConverterTest - Some message 079 String regex = ISO_REGEX + " INFO " + MAIN_REGEX + " c.q.l.c.pattern.ConverterTest - Some message\\s*"; 080 081 assertTrue("val=" + val, val.matches(regex)); 082 } 083 084 @Test 085 public void testNoExeptionHandler() { 086 pl.setPattern("%m%n"); 087 pl.start(); 088 String val = pl.doLayout(le); 089 assertTrue(val.contains("java.lang.Exception: Bogus exception")); 090 } 091 092 @Test 093 public void testCompositePattern() { 094 pl.setPattern("%-56(%d %lo{20}) - %m%n"); 095 pl.start(); 096 String val = pl.doLayout(getEventObject()); 097 // 2008-03-18 21:55:54,250 c.q.l.c.pattern.ConverterTest - Some message 098 String regex = ISO_REGEX + " c.q.l.c.p.ConverterTest - Some message\\s*"; 099 assertTrue(val.matches(regex)); 100 } 101 102 @Test 103 public void contextProperty() { 104 pl.setPattern("%property{a}"); 105 pl.start(); 106 lc.putProperty("a", "b"); 107 108 String val = pl.doLayout(getEventObject()); 109 assertEquals("b", val); 110 } 111 112 @Test 113 public void testNopExeptionHandler() { 114 pl.setPattern("%nopex %m%n"); 115 pl.start(); 116 String val = pl.doLayout(le); 117 assertTrue(!val.contains("java.lang.Exception: Bogus exception")); 118 } 119 120 @Test 121 public void testWithParenthesis() { 122 pl.setPattern("\\(%msg:%msg\\) %msg"); 123 pl.start(); 124 le = makeLoggingEvent(aMessage, null); 125 String val = pl.doLayout(le); 126 assertEquals("(Some message:Some message) Some message", val); 127 } 128 129 @Test 130 public void testWithLettersComingFromLog4j() { 131 // Letters: p = level and c = logger 132 pl.setPattern("%d %p [%t] %c{30} - %m%n"); 133 pl.start(); 134 String val = pl.doLayout(getEventObject()); 135 // 2006-02-01 22:38:06,212 INFO [main] c.q.l.pattern.ConverterTest - Some 136 // message 137 String regex = ClassicTestConstants.ISO_REGEX + " INFO " + MAIN_REGEX + " c.q.l.c.pattern.ConverterTest - Some message\\s*"; 138 assertTrue(val.matches(regex)); 139 } 140 141 @Test 142 public void mdcWithDefaultValue() { 143 String pattern = "%msg %mdc{foo} %mdc{bar:-[null]}"; 144 pl.setPattern(OptionHelper.substVars(pattern, lc)); 145 pl.start(); 146 MDC.put("foo", "foo"); 147 try { 148 String val = pl.doLayout(getEventObject()); 149 assertEquals("Some message foo [null]", val); 150 } finally { 151 MDC.remove("foo"); 152 } 153 } 154 155 @Test 156 public void contextNameTest() { 157 pl.setPattern("%contextName"); 158 lc.setName("aValue"); 159 pl.start(); 160 String val = pl.doLayout(getEventObject()); 161 assertEquals("aValue", val); 162 } 163 164 @Test 165 public void cnTest() { 166 pl.setPattern("%cn"); 167 lc.setName("aValue"); 168 pl.start(); 169 String val = pl.doLayout(getEventObject()); 170 assertEquals("aValue", val); 171 } 172 173 @Override 174 public Context getContext() { 175 return lc; 176 } 177 178 void configure(String file) throws JoranException { 179 JoranConfigurator jc = new JoranConfigurator(); 180 jc.setContext(lc); 181 jc.doConfigure(file); 182 } 183 184 @Test 185 public void testConversionRuleSupportInPatternLayout() throws JoranException { 186 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "conversionRule/patternLayout0.xml"); 187 root.getAppender("LIST"); 188 String msg = "Simon says"; 189 logger.debug(msg); 190 StringListAppender<ILoggingEvent> sla = (StringListAppender<ILoggingEvent>) root.getAppender("LIST"); 191 assertNotNull(sla); 192 assertEquals(1, sla.strList.size()); 193 assertEquals(SampleConverter.SAMPLE_STR + " - " + msg, sla.strList.get(0)); 194 } 195 196 @Test 197 public void smokeReplace() { 198 pl.setPattern("%replace(a1234b){'\\d{4}', 'XXXX'}"); 199 pl.start(); 200 StatusPrinter.print(lc); 201 String val = pl.doLayout(getEventObject()); 202 assertEquals("aXXXXb", val); 203 } 204 205 @Test 206 public void replaceNewline() { 207 String pattern = "%replace(A\nB){'\n', '\n\t'}"; 208 String substPattern = OptionHelper.substVars(pattern, null, lc); 209 assertEquals(pattern, substPattern); 210 pl.setPattern(substPattern); 211 pl.start(); 212 StatusPrinter.print(lc); 213 String val = pl.doLayout(makeLoggingEvent("", null)); 214 assertEquals("A\n\tB", val); 215 } 216 217 @Test 218 public void replaceWithJoran() throws JoranException { 219 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "pattern/replace0.xml"); 220 StatusPrinter.print(lc); 221 root.getAppender("LIST"); 222 String msg = "And the number is 4111111111110000, expiring on 12/2010"; 223 logger.debug(msg); 224 StringListAppender<ILoggingEvent> sla = (StringListAppender<ILoggingEvent>) root.getAppender("LIST"); 225 assertNotNull(sla); 226 assertEquals(1, sla.strList.size()); 227 assertEquals("And the number is XXXX, expiring on 12/2010", sla.strList.get(0)); 228 } 229 230 @Test 231 public void replaceWithJoran_NEWLINE() throws JoranException { 232 lc.putProperty("TAB", "\t"); 233 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "pattern/replaceNewline.xml"); 234 StatusPrinter.print(lc); 235 root.getAppender("LIST"); 236 String msg = "A\nC"; 237 logger.debug(msg); 238 StringListAppender<ILoggingEvent> sla = (StringListAppender<ILoggingEvent>) root.getAppender("LIST"); 239 assertNotNull(sla); 240 assertEquals(1, sla.strList.size()); 241 assertEquals("A\n\tC", sla.strList.get(0)); 242 } 243}