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.commons.logging.log4j;
19  
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.ObjectInputStream;
24  import java.io.ObjectOutputStream;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import junit.framework.TestCase;
29  
30  import org.apache.commons.logging.DummyException;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  
34  
35  /**
36   * Abstract set of tests that can be executed with various classpaths set.
37   * <p>
38   * The tests verify that when running on a system with Log4J present,
39   * Log4J is selected and that the logger basically works.
40   */
41  
42  public abstract class StandardTests extends TestCase {
43  
44      /**
45       * Simple structure to store information about messages that actually get
46       * logged by the underlying logging library.
47       */
48      public static class LogEvent {
49          public String msg;
50          public String level;
51          public Throwable throwable;
52      }
53  
54      // ------------------------------------------------------------------- 
55      // JUnit Infrastructure Methods
56      // ------------------------------------------------------------------- 
57  
58      /**
59       * Set up instance variables required by this test case.
60       */
61      public void setUp() throws Exception {
62          LogFactory.releaseAll();
63      }
64  
65      /**
66       * Tear down instance variables required by this test case.
67       */
68      public void tearDown() {
69          LogFactory.releaseAll();
70      }
71  
72      // ----------------------------------------------------------- 
73      // abstract methods
74      // ----------------------------------------------------------- 
75  
76      /**
77       * Modify log4j's setup so that all messages actually logged get redirected
78       * into the specified list.
79       * <p>
80       * This method also sets the logging level to INFO so that we
81       * can test whether messages are getting properly filtered.
82       */
83      public abstract void setUpTestAppender(List logEvents) throws Exception;
84      
85      // ----------------------------------------------------------- Test Methods
86  
87      /**
88       * Test that a LogFactory gets created as expected.
89       */
90      public void testCreateFactory() {
91          LogFactory factory = LogFactory.getFactory();
92          assertNotNull("LogFactory exists", factory);
93          assertEquals("LogFactory class",
94                       "org.apache.commons.logging.impl.LogFactoryImpl",
95                       factory.getClass().getName());
96  
97          String names[] = factory.getAttributeNames();
98          assertNotNull("Names exists", names);
99          assertEquals("Names empty", 0, names.length);
100     }
101 
102     /**
103      * Verify that we can log messages without exceptions.
104      */
105     public void testPlainMessages() throws Exception {
106         List logEvents = new ArrayList();
107         setUpTestAppender(logEvents);
108         Log log = LogFactory.getLog("test-category");
109         logPlainMessages(log);
110         checkLoggingEvents(logEvents, false);
111     }
112 
113     /**
114      * Verify that we can log exception messages.
115      */
116     public void testExceptionMessages() throws Exception {
117         List logEvents = new ArrayList();
118         setUpTestAppender(logEvents);
119         Log log = LogFactory.getLog("test-category");
120         logExceptionMessages(log);
121         checkLoggingEvents(logEvents, true);
122     }
123 
124     /**
125      * Test Serializability of Log instance
126      */
127     public void testSerializable() throws Exception {
128         List logEvents = new ArrayList();
129         setUpTestAppender(logEvents);
130         Log log = LogFactory.getLog("test-category");
131 
132         ByteArrayOutputStream baos = new ByteArrayOutputStream();
133         ObjectOutputStream oos = new ObjectOutputStream(baos);
134         oos.writeObject(log);
135         oos.close();
136         ByteArrayInputStream bais =
137             new ByteArrayInputStream(baos.toByteArray());
138         ObjectInputStream ois = new ObjectInputStream(bais);
139         Log newLog = (Log) ois.readObject();
140         ois.close();
141 
142         // Check the characteristics of the resulting object
143         logExceptionMessages(newLog);
144         checkLoggingEvents(logEvents, true);
145     }
146 
147     // -------------------------------------------------------- Support Methods
148 
149     /**
150      * Verify that the TestAppender has received the expected
151      * number of messages. This assumes that:
152      * <ul>
153      * <li>setUpTestAppender has been called
154      * <li>logPlainMessages or logExceptionMessages has been
155      * called to log a known number of messages at known levels.
156      * </ul>
157      * 
158      * @param logEvents is the list of log events received.
159      * 
160      * @param thrown False if logPlainMessages was called
161      * (ie the TestAppender is expected to have received
162      * logevents with no associated exception info). True if
163      * logExceptionMessages was called.
164      */
165     private void checkLoggingEvents(List logEvents, boolean thrown) {
166         LogEvent ev;
167         
168         assertEquals("Unexpected number of log events", 4, logEvents.size());
169         
170         ev = (LogEvent) logEvents.get(0);
171         assertEquals("Info message expected", "info", ev.msg);
172         assertEquals("Info level expected", "INFO", ev.level);
173         assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
174         
175         ev = (LogEvent) logEvents.get(1);
176         assertEquals("Warn message expected", "warn", ev.msg);
177         assertEquals("Warn level expected", "WARN", ev.level);
178         assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
179         
180         ev = (LogEvent) logEvents.get(2);
181         assertEquals("Error message expected", "error", ev.msg);
182         assertEquals("Error level expected", "ERROR", ev.level);
183         assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
184         
185         ev = (LogEvent) logEvents.get(3);
186         assertEquals("Fatal message expected", "fatal", ev.msg);
187         assertEquals("Fatal level expected", "FATAL", ev.level);
188         assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
189     }
190 
191 
192     /**
193      * Log plain messages.
194      */
195     private void logPlainMessages(Log log) {
196         log.trace("trace"); // Should not actually get logged
197         log.debug("debug"); // Should not actually get logged
198         log.info("info");
199         log.warn("warn");
200         log.error("error");
201         log.fatal("fatal");
202     }
203 
204     /**
205      * Log messages with exceptions
206      */
207     private void logExceptionMessages(Log log) {
208         Throwable t = new DummyException();
209         log.trace("trace", t); // Should not actually get logged
210         log.debug("debug", t); // Should not actually get logged
211         log.info("info", t);
212         log.warn("warn", t);
213         log.error("error", t);
214         log.fatal("fatal", t);
215     }
216 }