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.pattern;
015
016import static org.junit.Assert.assertEquals;
017import static org.junit.Assert.assertTrue;
018import static org.junit.Assert.fail;
019
020import java.util.ArrayList;
021import java.util.List;
022import java.util.regex.Pattern;
023
024import org.junit.Before;
025import org.junit.Test;
026import org.slf4j.MDC;
027import org.slf4j.MarkerFactory;
028
029import ch.qos.logback.classic.ClassicConstants;
030import ch.qos.logback.classic.ClassicTestConstants;
031import ch.qos.logback.classic.Level;
032import ch.qos.logback.classic.Logger;
033import ch.qos.logback.classic.LoggerContext;
034import ch.qos.logback.classic.spi.ILoggingEvent;
035import ch.qos.logback.classic.spi.LoggingEvent;
036import ch.qos.logback.core.CoreConstants;
037import ch.qos.logback.core.net.SyslogConstants;
038import ch.qos.logback.core.pattern.DynamicConverter;
039import ch.qos.logback.core.pattern.FormatInfo;
040
041
042public class ConverterTest {
043
044    LoggerContext lc = new LoggerContext();
045    Logger logger = lc.getLogger(ConverterTest.class);
046    LoggingEvent le;
047    List<String> optionList = new ArrayList<String>();
048
049    // The LoggingEvent is massaged with an FCQN of FormattingConverter. This
050    // forces the returned caller information to match the caller stack for this
051    // this particular test.
052    LoggingEvent makeLoggingEvent(Exception ex) {
053        return new LoggingEvent(ch.qos.logback.core.pattern.FormattingConverter.class.getName(), logger, Level.INFO, "Some message", ex, null);
054    }
055
056    Exception getException(String msg, Exception cause) {
057        return new Exception(msg, cause);
058    }
059
060    @Before
061    public void setUp() throws Exception {
062        Exception rootEx = getException("Innermost", null);
063        Exception nestedEx = getException("Nested", rootEx);
064
065        Exception ex = new Exception("Bogus exception", nestedEx);
066
067        le = makeLoggingEvent(ex);
068    }
069
070    @Test
071    public void testLineOfCaller() {
072        {
073            DynamicConverter<ILoggingEvent> converter = new LineOfCallerConverter();
074            StringBuilder buf = new StringBuilder();
075            converter.write(buf, le);
076            // the number below should be the line number of the previous line
077            assertEquals("75", buf.toString());
078        }
079    }
080
081    @Test
082    public void testLevel() {
083        {
084            DynamicConverter<ILoggingEvent> converter = new LevelConverter();
085            StringBuilder buf = new StringBuilder();
086            converter.write(buf, le);
087            assertEquals("INFO", buf.toString());
088        }
089        {
090            DynamicConverter<ILoggingEvent> converter = new LevelConverter();
091            converter.setFormattingInfo(new FormatInfo(1, 1, true, false));
092            StringBuilder buf = new StringBuilder();
093            converter.write(buf, le);
094            assertEquals("I", buf.toString());
095        }
096    }
097
098    @Test
099    public void testThread() {
100        DynamicConverter<ILoggingEvent> converter = new ThreadConverter();
101        StringBuilder buf = new StringBuilder();
102        converter.write(buf, le);
103        System.out.println(buf.toString());
104        String regex = ClassicTestConstants.NAKED_MAIN_REGEX;
105        assertTrue(buf.toString().matches(regex));
106    }
107
108    @Test
109    public void testMessage() {
110        DynamicConverter<ILoggingEvent> converter = new MessageConverter();
111        StringBuilder buf = new StringBuilder();
112        converter.write(buf, le);
113        assertEquals("Some message", buf.toString());
114    }
115
116    @Test
117    public void testLineSeparator() {
118        DynamicConverter<ILoggingEvent> converter = new LineSeparatorConverter();
119        StringBuilder buf = new StringBuilder();
120        converter.write(buf, le);
121        assertEquals(CoreConstants.LINE_SEPARATOR, buf.toString());
122    }
123
124    @Test
125    public void testException() {
126        {
127            DynamicConverter<ILoggingEvent> converter = new ThrowableProxyConverter();
128            StringBuilder buf = new StringBuilder();
129            converter.write(buf, le);
130        }
131
132        {
133            DynamicConverter<ILoggingEvent> converter = new ThrowableProxyConverter();
134            this.optionList.add("3");
135            converter.setOptionList(this.optionList);
136            StringBuilder buf = new StringBuilder();
137            converter.write(buf, le);
138        }
139    }
140
141    @Test
142    public void testLogger() {
143        {
144            ClassicConverter converter = new LoggerConverter();
145            StringBuilder buf = new StringBuilder();
146            converter.write(buf, le);
147            assertEquals(this.getClass().getName(), buf.toString());
148        }
149
150        {
151            ClassicConverter converter = new LoggerConverter();
152            this.optionList.add("20");
153            converter.setOptionList(this.optionList);
154            converter.start();
155            StringBuilder buf = new StringBuilder();
156            converter.write(buf, le);
157            assertEquals("c.q.l.c.p.ConverterTest", buf.toString());
158        }
159
160        {
161            DynamicConverter<ILoggingEvent> converter = new LoggerConverter();
162            this.optionList.clear();
163            this.optionList.add("0");
164            converter.setOptionList(this.optionList);
165            converter.start();
166            StringBuilder buf = new StringBuilder();
167            converter.write(buf, le);
168            assertEquals("ConverterTest", buf.toString());
169        }
170    }
171
172    @Test
173    public void testVeryLongLoggerName() {
174        ClassicConverter converter = new LoggerConverter();
175        this.optionList.add("5");
176        converter.setOptionList(this.optionList);
177        converter.start();
178        StringBuilder buf = new StringBuilder();
179
180        char c = 'a';
181        int extraParts = 3;
182        int totalParts = ClassicConstants.MAX_DOTS + extraParts;
183        StringBuilder loggerNameBuf = new StringBuilder();
184        StringBuilder witness = new StringBuilder();
185
186        for (int i = 0; i < totalParts; i++) {
187            loggerNameBuf.append(c).append(c).append(c);
188            if (i < ClassicConstants.MAX_DOTS) {
189                witness.append(c);
190            } else {
191                witness.append(c).append(c).append(c);
192            }
193            loggerNameBuf.append('.');
194            witness.append('.');
195        }
196        loggerNameBuf.append("zzzzzz");
197        witness.append("zzzzzz");
198
199        le.setLoggerName(loggerNameBuf.toString());
200        converter.write(buf, le);
201        assertEquals(witness.toString(), buf.toString());
202    }
203
204    @Test
205    public void testClass() {
206        DynamicConverter<ILoggingEvent> converter = new ClassOfCallerConverter();
207        StringBuilder buf = new StringBuilder();
208        converter.write(buf, le);
209        assertEquals(this.getClass().getName(), buf.toString());
210    }
211
212    @Test
213    public void testMethodOfCaller() {
214        DynamicConverter<ILoggingEvent> converter = new MethodOfCallerConverter();
215        StringBuilder buf = new StringBuilder();
216        converter.write(buf, le);
217        assertEquals("testMethodOfCaller", buf.toString());
218    }
219
220    @Test
221    public void testFileOfCaller() {
222        DynamicConverter<ILoggingEvent> converter = new FileOfCallerConverter();
223        StringBuilder buf = new StringBuilder();
224        converter.write(buf, le);
225        assertEquals("ConverterTest.java", buf.toString());
226    }
227
228    @Test
229    public void testCallerData() {
230        {
231            DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
232            converter.start();
233
234            StringBuilder buf = new StringBuilder();
235            converter.write(buf, le);
236            if (buf.length() < 10) {
237                fail("buf is too short");
238            }
239        }
240
241        {
242            DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
243            this.optionList.add("2");
244            this.optionList.add("XXX");
245            converter.setOptionList(this.optionList);
246            converter.start();
247
248            StringBuilder buf = new StringBuilder();
249            LoggingEvent event = makeLoggingEvent(null);
250            event.setMarker(MarkerFactory.getMarker("XXX"));
251            converter.write(buf, event);
252            if (buf.length() < 10) {
253                fail("buf is too short");
254            }
255        }
256
257        {
258            DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
259            this.optionList.clear();
260            this.optionList.add("2");
261            this.optionList.add("XXX");
262            this.optionList.add("*");
263            converter.setOptionList(this.optionList);
264            converter.start();
265
266            StringBuilder buf = new StringBuilder();
267            LoggingEvent event = makeLoggingEvent(null);
268            event.setMarker(MarkerFactory.getMarker("YYY"));
269            converter.write(buf, event);
270            if (buf.length() < 10) {
271                fail("buf is too short");
272            }
273        }
274        {
275            DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
276            this.optionList.clear();
277            this.optionList.add("2");
278            this.optionList.add("XXX");
279            this.optionList.add("+");
280            converter.setOptionList(this.optionList);
281            converter.start();
282
283            StringBuilder buf = new StringBuilder();
284            LoggingEvent event = makeLoggingEvent(null);
285            event.setMarker(MarkerFactory.getMarker("YYY"));
286            converter.write(buf, event);
287            if (buf.length() < 10) {
288                fail("buf is too short");
289            }
290        }
291
292        {
293            DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
294            this.optionList.clear();
295            this.optionList.add("2");
296            this.optionList.add("XXX");
297            this.optionList.add("*");
298            converter.setOptionList(this.optionList);
299            converter.start();
300
301            StringBuilder buf = new StringBuilder();
302            converter.write(buf, le);
303            if (buf.length() < 10) {
304                fail("buf is too short");
305            }
306            // System.out.println(buf);
307        }
308
309        {
310            DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
311            this.optionList.clear();
312            this.optionList.add("4..5");
313            converter.setOptionList(this.optionList);
314            converter.start();
315
316            StringBuilder buf = new StringBuilder();
317            converter.write(buf, le);
318            assertTrue("buf is too short", buf.length() >= 10);
319
320            String expectedRegex = "Caller\\+4\t at (java.base\\/)?java.lang.reflect.Method.invoke.*$";
321            String actual = buf.toString();
322            assertTrue("actual: "+actual, Pattern.compile(expectedRegex).matcher(actual).find());
323              
324        }
325    }
326
327    @Test
328    public void testRelativeTime() throws Exception {
329        DynamicConverter<ILoggingEvent> converter = new RelativeTimeConverter();
330        StringBuilder buf0 = new StringBuilder();
331        StringBuilder buf1 = new StringBuilder();
332        long timestamp = System.currentTimeMillis();
333        LoggingEvent e0 = makeLoggingEvent(null);
334        e0.setTimeStamp(timestamp);
335        LoggingEvent e1 = makeLoggingEvent(null);
336        e1.setTimeStamp(timestamp);
337        converter.write(buf0, e0);
338        converter.write(buf1, e1);
339        assertEquals(buf0.toString(), buf1.toString());
340    }
341
342    @Test
343    public void testSyslogStart() throws Exception {
344        DynamicConverter<ILoggingEvent> converter = new SyslogStartConverter();
345        this.optionList.clear();
346        this.optionList.add("MAIL");
347        converter.setOptionList(this.optionList);
348        converter.start();
349
350        ILoggingEvent event = makeLoggingEvent(null);
351
352        StringBuilder buf = new StringBuilder();
353        converter.write(buf, event);
354
355        String expected = "<" + (SyslogConstants.LOG_MAIL + SyslogConstants.INFO_SEVERITY) + ">";
356        assertTrue(buf.toString().startsWith(expected));
357    }
358
359    @Test
360    public void testMDCConverter() throws Exception {
361        MDC.clear();
362        MDC.put("someKey", "someValue");
363        MDCConverter converter = new MDCConverter();
364        this.optionList.clear();
365        this.optionList.add("someKey");
366        converter.setOptionList(optionList);
367        converter.start();
368
369        ILoggingEvent event = makeLoggingEvent(null);
370
371        String result = converter.convert(event);
372        assertEquals("someValue", result);
373    }
374
375    @Test
376    public void contextNameConverter() {
377        ClassicConverter converter = new ContextNameConverter();
378        // see http://jira.qos.ch/browse/LBCLASSIC-149
379        LoggerContext lcOther = new LoggerContext();
380        lcOther.setName("another");
381        converter.setContext(lcOther);
382
383        lc.setName("aValue");
384        ILoggingEvent event = makeLoggingEvent(null);
385
386        String result = converter.convert(event);
387        assertEquals("aValue", result);
388    }
389
390    @Test
391    public void contextProperty() {
392        PropertyConverter converter = new PropertyConverter();
393        converter.setContext(lc);
394        List<String> ol = new ArrayList<String>();
395        ol.add("k");
396        converter.setOptionList(ol);
397        converter.start();
398        lc.setName("aValue");
399        lc.putProperty("k", "v");
400        ILoggingEvent event = makeLoggingEvent(null);
401
402        String result = converter.convert(event);
403        assertEquals("v", result);
404    }
405}