View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.log4j;
19  
20  import junit.framework.TestCase;
21  import org.apache.log4j.util.AbsoluteDateAndTimeFilter;
22  import org.apache.log4j.util.AbsoluteTimeFilter;
23  import org.apache.log4j.util.Compare;
24  import org.apache.log4j.util.ControlFilter;
25  import org.apache.log4j.util.Filter;
26  import org.apache.log4j.util.ISO8601Filter;
27  import org.apache.log4j.util.JunitTestRunnerFilter;
28  import org.apache.log4j.util.LineNumberFilter;
29  import org.apache.log4j.util.RelativeTimeFilter;
30  import org.apache.log4j.util.SunReflectFilter;
31  import org.apache.log4j.util.Transformer;
32  import org.apache.log4j.util.MDCOrderFilter;
33  
34  import java.io.FileReader;
35  import java.text.ParsePosition;
36  import java.text.SimpleDateFormat;
37  import java.util.Date;
38  import java.util.TimeZone;
39  import java.io.*;
40  import java.util.Properties;
41  
42  
43  public class PatternLayoutTestCase extends TestCase {
44    static String TEMP = "temp";
45    static String FILTERED = "filtered";
46    static String EXCEPTION1 = "java.lang.Exception: Just testing";
47    static String EXCEPTION2 = "//s*at .*//(.*://d{1,4}//)";
48    static String EXCEPTION3 = "//s*at .*//(Native Method//)";
49    static String EXCEPTION4 = "//s*at .*//(.*Compiled Code//)";
50  
51    static String PAT0 =
52      "//[main]// (DEBUG|INFO|WARN|ERROR|FATAL) .* - Message //d{1,2}";
53    static String PAT1 = Filter.ISO8601_PAT + " " + PAT0;
54    static String PAT2 = Filter.ABSOLUTE_DATE_AND_TIME_PAT + " " + PAT0;
55    static String PAT3 = Filter.ABSOLUTE_TIME_PAT + " " + PAT0;
56    static String PAT4 = Filter.RELATIVE_TIME_PAT + " " + PAT0;
57    static String PAT5 =
58      "//[main]// (DEBUG|INFO|WARN|ERROR|FATAL) .* : Message //d{1,2}";
59    static String PAT6 =
60      "//[main]// (DEBUG|INFO |WARN |ERROR|FATAL) org.apache.log4j.PatternLayoutTestCase.common//(PatternLayoutTestCase.java://d{1,4}//): Message //d{1,2}";
61    static String PAT11a =
62      "^(DEBUG|INFO |WARN |ERROR|FATAL) //[main]// log4j.PatternLayoutTest: Message //d{1,2}";
63    static String PAT11b =
64      "^(DEBUG|INFO |WARN |ERROR|FATAL) //[main]// root: Message //d{1,2}";
65    static String PAT12 =
66      "^//[main]// (DEBUG|INFO |WARN |ERROR|FATAL) "
67      + "org.apache.log4j.PatternLayoutTestCase.common//(PatternLayoutTestCase.java://d{3}//): "
68      + "Message //d{1,2}";
69    static String PAT13 =
70      "^//[main]// (DEBUG|INFO |WARN |ERROR|FATAL) "
71      + "apache.log4j.PatternLayoutTestCase.common//(PatternLayoutTestCase.java://d{3}//): "
72      + "Message //d{1,2}";
73    static String PAT14 =
74      "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL)// //d{1,2}// *- Message //d{1,2}";
75    static String PAT_MDC_1 = "";
76    Logger root;
77    Logger logger;
78  
79    public PatternLayoutTestCase(final String name) {
80      super(name);
81    }
82  
83    public void setUp() {
84      root = Logger.getRootLogger();
85      logger = Logger.getLogger(PatternLayoutTest.class);
86    }
87  
88    public void tearDown() {
89      root.getLoggerRepository().resetConfiguration();
90    }
91  
92      /***
93       * Configures log4j from a properties file resource in class loader path.
94       * @param fileName resource name, only last element is significant.
95       * @throws IOException if resource not found or error reading resource.
96       */
97    private static void configure(final String fileName) throws IOException {
98          String resourceName = fileName;
99          int lastSlash = resourceName.lastIndexOf("/");
100         if (lastSlash >= 0) {
101              resourceName = resourceName.substring(lastSlash + 1);
102         }
103         InputStream is = PatternLayoutTestCase.class.getResourceAsStream(resourceName);
104         if (is == null) {
105             throw new FileNotFoundException("Could not find resource " + resourceName);
106         }
107         Properties props = new Properties();
108         props.load(is);
109         PropertyConfigurator.configure(props);
110   }
111 
112     /***
113      * Compares actual and expected files.
114      * @param actual file name for file generated by test
115      * @param expected resource name containing expected output
116      * @return true if files are the same after adjustments
117      * @throws IOException if IO error during comparison.
118      */
119   private static boolean compare(final String actual,
120                                  final String expected) throws IOException {
121       return Compare.compare(PatternLayoutTestCase.class, actual, expected);
122   }
123 
124   public void test1() throws Exception {
125     configure("input/pattern/patternLayout1.properties");
126     common();
127     Transformer.transform(
128       TEMP, FILTERED,
129       new Filter[] {
130         new LineNumberFilter(), new SunReflectFilter(),
131         new JunitTestRunnerFilter()
132       });
133     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.1"));
134   }
135 
136   public void test2() throws Exception {
137     configure("input/pattern/patternLayout2.properties");
138     common();
139 
140     ControlFilter cf1 =
141       new ControlFilter(
142         new String[] { PAT1, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
143     Transformer.transform(
144       TEMP, FILTERED,
145       new Filter[] {
146         cf1, new LineNumberFilter(), new ISO8601Filter(),
147         new SunReflectFilter(), new JunitTestRunnerFilter()
148       });
149     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.2"));
150   }
151 
152   public void test3() throws Exception {
153     configure("input/pattern/patternLayout3.properties");
154     common();
155 
156     ControlFilter cf1 =
157       new ControlFilter(
158         new String[] { PAT1, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
159     Transformer.transform(
160       TEMP, FILTERED,
161       new Filter[] {
162         cf1, new LineNumberFilter(), new ISO8601Filter(),
163         new SunReflectFilter(), new JunitTestRunnerFilter()
164       });
165     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.3"));
166   }
167 
168   // Output format:
169   // 06 avr. 2002 18:30:58,937 [main] DEBUG atternLayoutTest - Message 0  
170   public void test4() throws Exception {
171     configure("input/pattern/patternLayout4.properties");
172     common();
173 
174     ControlFilter cf1 =
175       new ControlFilter(
176         new String[] { PAT2, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
177     Transformer.transform(
178       TEMP, FILTERED,
179       new Filter[] {
180         cf1, new LineNumberFilter(), new AbsoluteDateAndTimeFilter(),
181         new SunReflectFilter(), new JunitTestRunnerFilter()
182       });
183     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.4"));
184   }
185 
186   public void test5() throws Exception {
187     configure("input/pattern/patternLayout5.properties");
188     common();
189 
190     ControlFilter cf1 =
191       new ControlFilter(
192         new String[] { PAT2, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
193     Transformer.transform(
194       TEMP, FILTERED,
195       new Filter[] {
196         cf1, new LineNumberFilter(), new AbsoluteDateAndTimeFilter(),
197         new SunReflectFilter(), new JunitTestRunnerFilter()
198       });
199     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.5"));
200   }
201 
202   // 18:54:19,201 [main] DEBUG atternLayoutTest - Message 0
203   public void test6() throws Exception {
204     configure("input/pattern/patternLayout6.properties");
205     common();
206 
207     ControlFilter cf1 =
208       new ControlFilter(
209         new String[] { PAT3, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
210     Transformer.transform(
211       TEMP, FILTERED,
212       new Filter[] {
213         cf1, new LineNumberFilter(), new AbsoluteTimeFilter(),
214         new SunReflectFilter(), new JunitTestRunnerFilter()
215       });
216     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.6"));
217   }
218 
219   public void test7() throws Exception {
220     configure("input/pattern/patternLayout7.properties");
221     common();
222 
223     ControlFilter cf1 =
224       new ControlFilter(
225         new String[] { PAT3, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
226     Transformer.transform(
227       TEMP, FILTERED,
228       new Filter[] {
229         cf1, new LineNumberFilter(), new AbsoluteTimeFilter(),
230         new SunReflectFilter(), new JunitTestRunnerFilter()
231       });
232     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.7"));
233   }
234 
235   public void test8() throws Exception {
236     configure("input/pattern/patternLayout8.properties");
237     common();
238 
239     ControlFilter cf1 =
240       new ControlFilter(
241         new String[] { PAT4, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
242     Transformer.transform(
243       TEMP, FILTERED,
244       new Filter[] {
245         cf1, new LineNumberFilter(), new RelativeTimeFilter(),
246         new SunReflectFilter(), new JunitTestRunnerFilter()
247       });
248     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.8"));
249   }
250 
251   public void test9() throws Exception {
252     configure("input/pattern/patternLayout9.properties");
253     common();
254 
255     ControlFilter cf1 =
256       new ControlFilter(
257         new String[] { PAT5, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
258     Transformer.transform(
259       TEMP, FILTERED,
260       new Filter[] {
261         cf1, new LineNumberFilter(), new SunReflectFilter(),
262         new JunitTestRunnerFilter()
263       });
264     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.9"));
265   }
266 
267   public void test10() throws Exception {
268     configure("input/pattern/patternLayout10.properties");
269     common();
270 
271     ControlFilter cf1 =
272       new ControlFilter(
273         new String[] { PAT6, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
274     Transformer.transform(
275       TEMP, FILTERED,
276       new Filter[] {
277         cf1, new LineNumberFilter(), new SunReflectFilter(),
278         new JunitTestRunnerFilter()
279       });
280     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.10"));
281   }
282 
283   public void test11() throws Exception {
284     configure("input/pattern/patternLayout11.properties");
285     common();
286 
287     ControlFilter cf1 =
288       new ControlFilter(
289         new String[] { PAT11a, PAT11b, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
290     Transformer.transform(
291       TEMP, FILTERED,
292       new Filter[] {
293         cf1, new LineNumberFilter(), new SunReflectFilter(),
294         new JunitTestRunnerFilter()
295       });
296     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.11"));
297   }
298 
299   public void test12() throws Exception {
300     configure("input/pattern/patternLayout12.properties");
301     common();
302 
303     ControlFilter cf1 =
304       new ControlFilter(
305         new String[] { PAT12, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
306     Transformer.transform(
307       TEMP, FILTERED,
308       new Filter[] {
309         cf1, new LineNumberFilter(), new SunReflectFilter(),
310         new JunitTestRunnerFilter()
311       });
312     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.12"));
313   }
314 
315   public void test13() throws Exception {
316     configure("input/pattern/patternLayout13.properties");
317     common();
318 
319     ControlFilter cf1 =
320       new ControlFilter(
321         new String[] { PAT13, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
322     Transformer.transform(
323       TEMP, FILTERED,
324       new Filter[] {
325         cf1, new LineNumberFilter(), new SunReflectFilter(),
326         new JunitTestRunnerFilter()
327       });
328     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.13"));
329   }
330 
331     /***
332      * Test of class abbreviation.
333      *
334      * @throws Exception
335      */
336     public void test14() throws Exception {
337       configure("input/pattern/patternLayout14.properties");
338       common();
339 
340       Transformer.transform(
341         TEMP, FILTERED,
342         new Filter[] {
343           new LineNumberFilter(), new SunReflectFilter(),
344           new JunitTestRunnerFilter()
345         });
346       assertTrue(compare(FILTERED, "witness/pattern/patternLayout.14"));
347     }
348 
349 
350   public void testMDC1() throws Exception {
351     configure("input/pattern/patternLayout.mdc.1.properties");
352     MDC.put("key1", "va11");
353     MDC.put("key2", "va12");
354     logger.debug("Hello World");
355     MDC.remove("key1");
356     MDC.remove("key2");
357 
358     Transformer.transform(
359       TEMP, FILTERED,
360       new Filter[] {
361         new LineNumberFilter(), new SunReflectFilter(),
362         new JunitTestRunnerFilter(),
363         new MDCOrderFilter()
364       });
365     assertTrue(compare(FILTERED, "witness/pattern/patternLayout.mdc.1"));
366   }
367 
368     /***
369      * Tests log4j 1.2 style extension of EnhancedPatternLayout.
370      * Was test14 in log4j 1.2.
371      * @throws Exception
372      */
373     public void test15() throws Exception {
374       configure("input/pattern/patternLayout15.properties");
375       common();
376       ControlFilter cf1 = new ControlFilter(new String[]{PAT14, EXCEPTION1,
377                                  EXCEPTION2, EXCEPTION3, EXCEPTION4});
378       Transformer.transform(
379         TEMP, FILTERED,
380         new Filter[] {
381           cf1, new LineNumberFilter(), new SunReflectFilter(),
382           new JunitTestRunnerFilter()
383         });
384       assertTrue(compare(FILTERED, "witness/pattern/patternLayout.15"));
385     }
386 
387     /***
388      * Tests explicit UTC time zone in pattern.
389      * @throws Exception
390      */
391     public void test16() throws Exception {
392       final long start = new Date().getTime();
393       configure("input/pattern/patternLayout16.properties");
394       common();
395       final long end = new Date().getTime();
396       FileReader reader = new FileReader("patternLayout16.log");
397       char chars[] = new char[50];
398       reader.read(chars, 0, chars.length);
399       reader.close();
400       SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
401       format.setTimeZone(TimeZone.getTimeZone("GMT+0"));
402       String utcStr = new String(chars, 0, 19);
403       Date utcDate = format.parse(utcStr, new ParsePosition(0));
404       assertTrue(utcDate.getTime() >= start - 1000 && utcDate.getTime() < end + 1000);
405       String cstStr = new String(chars, 21, 19);
406       format.setTimeZone(TimeZone.getTimeZone("GMT-6"));
407       Date cstDate = format.parse(cstStr, new ParsePosition(0));
408       assertFalse(cstStr.equals(utcStr));
409       assertTrue(cstDate.getTime() >= start - 1000 && cstDate.getTime() < end + 1000);
410     }
411 
412 
413   void common() {
414     int i = -1;
415 
416     logger.debug("Message " + ++i);
417     root.debug("Message " + i);
418 
419     logger.info("Message " + ++i);
420     root.info("Message " + i);
421 
422     logger.warn("Message " + ++i);
423     root.warn("Message " + i);
424 
425     logger.error("Message " + ++i);
426     root.error("Message " + i);
427 
428     logger.log(Level.FATAL, "Message " + ++i);
429     root.log(Level.FATAL, "Message " + i);
430 
431     Exception e = new Exception("Just testing");
432 
433     logger.debug("Message " + ++i, e);
434     logger.info("Message " + ++i, e);
435     logger.warn("Message " + ++i, e);
436     logger.error("Message " + ++i, e);
437     logger.log(Level.FATAL, "Message " + ++i, e);
438   }
439 
440   /***
441     Test case for MDC conversion pattern. */
442   public void testMDC2() throws Exception {
443     String OUTPUT_FILE   = "patternLayout.mdc.2";
444     String WITNESS_FILE  = "witness/pattern/patternLayout.mdc.2";
445     
446     String mdcMsgPattern1 = "%m : %X%n";
447     String mdcMsgPattern2 = "%m : %X{key1}%n";
448     String mdcMsgPattern3 = "%m : %X{key2}%n";
449     String mdcMsgPattern4 = "%m : %X{key3}%n";
450     String mdcMsgPattern5 = "%m : %X{key1},%X{key2},%X{key3}%n";
451     
452     // set up appender
453     EnhancedPatternLayout layout = new EnhancedPatternLayout("%m%n");
454     Appender appender = new FileAppender(layout, OUTPUT_FILE, false);
455             
456     // set appender on root and set level to debug
457     root.addAppender(appender);
458     root.setLevel(Level.DEBUG);
459     
460     // output starting message
461     root.debug("starting mdc pattern test");
462  
463     layout.setConversionPattern(mdcMsgPattern1);
464     layout.activateOptions();
465     root.debug("empty mdc, no key specified in pattern");
466     
467     layout.setConversionPattern(mdcMsgPattern2);
468     layout.activateOptions();
469     root.debug("empty mdc, key1 in pattern");
470     
471     layout.setConversionPattern(mdcMsgPattern3);
472     layout.activateOptions();
473     root.debug("empty mdc, key2 in pattern");
474     
475     layout.setConversionPattern(mdcMsgPattern4);
476     layout.activateOptions();
477     root.debug("empty mdc, key3 in pattern");
478     
479     layout.setConversionPattern(mdcMsgPattern5);
480     layout.activateOptions();
481     root.debug("empty mdc, key1, key2, and key3 in pattern");
482 
483     MDC.put("key1", "value1");
484     MDC.put("key2", "value2");
485 
486     layout.setConversionPattern(mdcMsgPattern1);
487     layout.activateOptions();
488     root.debug("filled mdc, no key specified in pattern");
489     
490     layout.setConversionPattern(mdcMsgPattern2);
491     layout.activateOptions();
492     root.debug("filled mdc, key1 in pattern");
493     
494     layout.setConversionPattern(mdcMsgPattern3);
495     layout.activateOptions();
496     root.debug("filled mdc, key2 in pattern");
497     
498     layout.setConversionPattern(mdcMsgPattern4);
499     layout.activateOptions();
500     root.debug("filled mdc, key3 in pattern");
501     
502     layout.setConversionPattern(mdcMsgPattern5);
503     layout.activateOptions();
504     root.debug("filled mdc, key1, key2, and key3 in pattern");
505 
506     MDC.remove("key1");
507     MDC.remove("key2");
508 
509     layout.setConversionPattern("%m%n");
510     layout.activateOptions();
511     root.debug("finished mdc pattern test");
512 
513       Transformer.transform(
514         OUTPUT_FILE, FILTERED,
515         new Filter[] {
516           new LineNumberFilter(), new SunReflectFilter(),
517           new JunitTestRunnerFilter(),
518           new MDCOrderFilter()
519         });
520 
521     assertTrue(compare(FILTERED, WITNESS_FILE));
522   }
523 
524 }