View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.pattern;
15  
16  import static org.junit.Assert.assertEquals;
17  import static org.junit.Assert.assertTrue;
18  import static org.junit.Assert.fail;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.regex.Pattern;
23  
24  import org.junit.Before;
25  import org.junit.Test;
26  import org.slf4j.MDC;
27  import org.slf4j.MarkerFactory;
28  
29  import ch.qos.logback.classic.ClassicConstants;
30  import ch.qos.logback.classic.ClassicTestConstants;
31  import ch.qos.logback.classic.Level;
32  import ch.qos.logback.classic.Logger;
33  import ch.qos.logback.classic.LoggerContext;
34  import ch.qos.logback.classic.spi.ILoggingEvent;
35  import ch.qos.logback.classic.spi.LoggingEvent;
36  import ch.qos.logback.core.CoreConstants;
37  import ch.qos.logback.core.net.SyslogConstants;
38  import ch.qos.logback.core.pattern.DynamicConverter;
39  import ch.qos.logback.core.pattern.FormatInfo;
40  import ch.qos.logback.core.util.EnvUtil;
41  
42  public class ConverterTest {
43  
44      LoggerContext lc = new LoggerContext();
45      Logger logger = lc.getLogger(ConverterTest.class);
46      LoggingEvent le;
47      List<String> optionList = new ArrayList<String>();
48  
49      // The LoggingEvent is massaged with an FCQN of FormattingConverter. This
50      // forces the returned caller information to match the caller stack for this
51      // this particular test.
52      LoggingEvent makeLoggingEvent(Exception ex) {
53          return new LoggingEvent(ch.qos.logback.core.pattern.FormattingConverter.class.getName(), logger, Level.INFO,
54                  "Some message", ex, null);
55      }
56  
57      Exception getException(String msg, Exception cause) {
58          return new Exception(msg, cause);
59      }
60  
61      @Before
62      public void setUp() throws Exception {
63          Exception rootEx = getException("Innermost", null);
64          Exception nestedEx = getException("Nested", rootEx);
65  
66          Exception ex = new Exception("Bogus exception", nestedEx);
67  
68          le = makeLoggingEvent(ex);
69      }
70  
71      @Test
72      public void testLineOfCaller() {
73          {
74              DynamicConverter<ILoggingEvent> converter = new LineOfCallerConverter();
75              StringBuilder buf = new StringBuilder();
76              converter.write(buf, le);
77              // the number below should be the line number of the previous line
78              assertEquals("76", buf.toString());
79          }
80      }
81  
82      @Test
83      public void testLevel() {
84          {
85              DynamicConverter<ILoggingEvent> converter = new LevelConverter();
86              StringBuilder buf = new StringBuilder();
87              converter.write(buf, le);
88              assertEquals("INFO", buf.toString());
89          }
90          {
91              DynamicConverter<ILoggingEvent> converter = new LevelConverter();
92              converter.setFormattingInfo(new FormatInfo(1, 1, true, false));
93              StringBuilder buf = new StringBuilder();
94              converter.write(buf, le);
95              assertEquals("I", buf.toString());
96          }
97      }
98  
99      @Test
100     public void testThread() {
101         DynamicConverter<ILoggingEvent> converter = new ThreadConverter();
102         StringBuilder buf = new StringBuilder();
103         converter.write(buf, le);
104         System.out.println(buf.toString());
105         String regex = ClassicTestConstants.NAKED_MAIN_REGEX;
106         assertTrue(buf.toString().matches(regex));
107     }
108 
109     @Test
110     public void testMessage() {
111         DynamicConverter<ILoggingEvent> converter = new MessageConverter();
112         StringBuilder buf = new StringBuilder();
113         converter.write(buf, le);
114         assertEquals("Some message", buf.toString());
115     }
116 
117     @Test
118     public void testLineSeparator() {
119         DynamicConverter<ILoggingEvent> converter = new LineSeparatorConverter();
120         StringBuilder buf = new StringBuilder();
121         converter.write(buf, le);
122         assertEquals(CoreConstants.LINE_SEPARATOR, buf.toString());
123     }
124 
125     @Test
126     public void testException() {
127         {
128             DynamicConverter<ILoggingEvent> converter = new ThrowableProxyConverter();
129             StringBuilder buf = new StringBuilder();
130             converter.write(buf, le);
131         }
132 
133         {
134             DynamicConverter<ILoggingEvent> converter = new ThrowableProxyConverter();
135             this.optionList.add("3");
136             converter.setOptionList(this.optionList);
137             StringBuilder buf = new StringBuilder();
138             converter.write(buf, le);
139         }
140     }
141 
142     @Test
143     public void testLogger() {
144         {
145             ClassicConverter converter = new LoggerConverter();
146             StringBuilder buf = new StringBuilder();
147             converter.write(buf, le);
148             assertEquals(this.getClass().getName(), buf.toString());
149         }
150 
151         {
152             ClassicConverter converter = new LoggerConverter();
153             this.optionList.add("20");
154             converter.setOptionList(this.optionList);
155             converter.start();
156             StringBuilder buf = new StringBuilder();
157             converter.write(buf, le);
158             assertEquals("c.q.l.c.p.ConverterTest", buf.toString());
159         }
160 
161         {
162             DynamicConverter<ILoggingEvent> converter = new LoggerConverter();
163             this.optionList.clear();
164             this.optionList.add("0");
165             converter.setOptionList(this.optionList);
166             converter.start();
167             StringBuilder buf = new StringBuilder();
168             converter.write(buf, le);
169             assertEquals("ConverterTest", buf.toString());
170         }
171     }
172 
173     @Test
174     public void testVeryLongLoggerName() {
175         ClassicConverter converter = new LoggerConverter();
176         this.optionList.add("5");
177         converter.setOptionList(this.optionList);
178         converter.start();
179         StringBuilder buf = new StringBuilder();
180 
181         char c = 'a';
182         int extraParts = 3;
183         int totalParts = ClassicConstants.MAX_DOTS + extraParts;
184         StringBuilder loggerNameBuf = new StringBuilder();
185         StringBuilder witness = new StringBuilder();
186 
187         for (int i = 0; i < totalParts; i++) {
188             loggerNameBuf.append(c).append(c).append(c);
189             witness.append(c);
190             loggerNameBuf.append('.');
191             witness.append('.');
192         }
193         loggerNameBuf.append("zzzzzz");
194         witness.append("zzzzzz");
195 
196         le.setLoggerName(loggerNameBuf.toString());
197         converter.write(buf, le);
198         assertEquals(witness.toString(), buf.toString());
199     }
200 
201     @Test
202     public void testClass() {
203         DynamicConverter<ILoggingEvent> converter = new ClassOfCallerConverter();
204         StringBuilder buf = new StringBuilder();
205         converter.write(buf, le);
206         assertEquals(this.getClass().getName(), buf.toString());
207     }
208 
209     @Test
210     public void testMethodOfCaller() {
211         DynamicConverter<ILoggingEvent> converter = new MethodOfCallerConverter();
212         StringBuilder buf = new StringBuilder();
213         converter.write(buf, le);
214         assertEquals("testMethodOfCaller", buf.toString());
215     }
216 
217     @Test
218     public void testFileOfCaller() {
219         DynamicConverter<ILoggingEvent> converter = new FileOfCallerConverter();
220         StringBuilder buf = new StringBuilder();
221         converter.write(buf, le);
222         assertEquals("ConverterTest.java", buf.toString());
223     }
224 
225     @Test
226     public void testCallerData() {
227         {
228             DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
229             converter.start();
230 
231             StringBuilder buf = new StringBuilder();
232             converter.write(buf, le);
233             if (buf.length() < 10) {
234                 fail("buf is too short");
235             }
236         }
237 
238         {
239             DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
240             this.optionList.add("2");
241             this.optionList.add("XXX");
242             converter.setOptionList(this.optionList);
243             converter.start();
244 
245             StringBuilder buf = new StringBuilder();
246             LoggingEvent event = makeLoggingEvent(null);
247             event.addMarker(MarkerFactory.getMarker("XXX"));
248             converter.write(buf, event);
249             if (buf.length() < 10) {
250                 fail("buf is too short");
251             }
252         }
253 
254         {
255             DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
256             this.optionList.clear();
257             this.optionList.add("2");
258             this.optionList.add("XXX");
259             this.optionList.add("*");
260             converter.setOptionList(this.optionList);
261             converter.start();
262 
263             StringBuilder buf = new StringBuilder();
264             LoggingEvent event = makeLoggingEvent(null);
265             event.addMarker(MarkerFactory.getMarker("YYY"));
266             converter.write(buf, event);
267             if (buf.length() < 10) {
268                 fail("buf is too short");
269             }
270         }
271         {
272             DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
273             this.optionList.clear();
274             this.optionList.add("2");
275             this.optionList.add("XXX");
276             this.optionList.add("+");
277             converter.setOptionList(this.optionList);
278             converter.start();
279 
280             StringBuilder buf = new StringBuilder();
281             LoggingEvent event = makeLoggingEvent(null);
282             event.addMarker(MarkerFactory.getMarker("YYY"));
283             converter.write(buf, event);
284             if (buf.length() < 10) {
285                 fail("buf is too short");
286             }
287         }
288 
289         {
290             DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
291             this.optionList.clear();
292             this.optionList.add("2");
293             this.optionList.add("XXX");
294             this.optionList.add("*");
295             converter.setOptionList(this.optionList);
296             converter.start();
297 
298             StringBuilder buf = new StringBuilder();
299             converter.write(buf, le);
300             if (buf.length() < 10) {
301                 fail("buf is too short");
302             }
303             // System.out.println(buf);
304         }
305 
306         {
307             DynamicConverter<ILoggingEvent> converter = new CallerDataConverter();
308             this.optionList.clear();
309             
310             boolean jdk18 = EnvUtil.isJDK18OrHigher();
311             // jdk 18EA creates a different stack trace
312             if(jdk18) {
313                this.optionList.add("2..3");
314             } else {
315                 this.optionList.add("4..5");
316             }
317             converter.setOptionList(this.optionList);
318             converter.start();
319 
320             StringBuilder buf = new StringBuilder();
321             converter.write(buf, le);
322             assertTrue("buf is too short", buf.length() >= 10);
323 
324             String expectedRegex = "Caller\\+4";
325             if(jdk18) {
326                 expectedRegex = "Caller\\+2";
327             }
328             expectedRegex+="\t at (java.base\\/)?java.lang.reflect.Method.invoke.*$";
329             String actual = buf.toString();
330             assertTrue("actual: " + actual, Pattern.compile(expectedRegex).matcher(actual).find());
331 
332         }
333     }
334 
335     @Test
336     public void testRelativeTime() throws Exception {
337         DynamicConverter<ILoggingEvent> converter = new RelativeTimeConverter();
338         StringBuilder buf0 = new StringBuilder();
339         StringBuilder buf1 = new StringBuilder();
340         long timestamp = System.currentTimeMillis();
341         LoggingEvent e0 = makeLoggingEvent(null);
342         e0.setTimeStamp(timestamp);
343         LoggingEvent e1 = makeLoggingEvent(null);
344         e1.setTimeStamp(timestamp);
345         converter.write(buf0, e0);
346         converter.write(buf1, e1);
347         assertEquals(buf0.toString(), buf1.toString());
348     }
349 
350     @Test
351     public void testSyslogStart() throws Exception {
352         DynamicConverter<ILoggingEvent> converter = new SyslogStartConverter();
353         this.optionList.clear();
354         this.optionList.add("MAIL");
355         converter.setOptionList(this.optionList);
356         converter.start();
357 
358         ILoggingEvent event = makeLoggingEvent(null);
359 
360         StringBuilder buf = new StringBuilder();
361         converter.write(buf, event);
362 
363         String expected = "<" + (SyslogConstants.LOG_MAIL + SyslogConstants.INFO_SEVERITY) + ">";
364         assertTrue(buf.toString().startsWith(expected));
365     }
366 
367     @Test
368     public void testMDCConverter() throws Exception {
369         MDC.clear();
370         MDC.put("someKey", "someValue");
371         MDCConverter converter = new MDCConverter();
372         this.optionList.clear();
373         this.optionList.add("someKey");
374         converter.setOptionList(optionList);
375         converter.start();
376 
377         ILoggingEvent event = makeLoggingEvent(null);
378 
379         String result = converter.convert(event);
380         assertEquals("someValue", result);
381     }
382 
383     @Test
384     public void contextNameConverter() {
385         ClassicConverter converter = new ContextNameConverter();
386         // see http://jira.qos.ch/browse/LBCLASSIC-149
387         LoggerContext lcOther = new LoggerContext();
388         lcOther.setName("another");
389         converter.setContext(lcOther);
390 
391         lc.setName("aValue");
392         ILoggingEvent event = makeLoggingEvent(null);
393 
394         String result = converter.convert(event);
395         assertEquals("aValue", result);
396     }
397 
398     @Test
399     public void contextProperty() {
400         PropertyConverter converter = new PropertyConverter();
401         converter.setContext(lc);
402         List<String> ol = new ArrayList<String>();
403         ol.add("k");
404         converter.setOptionList(ol);
405         converter.start();
406         lc.setName("aValue");
407         lc.putProperty("k", "v");
408         ILoggingEvent event = makeLoggingEvent(null);
409 
410         String result = converter.convert(event);
411         assertEquals("v", result);
412     }
413 }