Fix up log4j12 tests so no log4j lib needs to be in the classpath
when the suite() method is called on any TestCase class. git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/logging/trunk@209737 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -22,17 +22,15 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.ObjectInputStream;
|
import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.log4j.Level;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.apache.log4j.PropertyConfigurator;
|
|
||||||
import org.apache.log4j.spi.LoggingEvent;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.commons.logging.impl.Log4J12Logger;
|
import org.apache.commons.logging.impl.Log4J12Logger;
|
||||||
@@ -47,24 +45,40 @@ import org.apache.commons.logging.impl.Log4J12Logger;
|
|||||||
|
|
||||||
public abstract class StandardTests extends TestCase {
|
public abstract class StandardTests extends TestCase {
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
/**
|
||||||
// Constants
|
* Simple structure to store information about messages that actually get
|
||||||
// -------------------------------------------------------------------
|
* logged by the underlying logging library.
|
||||||
|
*/
|
||||||
|
public static class LogEvent {
|
||||||
|
public String msg;
|
||||||
|
public String level;
|
||||||
|
public Throwable throwable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The set of message strings that methods logPlainMessages and
|
* Simple helper class that can configure log4j to redirect all logged
|
||||||
* logExceptionMessages output when called.
|
* messages into a list of LogEvent messages.
|
||||||
|
* <p>
|
||||||
|
* The TestCase classes that junit will run later have two roles: they
|
||||||
|
* hold the tests to run, and they also provide the suite() method that
|
||||||
|
* indicates which tests to run. This causes complications for us in the
|
||||||
|
* case of log4j because of the binary-incompatible log4j versions. We
|
||||||
|
* can't have any version of log4j to be in the classpath until we are
|
||||||
|
* actually running the tests returned by suite() - but junit can't load
|
||||||
|
* the class to call suite() on it if the class or any of its ancestors
|
||||||
|
* have direct references to log4j APIs (or NoClassDefFound occurs).
|
||||||
|
* <p>
|
||||||
|
* The answer is to move all the direct log4j calls out of the TestCase
|
||||||
|
* classes into a helper which is only loaded via reflection during the
|
||||||
|
* test runs (and not during calls to suite()). This class defines the
|
||||||
|
* interface required of that helper.
|
||||||
|
* <p>
|
||||||
|
* See also method getTestHelperClassName.
|
||||||
*/
|
*/
|
||||||
private static final String TEST_MESSAGES[] = {
|
|
||||||
"info", "warn", "error", "fatal"
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
public static interface TestHelper {
|
||||||
* The message levels that the messages in TEST_MESSAGES are logged at.
|
public void forwardMessages(List logEvents);
|
||||||
*/
|
}
|
||||||
private static final Level TEST_LEVELS[] = {
|
|
||||||
Level.INFO, Level.WARN, Level.ERROR, Level.FATAL
|
|
||||||
};
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// JUnit Infrastructure Methods
|
// JUnit Infrastructure Methods
|
||||||
@@ -84,17 +98,13 @@ public abstract class StandardTests extends TestCase {
|
|||||||
LogFactory.releaseAll();
|
LogFactory.releaseAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------- Test Methods
|
// -----------------------------------------------------------
|
||||||
|
// abstract methods
|
||||||
|
// -----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
protected abstract String getTestHelperClassName();
|
||||||
* Test that our test harness code works, ie that we are able to
|
|
||||||
* configure log4j on the fly to write to an instance of TestAppender.
|
// ----------------------------------------------------------- Test Methods
|
||||||
*/
|
|
||||||
public void testAppender() throws Exception {
|
|
||||||
setUpTestAppender();
|
|
||||||
TestAppender testAppender = getTestAppender();
|
|
||||||
assertNotNull("Appender exists", testAppender);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that a LogFactory gets created as expected.
|
* Test that a LogFactory gets created as expected.
|
||||||
@@ -111,46 +121,34 @@ public abstract class StandardTests extends TestCase {
|
|||||||
assertEquals("Names empty", 0, names.length);
|
assertEquals("Names empty", 0, names.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test that a Log object gets created as expected.
|
|
||||||
*/
|
|
||||||
public void testCreateLog() throws Exception {
|
|
||||||
setUpTestAppender();
|
|
||||||
Log log = LogFactory.getLog("test-category");
|
|
||||||
|
|
||||||
// check that it is of the expected type, that we can access
|
|
||||||
// the underlying real logger and that the logger level has
|
|
||||||
// been set as expected after the call to setUpTestAppender.
|
|
||||||
Log4J12Logger log4j12 = (Log4J12Logger) log;
|
|
||||||
Logger logger = log4j12.getLogger();
|
|
||||||
assertEquals("Logger name", "test-category", logger.getName());
|
|
||||||
assertEquals("Logger level", Level.INFO, logger.getEffectiveLevel());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that we can log messages without exceptions.
|
* Verify that we can log messages without exceptions.
|
||||||
*/
|
*/
|
||||||
public void testPlainMessages() throws Exception {
|
public void testPlainMessages() throws Exception {
|
||||||
setUpTestAppender();
|
List logEvents = new ArrayList();
|
||||||
|
setUpTestAppender(logEvents);
|
||||||
Log log = LogFactory.getLog("test-category");
|
Log log = LogFactory.getLog("test-category");
|
||||||
logPlainMessages(log);
|
logPlainMessages(log);
|
||||||
checkLoggingEvents(false);
|
checkLoggingEvents(logEvents, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that we can log exception messages.
|
* Verify that we can log exception messages.
|
||||||
*/
|
*/
|
||||||
public void testExceptionMessages() throws Exception {
|
public void testExceptionMessages() throws Exception {
|
||||||
setUpTestAppender();
|
List logEvents = new ArrayList();
|
||||||
|
setUpTestAppender(logEvents);
|
||||||
Log log = LogFactory.getLog("test-category");
|
Log log = LogFactory.getLog("test-category");
|
||||||
logExceptionMessages(log);
|
logExceptionMessages(log);
|
||||||
checkLoggingEvents(true);
|
checkLoggingEvents(logEvents, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test Serializability of Log instance
|
* Test Serializability of Log instance
|
||||||
*/
|
*/
|
||||||
public void testSerializable() throws Exception {
|
public void testSerializable() throws Exception {
|
||||||
|
List logEvents = new ArrayList();
|
||||||
|
setUpTestAppender(logEvents);
|
||||||
Log log = LogFactory.getLog("test-category");
|
Log log = LogFactory.getLog("test-category");
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
@@ -165,37 +163,23 @@ public abstract class StandardTests extends TestCase {
|
|||||||
|
|
||||||
// Check the characteristics of the resulting object
|
// Check the characteristics of the resulting object
|
||||||
logExceptionMessages(newLog);
|
logExceptionMessages(newLog);
|
||||||
checkLoggingEvents(true);
|
checkLoggingEvents(logEvents, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------- Support Methods
|
// -------------------------------------------------------- Support Methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call log4j's PropertyConfigurator passing specific config info
|
* Modify log4j's setup so that all messages actually logged get redirected
|
||||||
* in order to force log4j to create an instance of class TestAppender
|
* into the specified list.
|
||||||
* and send all logged messages to that appender object.
|
|
||||||
* <p>
|
|
||||||
* The TestAppender class stores all its messages in memory, so we
|
|
||||||
* can later check what messages it received from log4j.
|
|
||||||
* <p>
|
* <p>
|
||||||
* This method also sets the logging level to INFO so that we
|
* This method also sets the logging level to INFO so that we
|
||||||
* can test whether messages are getting properly filtered.
|
* can test whether messages are getting properly filtered.
|
||||||
*/
|
*/
|
||||||
private void setUpTestAppender() throws Exception {
|
private void setUpTestAppender(List logEvents) throws Exception {
|
||||||
Properties props = new Properties();
|
String testHelperClassName = getTestHelperClassName();
|
||||||
props.put("log4j.rootLogger", "INFO, A1");
|
Class clazz = this.getClass().getClassLoader().loadClass(testHelperClassName);
|
||||||
props.put("log4j.appender.A1", "org.apache.commons.logging.log4j.TestAppender");
|
TestHelper testHelper = (TestHelper) clazz.newInstance();
|
||||||
PropertyConfigurator.configure(props);
|
testHelper.forwardMessages(logEvents);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the custom TestAppender that has been set to recieve all
|
|
||||||
* messages logged via log4j. It is presumed that method setUpTestAppender
|
|
||||||
* has been called earlier to force a TestAppender to be used by log4j.
|
|
||||||
*/
|
|
||||||
private TestAppender getTestAppender() {
|
|
||||||
Enumeration appenders = Logger.getRootLogger().getAllAppenders();
|
|
||||||
return (TestAppender) appenders.nextElement();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -207,36 +191,37 @@ public abstract class StandardTests extends TestCase {
|
|||||||
* called to log a known number of messages at known levels.
|
* called to log a known number of messages at known levels.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* @param logEvents is the list of log events received.
|
||||||
|
*
|
||||||
* @param thrown False if logPlainMessages was called
|
* @param thrown False if logPlainMessages was called
|
||||||
* (ie the TestAppender is expected to have received
|
* (ie the TestAppender is expected to have received
|
||||||
* logevents with no associated exception info). True if
|
* logevents with no associated exception info). True if
|
||||||
* logExceptionMessages was called.
|
* logExceptionMessages was called.
|
||||||
*/
|
*/
|
||||||
private void checkLoggingEvents(boolean thrown) {
|
private void checkLoggingEvents(List logEvents, boolean thrown) {
|
||||||
TestAppender appender = getTestAppender();
|
LogEvent ev;
|
||||||
Iterator events = appender.events();
|
|
||||||
for (int i = 0; i < TEST_MESSAGES.length; i++) {
|
|
||||||
assertTrue("Logged event " + i + " exists",events.hasNext());
|
|
||||||
LoggingEvent event = (LoggingEvent) events.next();
|
|
||||||
assertEquals("LoggingEvent level",
|
|
||||||
TEST_LEVELS[i], event.getLevel());
|
|
||||||
assertEquals("LoggingEvent message",
|
|
||||||
TEST_MESSAGES[i], event.getMessage());
|
|
||||||
|
|
||||||
if (thrown) {
|
assertEquals("Unexpected number of log events", 4, logEvents.size());
|
||||||
assertNotNull("LoggingEvent thrown",
|
|
||||||
event.getThrowableInformation().getThrowableStrRep());
|
ev = (LogEvent) logEvents.get(0);
|
||||||
assertTrue("LoggingEvent thrown type",
|
assertEquals("Info message expected", "info", ev.msg);
|
||||||
event.getThrowableInformation()
|
assertEquals("Info level expected", "INFO", ev.level);
|
||||||
.getThrowableStrRep()[0]
|
assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
|
||||||
.indexOf("IndexOutOfBoundsException")>0);
|
|
||||||
} else {
|
ev = (LogEvent) logEvents.get(1);
|
||||||
assertNull("LoggingEvent thrown",
|
assertEquals("Warn message expected", "warn", ev.msg);
|
||||||
event.getThrowableInformation());
|
assertEquals("Warn level expected", "WARN", ev.level);
|
||||||
}
|
assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
|
||||||
}
|
|
||||||
assertTrue(!events.hasNext());
|
ev = (LogEvent) logEvents.get(2);
|
||||||
appender.flush();
|
assertEquals("Error message expected", "error", ev.msg);
|
||||||
|
assertEquals("Error level expected", "ERROR", ev.level);
|
||||||
|
assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
|
||||||
|
|
||||||
|
ev = (LogEvent) logEvents.get(3);
|
||||||
|
assertEquals("Fatal message expected", "fatal", ev.msg);
|
||||||
|
assertEquals("Fatal level expected", "FATAL", ev.level);
|
||||||
|
assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -252,7 +237,7 @@ public abstract class StandardTests extends TestCase {
|
|||||||
log.fatal("fatal");
|
log.fatal("fatal");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Log messages with exceptions
|
* Log messages with exceptions
|
||||||
*/
|
*/
|
||||||
private void logExceptionMessages(Log log) {
|
private void logExceptionMessages(Log log) {
|
||||||
|
|||||||
@@ -49,4 +49,12 @@ public class ApiClasspathStandardTestCase extends StandardTests {
|
|||||||
Class testClass = child.loadClass(thisClass.getName());
|
Class testClass = child.loadClass(thisClass.getName());
|
||||||
return new PathableTestSuite(testClass, child);
|
return new PathableTestSuite(testClass, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of a class that makes all direct calls to log4j
|
||||||
|
* apis. See StandardTests.TestHelper for more information.
|
||||||
|
*/
|
||||||
|
public String getTestHelperClassName() {
|
||||||
|
return "org.apache.commons.logging.log4j.log4j12.TestHelper";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,4 +44,12 @@ public class AppClasspathStandardTestCase extends StandardTests {
|
|||||||
Class testClass = loader.loadClass(thisClass.getName());
|
Class testClass = loader.loadClass(thisClass.getName());
|
||||||
return new PathableTestSuite(testClass, loader);
|
return new PathableTestSuite(testClass, loader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of a class that makes all direct calls to log4j
|
||||||
|
* apis. See StandardTests.TestHelper for more information.
|
||||||
|
*/
|
||||||
|
public String getTestHelperClassName() {
|
||||||
|
return "org.apache.commons.logging.log4j.log4j12.TestHelper";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,4 +47,12 @@ public class ChildClasspathStandardTestCase extends StandardTests {
|
|||||||
Class testClass = child.loadClass(thisClass.getName());
|
Class testClass = child.loadClass(thisClass.getName());
|
||||||
return new PathableTestSuite(testClass, child);
|
return new PathableTestSuite(testClass, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of a class that makes all direct calls to log4j
|
||||||
|
* apis. See StandardTests.TestHelper for more information.
|
||||||
|
*/
|
||||||
|
public String getTestHelperClassName() {
|
||||||
|
return "org.apache.commons.logging.log4j.log4j12.TestHelper";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,4 +46,12 @@ public class ParentClasspathStandardTestCase extends StandardTests {
|
|||||||
Class testClass = child.loadClass(thisClass.getName());
|
Class testClass = child.loadClass(thisClass.getName());
|
||||||
return new PathableTestSuite(testClass, child);
|
return new PathableTestSuite(testClass, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of a class that makes all direct calls to log4j
|
||||||
|
* apis. See StandardTests.TestHelper for more information.
|
||||||
|
*/
|
||||||
|
public String getTestHelperClassName() {
|
||||||
|
return "org.apache.commons.logging.log4j.log4j12.TestHelper";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2004 The Apache Software Foundation.
|
* Copyright 2005 The Apache Software Foundation.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -14,55 +14,59 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.commons.logging.log4j;
|
package org.apache.commons.logging.log4j.log4j12;
|
||||||
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Level;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
import org.apache.log4j.AppenderSkeleton;
|
import org.apache.log4j.AppenderSkeleton;
|
||||||
import org.apache.log4j.spi.LoggingEvent;
|
import org.apache.log4j.spi.LoggingEvent;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.log4j.StandardTests;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A custom implementation of <code>org.apache.log4j.Appender</code> which
|
* A custom implementation of <code>org.apache.log4j.Appender</code> which
|
||||||
* stores all received log event messages in memory. This allows test code
|
* converts the log4j-specific log event record into a representation that
|
||||||
* to check whether the messages it expected to log have actually been logged.
|
* doesn't have a dependency on log4j and stores that new representation into
|
||||||
*
|
* an external list.
|
||||||
*
|
|
||||||
* @author Craig R. McClanahan
|
|
||||||
* @version $Revision$ $Date$
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class TestAppender extends AppenderSkeleton {
|
public class TestAppender extends AppenderSkeleton {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public TestAppender(List logEvents) {
|
||||||
|
events = logEvents;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------- Instance Variables
|
// ----------------------------------------------------- Instance Variables
|
||||||
|
|
||||||
|
|
||||||
// The set of logged events for this appender
|
// The set of logged events for this appender
|
||||||
private List events = new ArrayList();
|
private List events;
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------- Public Methods
|
|
||||||
|
|
||||||
|
|
||||||
public Iterator events() {
|
|
||||||
return (events.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void flush() {
|
|
||||||
events.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------- Appender Methods
|
// ------------------------------------------------------- Appender Methods
|
||||||
|
|
||||||
|
|
||||||
protected void append(LoggingEvent event) {
|
protected void append(LoggingEvent event) {
|
||||||
events.add(event);
|
StandardTests.LogEvent lev = new StandardTests.LogEvent();
|
||||||
|
|
||||||
|
lev.level = event.getLevel().toString();
|
||||||
|
|
||||||
|
if (event.getMessage() == null)
|
||||||
|
lev.msg = null;
|
||||||
|
else
|
||||||
|
lev.msg = event.getMessage().toString();
|
||||||
|
|
||||||
|
if (event.getThrowableInformation() == null)
|
||||||
|
lev.throwable = null;
|
||||||
|
else
|
||||||
|
lev.throwable = event.getThrowableInformation().getThrowable();
|
||||||
|
|
||||||
|
events.add(lev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005 The Apache Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.commons.logging.log4j.log4j12;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.apache.log4j.Level;
|
||||||
|
import org.apache.commons.logging.log4j.StandardTests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See StandardTests.TestHelper for information on this class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TestHelper implements StandardTests.TestHelper {
|
||||||
|
|
||||||
|
public void forwardMessages(List logEvents) {
|
||||||
|
TestAppender appender = new TestAppender(logEvents);
|
||||||
|
Logger rootLogger = Logger.getRootLogger();
|
||||||
|
rootLogger.removeAllAppenders();
|
||||||
|
rootLogger.addAppender(appender);
|
||||||
|
rootLogger.setLevel(Level.INFO);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user