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