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}