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.pattern;
19  
20  import java.lang.reflect.Method;
21  import java.text.SimpleDateFormat;
22  import java.util.ArrayList;
23  import java.util.Date;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.TimeZone;
29  
30  import junit.framework.TestCase;
31  
32  import org.apache.log4j.Layout;
33  import org.apache.log4j.Level;
34  import org.apache.log4j.Logger;
35  import org.apache.log4j.spi.LoggingEvent;
36  
37  
38  /**
39     Test case for PatternParser.java. Tests the various
40     conversion patterns supported by PatternParser. This test
41     class tests PatternParser via the EnhancedPatternLayout class which
42     uses it.
43   */
44  public class PatternParserTest extends TestCase {
45    private final Logger logger = Logger.getLogger("org.foobar");
46    private final LoggingEvent event;
47  
48    public PatternParserTest(String name) {
49      super(name);
50      event = new LoggingEvent("org.apache.log4j.Logger",
51              logger, Level.INFO, "msg 1", null);
52    }
53  
54    private static String convert(
55                   String pattern,
56                   Map registry,
57                   LoggingEvent event) {
58      List converters = new ArrayList();
59      List fields = new ArrayList();
60      PatternParser.parse(pattern, converters, fields,
61              registry,
62              PatternParser.getPatternLayoutRules());
63      assertEquals(converters.size(), fields.size());
64  
65      StringBuffer buf = new StringBuffer();
66      Iterator converterIter = converters.iterator();
67      Iterator fieldIter = fields.iterator();
68      while(converterIter.hasNext()) {
69          int fieldStart = buf.length();
70          ((PatternConverter) converterIter.next()).format(event, buf);
71          ((FormattingInfo) fieldIter.next()).format(fieldStart, buf);
72      }
73      return buf.toString();
74    }
75  
76    public void testNewWord() throws Exception {
77      HashMap ruleRegistry = new HashMap(5);
78      ruleRegistry.put("z343", Num343PatternConverter.class.getName());
79      String result = convert("%z343", ruleRegistry, event);
80      assertEquals("343", result);
81    }
82  
83    /* Test whether words starting with the letter 'n' are treated differently,
84     * which was previously the case by mistake.
85     */
86    public void testNewWord2() throws Exception {
87      HashMap ruleRegistry = new HashMap(5);
88      ruleRegistry.put("n343", Num343PatternConverter.class.getName());
89      String result = convert("%n343", ruleRegistry, event);
90      assertEquals("343", result);
91    }
92  
93    public void testBogusWord1() throws Exception {
94      String result = convert("%, foobar", null, event);
95      assertEquals("%, foobar", result);
96    }
97  
98    public void testBogusWord2() throws Exception {
99      String result = convert("xyz %, foobar", null, event);
100     assertEquals("xyz %, foobar", result);
101   }
102 
103   public void testBasic1() throws Exception {
104     String result = convert("hello %-5level - %m%n", null, event);
105     assertEquals("hello INFO  - msg 1" + Layout.LINE_SEP, result);
106   }
107 
108   public void testBasic2() throws Exception {
109     String result = convert("%relative %-5level [%thread] %logger - %m%n", null, event);
110 
111     long expectedRelativeTime = event.timeStamp - LoggingEvent.getStartTime();
112     assertEquals(expectedRelativeTime + " INFO  [main] "+logger.getName()+" - msg 1" + Layout.LINE_SEP, result);
113   }
114 
115   public void testMultiOption() throws Exception {
116     String result = convert("%d{HH:mm:ss}{GMT} %d{HH:mm:ss} %c  - %m", null, event);
117 
118     SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
119     String localTime = dateFormat.format(new Date(event.timeStamp));
120     dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
121     String utcTime = dateFormat.format(new Date(event.timeStamp));
122     StringBuffer buf = new StringBuffer(utcTime);
123     buf.append(' ');
124     buf.append(localTime);
125     buf.append(" org.foobar  - msg 1");
126     assertEquals(buf.toString(), result);
127   }
128 
129   public void testBogus() throws Exception {
130       String result = convert("%bogus", null, event);
131       assertEquals("%bogus", result);
132     }
133 
134   public void testMore() throws Exception {
135         String result = convert("%more", null, event);
136         assertEquals("msg 1ore", result);
137   }
138 
139     /**
140      * Options with missing close braces will be treated as a literal.
141      * Endless looped with earlier code.
142      *
143      */
144     public void testMalformedOption() {
145         String result = convert("foo%m{yyyy.MM.dd", null, event);
146         assertEquals("foomsg 1{yyyy.MM.dd", result);
147     }
148 
149 
150   private void assertFactories(Map rules) throws Exception {
151       assertTrue(rules.size() > 0);
152       Iterator iter = rules.values().iterator();
153       Class[] factorySig = new Class[] { Class.forName("[Ljava.lang.String;") };
154       Object[] factoryArg = new Object[] { null };
155       while(iter.hasNext()) {
156           Class ruleClass = (Class) iter.next();
157           Method factory =  ruleClass.getMethod("newInstance", factorySig);
158           Object converter = factory.invoke(null, factoryArg);
159           assertTrue(converter != null);
160       }
161   }
162 
163   public void testPatternLayoutFactories() throws Exception {
164       assertFactories(PatternParser.getPatternLayoutRules());
165   }
166 
167   public void testFileNamePatternFactories() throws Exception {
168         assertFactories(PatternParser.getFileNamePatternRules());
169   }
170 
171 }