You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by sk...@apache.org on 2005/07/08 13:45:29 UTC

svn commit: r209737 - in /jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j: ./ log4j12/

Author: skitching
Date: Fri Jul  8 04:45:25 2005
New Revision: 209737

URL: http://svn.apache.org/viewcvs?rev=209737&view=rev
Log:
Fix up log4j12 tests so no log4j lib needs to be in the classpath
when the suite() method is called on any TestCase class.

Added:
    jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java   (with props)
    jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestHelper.java   (with props)
Removed:
    jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/TestAppender.java
Modified:
    jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/StandardTests.java
    jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java
    jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java
    jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java
    jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java

Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/StandardTests.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/StandardTests.java?rev=209737&r1=209736&r2=209737&view=diff
==============================================================================
--- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/StandardTests.java (original)
+++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/StandardTests.java Fri Jul  8 04:45:25 2005
@@ -22,17 +22,15 @@
 import java.io.InputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+
+import java.util.List;
+import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.Properties;
 
 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.LogFactory;
 import org.apache.commons.logging.impl.Log4J12Logger;
@@ -47,24 +45,40 @@
 
 public abstract class StandardTests extends TestCase {
 
-    // -------------------------------------------------------------------
-    // Constants
-    // ------------------------------------------------------------------- 
-
     /**
-     * The set of message strings that methods logPlainMessages and 
-     * logExceptionMessages output when called.
+     * Simple structure to store information about messages that actually get
+     * logged by the underlying logging library.
      */
-    private static final String TEST_MESSAGES[] = { 
-        "info", "warn", "error", "fatal" 
-    };
-
+    public static class LogEvent {
+        public String msg;
+        public String level;
+        public Throwable throwable;
+    }
+    
     /**
-     * The message levels that the messages in TEST_MESSAGES are logged at.
+     * Simple helper class that can configure log4j to redirect all logged
+     * 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 Level TEST_LEVELS[] = { 
-        Level.INFO, Level.WARN, Level.ERROR, Level.FATAL 
-    };
+
+    public static interface TestHelper {
+        public void forwardMessages(List logEvents);
+    }
 
     // ------------------------------------------------------------------- 
     // JUnit Infrastructure Methods
@@ -84,17 +98,13 @@
         LogFactory.releaseAll();
     }
 
-    // ----------------------------------------------------------- Test Methods
+    // ----------------------------------------------------------- 
+    // abstract methods
+    // ----------------------------------------------------------- 
 
-    /**
-     * 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.
-     */
-    public void testAppender() throws Exception {
-        setUpTestAppender();
-        TestAppender testAppender = getTestAppender();
-        assertNotNull("Appender exists", testAppender);
-    }
+    protected abstract String getTestHelperClassName();
+
+    // ----------------------------------------------------------- Test Methods
 
     /**
      * Test that a LogFactory gets created as expected.
@@ -112,45 +122,33 @@
     }
 
     /**
-     * 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.
      */
     public void testPlainMessages() throws Exception {
-        setUpTestAppender();
+        List logEvents = new ArrayList();
+        setUpTestAppender(logEvents);
         Log log = LogFactory.getLog("test-category");
         logPlainMessages(log);
-        checkLoggingEvents(false);
+        checkLoggingEvents(logEvents, false);
     }
 
     /**
      * Verify that we can log exception messages.
      */
     public void testExceptionMessages() throws Exception {
-        setUpTestAppender();
+        List logEvents = new ArrayList();
+        setUpTestAppender(logEvents);
         Log log = LogFactory.getLog("test-category");
         logExceptionMessages(log);
-        checkLoggingEvents(true);
+        checkLoggingEvents(logEvents, true);
     }
 
     /**
      * Test Serializability of Log instance
      */
     public void testSerializable() throws Exception {
+        List logEvents = new ArrayList();
+        setUpTestAppender(logEvents);
         Log log = LogFactory.getLog("test-category");
 
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -165,37 +163,23 @@
 
         // Check the characteristics of the resulting object
         logExceptionMessages(newLog);
-        checkLoggingEvents(true);
+        checkLoggingEvents(logEvents, true);
     }
 
     // -------------------------------------------------------- Support Methods
 
     /**
-     * Call log4j's PropertyConfigurator passing specific config info
-     * in order to force log4j to create an instance of class TestAppender
-     * 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.
+     * Modify log4j's setup so that all messages actually logged get redirected
+     * into the specified list.
      * <p>
      * This method also sets the logging level to INFO so that we
      * can test whether messages are getting properly filtered.
      */
-    private void setUpTestAppender() throws Exception {
-        Properties props = new Properties();
-        props.put("log4j.rootLogger", "INFO, A1");
-        props.put("log4j.appender.A1", "org.apache.commons.logging.log4j.TestAppender");
-        PropertyConfigurator.configure(props);
-    }
-
-    /**
-     * 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();
+    private void setUpTestAppender(List logEvents) throws Exception {
+        String testHelperClassName = getTestHelperClassName();
+        Class clazz = this.getClass().getClassLoader().loadClass(testHelperClassName);
+        TestHelper testHelper = (TestHelper) clazz.newInstance();
+        testHelper.forwardMessages(logEvents);
     }
 
     /**
@@ -207,36 +191,37 @@
      * called to log a known number of messages at known levels.
      * </ul>
      * 
+     * @param logEvents is the list of log events received.
+     * 
      * @param thrown False if logPlainMessages was called
      * (ie the TestAppender is expected to have received
      * logevents with no associated exception info). True if
      * logExceptionMessages was called.
      */
-    private void checkLoggingEvents(boolean thrown) {
-        TestAppender appender = getTestAppender();
-        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) {
-                assertNotNull("LoggingEvent thrown",
-                              event.getThrowableInformation().getThrowableStrRep());
-                assertTrue("LoggingEvent thrown type",
-                           event.getThrowableInformation()
-                                .getThrowableStrRep()[0]
-                                    .indexOf("IndexOutOfBoundsException")>0);
-            } else {
-                assertNull("LoggingEvent thrown",
-                           event.getThrowableInformation());
-            }
-        }
-        assertTrue(!events.hasNext());
-        appender.flush();
+    private void checkLoggingEvents(List logEvents, boolean thrown) {
+        LogEvent ev;
+        
+        assertEquals("Unexpected number of log events", 4, logEvents.size());
+        
+        ev = (LogEvent) logEvents.get(0);
+        assertEquals("Info message expected", "info", ev.msg);
+        assertEquals("Info level expected", "INFO", ev.level);
+        assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
+        
+        ev = (LogEvent) logEvents.get(1);
+        assertEquals("Warn message expected", "warn", ev.msg);
+        assertEquals("Warn level expected", "WARN", ev.level);
+        assertEquals("Exception data incorrect", (ev.throwable!=null), thrown);
+        
+        ev = (LogEvent) logEvents.get(2);
+        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 @@
         log.fatal("fatal");
     }
 
