1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 import org.apache.log4j.spi.ThrowableInformation;
34
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 EnhancedPatternLayoutTestCase 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|Unknown Source)//)";
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.EnhancedPatternLayoutTestCase.common//(EnhancedPatternLayoutTestCase.java://d{1,4}//): Message //d{1,2}";
61 static String PAT11a =
62 "^(DEBUG|INFO |WARN |ERROR|FATAL) //[main]// log4j.EnhancedPatternLayoutTest: 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.EnhancedPatternLayoutTestCase.common//(EnhancedPatternLayoutTestCase.java://d{3}//): "
68 + "Message //d{1,2}";
69 static String PAT13 =
70 "^//[main]// (DEBUG|INFO |WARN |ERROR|FATAL) "
71 + "apache.log4j.EnhancedPatternLayoutTestCase.common//(EnhancedPatternLayoutTestCase.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 EnhancedPatternLayoutTestCase(final String name) {
80 super(name);
81 }
82
83 public void setUp() {
84 root = Logger.getRootLogger();
85 logger = Logger.getLogger(EnhancedPatternLayoutTest.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 = EnhancedPatternLayoutTestCase.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(EnhancedPatternLayoutTestCase.class, actual, expected);
122 }
123
124
125 public void test1() throws Exception {
126 configure("input/pattern/enhancedPatternLayout1.properties");
127 common();
128 Transformer.transform(
129 TEMP, FILTERED,
130 new Filter[] {
131 new LineNumberFilter(), new SunReflectFilter(),
132 new JunitTestRunnerFilter()
133 });
134 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.1"));
135 }
136
137 public void test2() throws Exception {
138 configure("input/pattern/enhancedPatternLayout2.properties");
139 common();
140
141 ControlFilter cf1 =
142 new ControlFilter(
143 new String[] { PAT1, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
144 Transformer.transform(
145 TEMP, FILTERED,
146 new Filter[] {
147 cf1, new LineNumberFilter(), new ISO8601Filter(),
148 new SunReflectFilter(), new JunitTestRunnerFilter()
149 });
150 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.2"));
151 }
152
153 public void test3() throws Exception {
154 configure("input/pattern/enhancedPatternLayout3.properties");
155 common();
156
157 ControlFilter cf1 =
158 new ControlFilter(
159 new String[] { PAT1, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
160 Transformer.transform(
161 TEMP, FILTERED,
162 new Filter[] {
163 cf1, new LineNumberFilter(), new ISO8601Filter(),
164 new SunReflectFilter(), new JunitTestRunnerFilter()
165 });
166 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.3"));
167 }
168
169
170
171 public void test4() throws Exception {
172 configure("input/pattern/enhancedPatternLayout4.properties");
173 common();
174
175 ControlFilter cf1 =
176 new ControlFilter(
177 new String[] { PAT2, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
178 Transformer.transform(
179 TEMP, FILTERED,
180 new Filter[] {
181 cf1, new LineNumberFilter(), new AbsoluteDateAndTimeFilter(),
182 new SunReflectFilter(), new JunitTestRunnerFilter()
183 });
184 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.4"));
185 }
186
187 public void test5() throws Exception {
188 configure("input/pattern/enhancedPatternLayout5.properties");
189 common();
190
191 ControlFilter cf1 =
192 new ControlFilter(
193 new String[] { PAT2, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
194 Transformer.transform(
195 TEMP, FILTERED,
196 new Filter[] {
197 cf1, new LineNumberFilter(), new AbsoluteDateAndTimeFilter(),
198 new SunReflectFilter(), new JunitTestRunnerFilter()
199 });
200 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.5"));
201 }
202
203
204 public void test6() throws Exception {
205 configure("input/pattern/enhancedPatternLayout6.properties");
206 common();
207
208 ControlFilter cf1 =
209 new ControlFilter(
210 new String[] { PAT3, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
211 Transformer.transform(
212 TEMP, FILTERED,
213 new Filter[] {
214 cf1, new LineNumberFilter(), new AbsoluteTimeFilter(),
215 new SunReflectFilter(), new JunitTestRunnerFilter()
216 });
217 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.6"));
218 }
219
220 public void test7() throws Exception {
221 configure("input/pattern/enhancedPatternLayout7.properties");
222 common();
223
224 ControlFilter cf1 =
225 new ControlFilter(
226 new String[] { PAT3, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
227 Transformer.transform(
228 TEMP, FILTERED,
229 new Filter[] {
230 cf1, new LineNumberFilter(), new AbsoluteTimeFilter(),
231 new SunReflectFilter(), new JunitTestRunnerFilter()
232 });
233 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.7"));
234 }
235
236 public void test8() throws Exception {
237 configure("input/pattern/enhancedPatternLayout8.properties");
238 common();
239
240 ControlFilter cf1 =
241 new ControlFilter(
242 new String[] { PAT4, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
243 Transformer.transform(
244 TEMP, FILTERED,
245 new Filter[] {
246 cf1, new LineNumberFilter(), new RelativeTimeFilter(),
247 new SunReflectFilter(), new JunitTestRunnerFilter()
248 });
249 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.8"));
250 }
251
252 public void test9() throws Exception {
253 configure("input/pattern/enhancedPatternLayout9.properties");
254 common();
255
256 ControlFilter cf1 =
257 new ControlFilter(
258 new String[] { PAT5, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
259 Transformer.transform(
260 TEMP, FILTERED,
261 new Filter[] {
262 cf1, new LineNumberFilter(), new SunReflectFilter(),
263 new JunitTestRunnerFilter()
264 });
265 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.9"));
266 }
267
268 public void test10() throws Exception {
269 configure("input/pattern/enhancedPatternLayout10.properties");
270 common();
271
272 ControlFilter cf1 =
273 new ControlFilter(
274 new String[] { PAT6, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
275 Transformer.transform(
276 TEMP, FILTERED,
277 new Filter[] {
278 cf1, new LineNumberFilter(), new SunReflectFilter(),
279 new JunitTestRunnerFilter()
280 });
281 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.10"));
282 }
283
284 public void test11() throws Exception {
285 configure("input/pattern/enhancedPatternLayout11.properties");
286 common();
287
288 ControlFilter cf1 =
289 new ControlFilter(
290 new String[] { PAT11a, PAT11b, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
291 Transformer.transform(
292 TEMP, FILTERED,
293 new Filter[] {
294 cf1, new LineNumberFilter(), new SunReflectFilter(),
295 new JunitTestRunnerFilter()
296 });
297 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.11"));
298 }
299
300 public void test12() throws Exception {
301 configure("input/pattern/enhancedPatternLayout12.properties");
302 common();
303
304 ControlFilter cf1 =
305 new ControlFilter(
306 new String[] { PAT12, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
307 Transformer.transform(
308 TEMP, FILTERED,
309 new Filter[] {
310 cf1, new LineNumberFilter(), new SunReflectFilter(),
311 new JunitTestRunnerFilter()
312 });
313 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.12"));
314 }
315
316 public void test13() throws Exception {
317 configure("input/pattern/enhancedPatternLayout13.properties");
318 common();
319
320 ControlFilter cf1 =
321 new ControlFilter(
322 new String[] { PAT13, EXCEPTION1, EXCEPTION2, EXCEPTION3 });
323 Transformer.transform(
324 TEMP, FILTERED,
325 new Filter[] {
326 cf1, new LineNumberFilter(), new SunReflectFilter(),
327 new JunitTestRunnerFilter()
328 });
329 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.13"));
330 }
331
332 /***
333 * Test of class abbreviation.
334 *
335 * @throws Exception
336 */
337 public void test14() throws Exception {
338 configure("input/pattern/enhancedPatternLayout14.properties");
339 common();
340
341 Transformer.transform(
342 TEMP, FILTERED,
343 new Filter[] {
344 new LineNumberFilter(), new SunReflectFilter(),
345 new JunitTestRunnerFilter()
346 });
347 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.14"));
348 }
349
350
351 private static void clearMDC() throws Exception {
352 java.util.Hashtable context = MDC.getContext();
353 if (context != null) {
354 context.clear();
355 }
356 }
357
358 public void testMDC1() throws Exception {
359 configure("input/pattern/enhancedPatternLayout.mdc.1.properties");
360 clearMDC();
361 MDC.put("key1", "va11");
362 MDC.put("key2", "va12");
363 logger.debug("Hello World");
364 MDC.remove("key1");
365 MDC.remove("key2");
366
367 Transformer.transform(
368 TEMP, FILTERED,
369 new Filter[] {
370 new LineNumberFilter(), new SunReflectFilter(),
371 new JunitTestRunnerFilter(),
372 new MDCOrderFilter()
373 });
374 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.mdc.1"));
375 }
376 /***
377 * Tests log4j 1.2 style extension of EnhancedPatternLayout.
378 * Was test14 in log4j 1.2.
379 * @throws Exception
380 */
381 public void test15() throws Exception {
382 configure("input/pattern/enhancedPatternLayout15.properties");
383 common();
384 ControlFilter cf1 = new ControlFilter(new String[]{PAT14, EXCEPTION1,
385 EXCEPTION2, EXCEPTION3, EXCEPTION4});
386 Transformer.transform(
387 TEMP, FILTERED,
388 new Filter[] {
389 cf1, new LineNumberFilter(), new SunReflectFilter(),
390 new JunitTestRunnerFilter()
391 });
392 assertTrue(compare(FILTERED, "witness/pattern/enhancedPatternLayout.15"));
393 }
394 /***
395 * Tests explicit UTC time zone in pattern.
396 * @throws Exception
397 */
398 public void test16() throws Exception {
399 final long start = new Date().getTime();
400 configure("input/pattern/enhancedPatternLayout16.properties");
401 common();
402 final long end = new Date().getTime();
403 FileReader reader = new FileReader("patternLayout16.log");
404 char chars[] = new char[50];
405 reader.read(chars, 0, chars.length);
406 reader.close();
407 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
408 format.setTimeZone(TimeZone.getTimeZone("GMT+0"));
409 String utcStr = new String(chars, 0, 19);
410 Date utcDate = format.parse(utcStr, new ParsePosition(0));
411 assertTrue(utcDate.getTime() >= start - 1000 && utcDate.getTime() < end + 1000);
412 String cstStr = new String(chars, 21, 19);
413 format.setTimeZone(TimeZone.getTimeZone("GMT-6"));
414 Date cstDate = format.parse(cstStr, new ParsePosition(0));
415 assertFalse(cstStr.equals(utcStr));
416 assertTrue(cstDate.getTime() >= start - 1000 && cstDate.getTime() < end + 1000);
417 }
418
419 /***
420 * Test left and right truncation
421 */
422 public void test17() throws Exception {
423 configure("input/pattern/enhancedPatternLayout17.properties");
424 root.info("012");
425 root.info("");
426 root.info("12345");
427 root.info("0123456789");
428 assertTrue(compare("patternLayout17.log", "witness/pattern/enhancedPatternLayout.17"));
429 }
430
431
432 void common() {
433 int i = -1;
434
435 logger.debug("Message " + ++i);
436 root.debug("Message " + i);
437
438 logger.info("Message " + ++i);
439 root.info("Message " + i);
440
441 logger.warn("Message " + ++i);
442 root.warn("Message " + i);
443
444 logger.error("Message " + ++i);
445 root.error("Message " + i);
446
447 logger.log(Level.FATAL, "Message " + ++i);
448 root.log(Level.FATAL, "Message " + i);
449
450 Exception e = new Exception("Just testing");
451
452 logger.debug("Message " + ++i, e);
453 logger.info("Message " + ++i, e);
454 logger.warn("Message " + ++i, e);
455 logger.error("Message " + ++i, e);
456 logger.log(Level.FATAL, "Message " + ++i, e);
457 }
458
459 /***
460 Test case for MDC conversion pattern. */
461 public void testMDC2() throws Exception {
462 String OUTPUT_FILE = "patternLayout.mdc.2";
463 String WITNESS_FILE = "witness/pattern/enhancedPatternLayout.mdc.2";
464
465 String mdcMsgPattern1 = "%m : %X%n";
466 String mdcMsgPattern2 = "%m : %X{key1}%n";
467 String mdcMsgPattern3 = "%m : %X{key2}%n";
468 String mdcMsgPattern4 = "%m : %X{key3}%n";
469 String mdcMsgPattern5 = "%m : %X{key1},%X{key2},%X{key3}%n";
470
471
472 EnhancedPatternLayout layout = new EnhancedPatternLayout("%m%n");
473 Appender appender = new FileAppender(layout, OUTPUT_FILE, false);
474
475
476 root.addAppender(appender);
477 root.setLevel(Level.DEBUG);
478
479 clearMDC();
480
481 root.debug("starting mdc pattern test");
482
483 layout.setConversionPattern(mdcMsgPattern1);
484 layout.activateOptions();
485 root.debug("empty mdc, no key specified in pattern");
486
487 layout.setConversionPattern(mdcMsgPattern2);
488 layout.activateOptions();
489 root.debug("empty mdc, key1 in pattern");
490
491 layout.setConversionPattern(mdcMsgPattern3);
492 layout.activateOptions();
493 root.debug("empty mdc, key2 in pattern");
494
495 layout.setConversionPattern(mdcMsgPattern4);
496 layout.activateOptions();
497 root.debug("empty mdc, key3 in pattern");
498
499 layout.setConversionPattern(mdcMsgPattern5);
500 layout.activateOptions();
501 root.debug("empty mdc, key1, key2, and key3 in pattern");
502
503 MDC.put("key1", "value1");
504 MDC.put("key2", "value2");
505
506 layout.setConversionPattern(mdcMsgPattern1);
507 layout.activateOptions();
508 root.debug("filled mdc, no key specified in pattern");
509
510 layout.setConversionPattern(mdcMsgPattern2);
511 layout.activateOptions();
512 root.debug("filled mdc, key1 in pattern");
513
514 layout.setConversionPattern(mdcMsgPattern3);
515 layout.activateOptions();
516 root.debug("filled mdc, key2 in pattern");
517
518 layout.setConversionPattern(mdcMsgPattern4);
519 layout.activateOptions();
520 root.debug("filled mdc, key3 in pattern");
521
522 layout.setConversionPattern(mdcMsgPattern5);
523 layout.activateOptions();
524 root.debug("filled mdc, key1, key2, and key3 in pattern");
525
526 MDC.remove("key1");
527 MDC.remove("key2");
528
529 layout.setConversionPattern("%m%n");
530 layout.activateOptions();
531 root.debug("finished mdc pattern test");
532
533
534 Transformer.transform(
535 OUTPUT_FILE, FILTERED,
536 new Filter[] {
537 new LineNumberFilter(), new SunReflectFilter(),
538 new JunitTestRunnerFilter(),
539 new MDCOrderFilter()
540 });
541
542 assertTrue(compare(FILTERED, WITNESS_FILE));
543 }
544 /***
545 Test case for throwable conversion pattern. */
546 public void testThrowable() throws Exception {
547 String OUTPUT_FILE = "patternLayout.throwable";
548 String WITNESS_FILE = "witness/pattern/enhancedPatternLayout.throwable";
549
550
551
552 EnhancedPatternLayout layout = new EnhancedPatternLayout("%m%n");
553 Appender appender = new FileAppender(layout, OUTPUT_FILE, false);
554
555
556 root.addAppender(appender);
557 root.setLevel(Level.DEBUG);
558
559
560 root.debug("starting throwable pattern test");
561 Exception ex = new Exception("Test Exception");
562 root.debug("plain pattern, no exception");
563 root.debug("plain pattern, with exception", ex);
564 layout.setConversionPattern("%m%n%throwable");
565 layout.activateOptions();
566 root.debug("%throwable, no exception");
567 root.debug("%throwable, with exception", ex);
568
569 layout.setConversionPattern("%m%n%throwable{short}");
570 layout.activateOptions();
571 root.debug("%throwable{short}, no exception");
572 root.debug("%throwable{short}, with exception", ex);
573
574 layout.setConversionPattern("%m%n%throwable{none}");
575 layout.activateOptions();
576 root.debug("%throwable{none}, no exception");
577 root.debug("%throwable{none}, with exception", ex);
578
579
580 layout.setConversionPattern("%m%n%throwable{0}");
581 layout.activateOptions();
582 root.debug("%throwable{0}, no exception");
583 root.debug("%throwable{0}, with exception", ex);
584
585 layout.setConversionPattern("%m%n%throwable{1}");
586 layout.activateOptions();
587 root.debug("%throwable{1}, no exception");
588 root.debug("%throwable{1}, with exception", ex);
589
590 layout.setConversionPattern("%m%n%throwable{100}");
591 layout.activateOptions();
592 root.debug("%throwable{100}, no exception");
593 root.debug("%throwable{100}, with exception", ex);
594
595
596
597
598 String[] trace = new ThrowableInformation(ex).getThrowableStrRep();
599 layout.setConversionPattern("%m%n%throwable{" + (2 - trace.length) + "}");
600 layout.activateOptions();
601 root.debug("%throwable{-n}, no exception");
602 root.debug("%throwable{-n}, with exception", ex);
603
604
605 Transformer.transform(
606 OUTPUT_FILE, FILTERED,
607 new Filter[] {
608 new LineNumberFilter(), new SunReflectFilter(),
609 new JunitTestRunnerFilter(),
610 new MDCOrderFilter()
611 });
612
613 assertTrue(compare(FILTERED, WITNESS_FILE));
614 }
615 }