-    /*
+    /**
      * Log messages with exceptions
      */
     private void logExceptionMessages(Log log) {

Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java?rev=209737&r1=209736&r2=209737&view=diff
==============================================================================
--- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java (original)
+++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ApiClasspathStandardTestCase.java Fri Jul  8 04:45:25 2005
@@ -49,4 +49,12 @@
         Class testClass = child.loadClass(thisClass.getName());
         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";
+    }
 }

Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java?rev=209737&r1=209736&r2=209737&view=diff
==============================================================================
--- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java (original)
+++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/AppClasspathStandardTestCase.java Fri Jul  8 04:45:25 2005
@@ -44,4 +44,12 @@
         Class testClass = loader.loadClass(thisClass.getName());
         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";
+    }
 }

Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java?rev=209737&r1=209736&r2=209737&view=diff
==============================================================================
--- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java (original)
+++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ChildClasspathStandardTestCase.java Fri Jul  8 04:45:25 2005
@@ -47,4 +47,12 @@
         Class testClass = child.loadClass(thisClass.getName());
         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";
+    }
 }

Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java?rev=209737&r1=209736&r2=209737&view=diff
==============================================================================
--- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java (original)
+++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/ParentClasspathStandardTestCase.java Fri Jul  8 04:45:25 2005
@@ -46,4 +46,12 @@
         Class testClass = child.loadClass(thisClass.getName());
         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";
+    }
 }

Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java?rev=209737&view=auto
==============================================================================
--- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java (added)
+++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java Fri Jul  8 04:45:25 2005
@@ -0,0 +1,82 @@
+/*
+ * 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.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.spi.LoggingEvent;
+
+import org.apache.commons.logging.log4j.StandardTests;
+
+/**
+ * A custom implementation of <code>org.apache.log4j.Appender</code> which
+ * converts the log4j-specific log event record into a representation that
+ * doesn't have a dependency on log4j and stores that new representation into
+ * an external list.
+ */
+
+public class TestAppender extends AppenderSkeleton {
+
+    /**
+     * Constructor.
+     */
+    public TestAppender(List logEvents) {
+        events = logEvents;
+    }
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    // The set of logged events for this appender
+    private List events;
+
+
+    // ------------------------------------------------------- Appender Methods
+
+    protected void append(LoggingEvent 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);
+    }
+
+
+    public void close() {
+    }
+
+
+    public boolean requiresLayout() {
+        return (false);
+    }
+
+
+}

Propchange: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestAppender.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestHelper.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestHelper.java?rev=209737&view=auto
==============================================================================
--- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestHelper.java (added)
+++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestHelper.java Fri Jul  8 04:45:25 2005
@@ -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);
+    }
+}

Propchange: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/log4j12/TestHelper.java
------------------------------------------------------------------------------
    svn:keywords = Id



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org