Author: skitching Date: Wed Jun 29 20:21:03 2005 New Revision: 202471 URL: http://svn.apache.org/viewcvs?rev=202471&view=rev Log: Allow testcases to control the classloader hierarchy used during the test.
Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableClassLoader.java (with props) jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableTestSuite.java (with props) jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java (with props) jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java (with props) jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigAPITestCase.java (with props) jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigFullTestCase.java (with props) jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/pathable/ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/pathable/PathableTestCase.java (with props) Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigTestCase.java jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/DefaultConfigTestCase.java Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableClassLoader.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableClassLoader.java?rev=202471&view=auto ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableClassLoader.java (added) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableClassLoader.java Wed Jun 29 20:21:03 2005 @@ -0,0 +1,251 @@ +/* + * Created on 24/06/2005 + * + * TODO To change the template for this generated file go to + * Window - Preferences - Java - Code Style - Code Templates + */ + +package org.apache.commons.logging; + +import java.net.URL; +import java.net.URLClassLoader; + +// TODO: use Hashtable instead of HashMap +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; + +import java.util.Enumeration; +import java.util.Vector; +import java.io.File; +import java.io.InputStream; +import java.io.IOException; + +/** + * A ClassLoader which sees only the specified classes. + */ +public class PathableClassLoader extends URLClassLoader { + + private static final URL[] NO_URLS = new URL[0]; + + /** + * A map of package-prefix to ClassLoader. Any class which is in + * this map is looked up via the specified classloader instead of + * the classpath associated with this classloader or its parents. + * <p> + * This is necessary in order for the rest of the world to communicate + * with classes loaded via a custom classloader. As an example, junit + * testcases which are loaded via a custom classloader needs to see + * the same junit classes as the code invoking the testcase, otherwise + * they can't pass result objects back. + * <p> + * Normally, only a classloader created with a null parent needs to + * have any lookasides defined. + */ + private HashMap lookasides = null; + + /** + * See setParentFirst. + */ + private boolean parentFirst = true; + + /** + * Constructor. + */ + public PathableClassLoader(ClassLoader parent) { + super(NO_URLS, parent); + } + + /** + * Specify whether this classloader should ask the parent classloader + * to resolve a class first, before trying to resolve it via its own + * classpath. + * <p> + * Checking with the parent first is the normal approach for java, but + * components within containers such as servlet engines can use + * child-first lookup instead, to allow the components to override libs + * which are visible in shared classloaders provided by the container. + * <p> + * This value defaults to true. + */ + public void setParentFirst(boolean state) { + parentFirst = state; + } + + /** + * For classes with the specified prefix, get them from the system + * classpath <i>which is active at the point this method is called</i>. + * <p> + * This method is just a shortcut for + * <pre> + * useExplicitLoader(prefix, ClassLoader.getSystemClassLoader()); + * </pre> + */ + public void useSystemLoader(String prefix) { + useExplicitLoader(prefix, ClassLoader.getSystemClassLoader()); + + } + + /** + * Specify a classloader to use for specific java packages. + */ + public void useExplicitLoader(String prefix, ClassLoader loader) { + if (lookasides == null) { + lookasides = new HashMap(); + } + lookasides.put(prefix, loader); + } + + /** + * Specify a collection of logical libraries. See addLogicalLib. + */ + public void addLogicalLib(String[] logicalLibs) { + for(int i=0; i<logicalLibs.length; ++i) { + addLogicalLib(logicalLibs[i]); + } + } + + /** + * Specify a logical library to be included in the classpath used to + * locate classes. + * <p> + * The specified lib name is used as a key into the system properties; + * there is expected to be a system property defined with that name + * whose value is a url that indicates where that logical library can + * be found. Typically this is the name of a jar file, or a directory + * containing class files. + * <p> + * Using logical library names allows the calling code to specify its + * desired classpath without knowing the exact location of the necessary + * classes. + */ + public void addLogicalLib(String logicalLib) { + String filename = System.getProperty(logicalLib); + if (filename == null) { + throw new UnknownError( + "Logical lib [" + logicalLib + "] is not defined" + + " as a System property."); + } + + try { + URL url = new File(filename).toURL(); + addURL(url); + } catch(java.net.MalformedURLException e) { + throw new UnknownError( + "Invalid file [" + filename + "] for logical lib [" + logicalLib + "]"); + } + } + + /** + * Override ClassLoader method. + * <p> + * For each explicitly mapped package prefix, if the name matches the + * prefix associated with that entry then attempt to load the class via + * that entries' classloader. + */ + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + // just for performance, check java and javax + if (name.startsWith("java.") || name.startsWith("javax.")) { + return super.loadClass(name, resolve); + } + + if (lookasides != null) { + for(Iterator i = lookasides.entrySet().iterator(); i.hasNext(); ) { + Map.Entry entry = (Map.Entry) i.next(); + String prefix = (String) entry.getKey(); + if (name.startsWith(prefix) == true) { + ClassLoader loader = (ClassLoader) entry.getValue(); + Class clazz = Class.forName(name, resolve, loader); + return clazz; + } + } + } + + if (parentFirst) { + return super.loadClass(name, resolve); + } else { + // ok, implement child-first + try { + Class clazz = super.findClass(name); + if (resolve) { + resolveClass(clazz); + } + return clazz; + } catch(ClassNotFoundException e) { + return super.loadClass(name, resolve); + } + } + } + + /** + * Same as parent class method except that when parentFirst is false + * the resource is looked for in the local classpath before the parent + * loader is consulted. + */ + public URL getResource(String name) { + if (parentFirst) { + return super.getResource(name); + } else { + URL local = super.findResource(name); + if (local != null) { + return local; + } + return super.getResource(name); + } + } + + /** + * Same as parent class method except that when parentFirst is false + * the resource is looked for in the local classpath before the parent + * loader is consulted. + */ + public InputStream getResourceAsStream(String name) { + if (parentFirst) { + return super.getResourceAsStream(name); + } else { + URL local = super.findResource(name); + if (local != null) { + try { + return local.openStream(); + } catch(IOException e) { + // TODO: check if this is right or whether we should + // fall back to trying parent. The javadoc doesn't say... + return null; + } + } + return super.getResourceAsStream(name); + } + } + + /** + * Same as parent class method except that when parentFirst is false + * the resources available from this class are returned at the head of + * the list instead of the tail. + */ + public Enumeration getResources(String name) throws IOException { + if (parentFirst) { + return super.getResources(name); + } else { + Enumeration local = super.findResources(name); + Enumeration parent = getParent().getResources(name); + + if (!local.hasMoreElements()) { + return parent; + } + + if (!parent.hasMoreElements()) { + return local; + } + + Vector v = new Vector(); + while (local.hasMoreElements()) { + v.add(local.nextElement()); + } + while (parent.hasMoreElements()) { + v.add(parent.nextElement()); + } + return v.elements(); + } + } +} Propchange: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableClassLoader.java ------------------------------------------------------------------------------ svn:keywords = Id Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableTestSuite.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableTestSuite.java?rev=202471&view=auto ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableTestSuite.java (added) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableTestSuite.java Wed Jun 29 20:21:03 2005 @@ -0,0 +1,125 @@ +/* + * Created on 24/06/2005 + * + * TODO To change the template for this generated file go to + * Window - Preferences - Java - Code Style - Code Templates + */ + +package org.apache.commons.logging; + +import java.io.PrintStream; + +import junit.framework.Test; +import junit.framework.TestSuite; +import junit.framework.TestResult; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.Vector; + +/** + * Custom TestSuite class that can be used to control the context classloader + * in operation when a test runs. + * <p> + * For tests that need to control exactly what the classloader hierarchy is + * like when the test is run, something like the following is recommended: + * <pre> + * class SomeTestCase extends TestCase { + * public static Test suite() throws Exception { + * PathableClassLoader parent = new PathableClassLoader(null); + * parent.useSystemLoader("junit."); + * + * PathableClassLoader child = new PathableClassLoader(parent); + * child.addLogicalLib("testclasses"); + * child.addLogicalLib("log4j12"); + * child.addLogicalLib("commons-logging"); + * + * Class testClass = child.loadClass(SomeTestCase.class.getName()); + * ClassLoader contextClassLoader = child; + * + * PathableTestSuite suite = new PathableTestSuite(testClass, child); + * return suite; + * } + * + * // test methods go here + * } + * </pre> + * Note that if the suite method throws an exception then this will be handled + * reasonable gracefully by junit; it will report that the suite method for + * a test case failed with exception yyy. + * <p> + * The use of PathableClassLoader is not required to use this class, but it + * is expected that using the two classes together is common practice. + * <p> + * This class will run each test methods within the specified TestCase using + * the specified context classloader and system classloader. If different + * tests within the same class require different context classloaders, + * then the context classloader passed to the constructor should be the + * "lowest" one available, and tests that need the context set to some parent + * of this "lowest" classloader can call + * <pre> + * // NB: pseudo-code only + * setContextClassLoader(getContextClassLoader().getParent()); + * </pre> + * This class ensures that any context classloader changes applied by a test + * is undone after the test is run, so tests don't need to worry about + * restoring the context classloader on exit. + * <p> + * This class does not provide facilities for manipulating system properties; + * tests that need specific system properties can simply set them in the + * fixture or at the start of a test method. + * <p> + * This class cannot control the system classloader (ie what method + * ClassLoader.getSystemClassLoader returns) because Java provides no + * mechanism for setting the system classloader. In this case, the only + * option is to invoke the unit test in a separate JVM with the appropriate + * settings. + * <p> + * <b>Important!</b> When the test case is run, "this.getClass()" refers of + * course to the Class object passed to the constructor of this class - which + * is different from the class whose suite() method was executed to determine + * the classpath. This means that the suite method cannot communicate with + * the test cases simply by setting static variables (for example to make the + * custom classloaders available to the test methods or setUp/tearDown fixtures). + * If this is really necessary then it is possible to use reflection to invoke + * static methods on the class object passed to the constructor of this class + */ +public class PathableTestSuite extends TestSuite { + + /** + * The classloader that should be set as the context classloader + * before each test in the suite is run. + */ + private ClassLoader contextLoader; + + /** + * Constructor. + * + * @param testClass is the TestCase that is to be run, as loaded by + * the appropriate ClassLoader. + * + * @param contextClassLoader is the loader that should be returned by + * calls to Thread.currentThread.getContextClassLoader from test methods + * (or any method called by test methods). + */ + public PathableTestSuite(Class testClass, ClassLoader contextClassLoader) { + super(testClass); + contextLoader = contextClassLoader; + } + + /** + * This method is invoked once for each Test in the current TestSuite. + * Note that a Test may itself be a TestSuite object (ie a collection + * of tests). + */ + public void runTest(Test test, TestResult result) { + ClassLoader origContext = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(contextLoader); + test.run(result); + } finally { + Thread.currentThread().setContextClassLoader(origContext); + } + } +} Propchange: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/PathableTestSuite.java ------------------------------------------------------------------------------ svn:keywords = Id Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java?rev=202471&view=auto ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java (added) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java Wed Jun 29 20:21:03 2005 @@ -0,0 +1,59 @@ +/* + * 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.jdk14; + +import junit.framework.Test; + +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; + + +/** + * TestCase for Jdk14 logging when the commons-logging-api jar file is in + * the parent classpath and commons-logging.jar is in the child. + */ + +public class CustomConfigAPITestCase extends CustomConfigTestCase { + + + public CustomConfigAPITestCase(String name) { + super(name); + } + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useSystemLoader("junit."); + // the TestHandler class must be accessable from the System classloader + // in order for java.util.logging.LogManager.readConfiguration to + // be able to instantiate it. And this test case must see the same + // class in order to be able to access its data. Yes this is ugly + // but the whole jdk14 API is a ******* mess anyway. + parent.useSystemLoader("org.apache.commons.logging.jdk14.TestHandler"); + parent.addLogicalLib("commons-logging-api"); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + child.addLogicalLib("commons-logging"); + + Class testClass = child.loadClass(CustomConfigAPITestCase.class.getName()); + return new PathableTestSuite(testClass, child); + } +} Propchange: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java ------------------------------------------------------------------------------ svn:keywords = Id Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java?rev=202471&view=auto ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java (added) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java Wed Jun 29 20:21:03 2005 @@ -0,0 +1,59 @@ +/* + * 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.jdk14; + + +import junit.framework.Test; + +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; + + +/** + * TestCase for Jdk14 logging when the commons-logging jar file is in + * the parent classpath. + */ + +public class CustomConfigFullTestCase extends CustomConfigTestCase { + + + public CustomConfigFullTestCase(String name) { + super(name); + } + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useSystemLoader("junit."); + // the TestHandler class must be accessable from the System classloader + // in order for java.util.logging.LogManager.readConfiguration to + // be able to instantiate it. And this test case must see the same + // class in order to be able to access its data. Yes this is ugly + // but the whole jdk14 API is a ******* mess anyway. + parent.useSystemLoader("org.apache.commons.logging.jdk14.TestHandler"); + parent.addLogicalLib("commons-logging"); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + + Class testClass = child.loadClass(CustomConfigFullTestCase.class.getName()); + return new PathableTestSuite(testClass, child); + } +} Propchange: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java ------------------------------------------------------------------------------ svn:keywords = Id Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java?rev=202471&r1=202470&r2=202471&view=diff ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java (original) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java Wed Jun 29 20:21:03 2005 @@ -28,6 +28,9 @@ import junit.framework.Test; import junit.framework.TestSuite; +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; + /** * <p>TestCase for JDK 1.4 logging when running on a JDK 1.4 system with @@ -114,8 +117,19 @@ /** * Return the tests included in this test suite. */ - public static Test suite() { - return (new TestSuite(CustomConfigTestCase.class)); + public static Test suite() throws Exception { + /* + PathableClassLoader loader = new PathableClassLoader(null); + loader.useSystemLoader("junit."); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + child.addLogicalLib("commons-logging"); + + Class testClass = child.loadClass(CustomConfigTestCase.class.getName()); + return new PathableTestSuite(testClass, child); + */ + return new TestSuite(CustomConfigTestCase.class); } /** @@ -220,9 +234,9 @@ testLevels[i], record.getLevel()); assertEquals("LogRecord message", testMessages[i], record.getMessage()); - assertEquals("LogRecord class", - this.getClass().getName(), - record.getSourceClassName()); + assertTrue("LogRecord class", + record.getSourceClassName().startsWith( + "org.apache.commons.logging.jdk14.CustomConfig")); if (thrown) { assertEquals("LogRecord method", "logExceptionMessages", Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java?rev=202471&r1=202470&r2=202471&view=diff ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java (original) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java Wed Jun 29 20:21:03 2005 @@ -85,7 +85,7 @@ /** * Return the tests included in this test suite. */ - public static Test suite() { + public static Test suite() throws Exception { return (new TestSuite(DefaultConfigTestCase.class)); } Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigAPITestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigAPITestCase.java?rev=202471&view=auto ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigAPITestCase.java (added) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigAPITestCase.java Wed Jun 29 20:21:03 2005 @@ -0,0 +1,54 @@ +/* + * 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; + +import junit.framework.Test; + +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; + + +/** + * TestCase for Log4J logging when the commons-logging-api jar file is in + * the parent classpath and commons-logging.jar is in the child. + */ + +public class CustomConfigAPITestCase extends CustomConfigTestCase { + + + public CustomConfigAPITestCase(String name) { + super(name); + } + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useSystemLoader("junit."); + parent.addLogicalLib("commons-logging-api"); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + child.addLogicalLib("log4j12"); + child.addLogicalLib("commons-logging"); + + Class testClass = child.loadClass(CustomConfigAPITestCase.class.getName()); + return new PathableTestSuite(testClass, child); + } +} Propchange: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigAPITestCase.java ------------------------------------------------------------------------------ svn:keywords = Id Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigFullTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigFullTestCase.java?rev=202471&view=auto ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigFullTestCase.java (added) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigFullTestCase.java Wed Jun 29 20:21:03 2005 @@ -0,0 +1,53 @@ +/* + * 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; + +import junit.framework.Test; + +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; + + +/** + * TestCase for Log4J logging when the commons-logging jar file is in + * the parent classpath. + */ + +public class CustomConfigFullTestCase extends CustomConfigTestCase { + + + public CustomConfigFullTestCase(String name) { + super(name); + } + + + /** + * Return the tests included in this test suite. + */ + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useSystemLoader("junit."); + parent.addLogicalLib("commons-logging"); + parent.addLogicalLib("log4j12"); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + + Class testClass = child.loadClass(CustomConfigFullTestCase.class.getName()); + return new PathableTestSuite(testClass, child); + } +} Propchange: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigFullTestCase.java ------------------------------------------------------------------------------ svn:keywords = Id Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigTestCase.java?rev=202471&r1=202470&r2=202471&view=diff ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigTestCase.java (original) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/CustomConfigTestCase.java Wed Jun 29 20:21:03 2005 @@ -23,13 +23,15 @@ import java.util.Properties; import junit.framework.Test; -import junit.framework.TestSuite; 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.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; + /** * <p>TestCase for Log4J logging when running on a system with Log4J present, @@ -103,8 +105,17 @@ /** * Return the tests included in this test suite. */ - public static Test suite() { - return (new TestSuite(CustomConfigTestCase.class)); + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useSystemLoader("junit."); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + child.addLogicalLib("log4j12"); + child.addLogicalLib("commons-logging"); + + Class testClass = child.loadClass(CustomConfigTestCase.class.getName()); + return new PathableTestSuite(testClass, child); } /** @@ -123,7 +134,6 @@ // Test logging message strings with exceptions public void testExceptionMessages() throws Exception { - logExceptionMessages(); checkLoggingEvents(true); Modified: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/DefaultConfigTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/DefaultConfigTestCase.java?rev=202471&r1=202470&r2=202471&view=diff ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/DefaultConfigTestCase.java (original) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/log4j/DefaultConfigTestCase.java Wed Jun 29 20:21:03 2005 @@ -28,6 +28,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; /** @@ -85,8 +87,17 @@ /** * Return the tests included in this test suite. */ - public static Test suite() { - return (new TestSuite(DefaultConfigTestCase.class)); + public static Test suite() throws Exception { + PathableClassLoader parent = new PathableClassLoader(null); + parent.useSystemLoader("junit."); + + PathableClassLoader child = new PathableClassLoader(parent); + child.addLogicalLib("testclasses"); + child.addLogicalLib("log4j12"); + child.addLogicalLib("commons-logging"); + + Class testClass = child.loadClass(DefaultConfigTestCase.class.getName()); + return new PathableTestSuite(testClass, child); } /** Added: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/pathable/PathableTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/pathable/PathableTestCase.java?rev=202471&view=auto ============================================================================== --- jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/pathable/PathableTestCase.java (added) +++ jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/pathable/PathableTestCase.java Wed Jun 29 20:21:03 2005 @@ -0,0 +1,129 @@ +/* + * 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.pathable; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; + +/** + * Tests for the PathableTestSuite and PathableClassLoader functionality. + * <p> + * These tests assume: + * <ul> + * <li>junit is in system classpath + * <li>nothing else is in system classpath + * </ul> + */ + +public class PathableTestCase extends TestCase { + public static Test suite() throws Exception { + // make the parent a direct child of the bootloader to hide all + // other classes in the system classpath + PathableClassLoader parent = new PathableClassLoader(null); + + // make the junit classes from the system classpath visible, though, + // as junit won't be able to call this class at all without this.. + parent.useSystemLoader("junit."); + + // make the commons-logging-api.jar classes visible via the parent + parent.addLogicalLib("commons-logging-api"); + + // create a child classloader to load the test case through + PathableClassLoader child = new PathableClassLoader(parent); + + // obviously, the child classloader needs to have the test classes + // in its path! + child.addLogicalLib("testclasses"); + + // create a third classloader to be the context classloader. + PathableClassLoader context = new PathableClassLoader(child); + + // reload this class via the child classloader + Class testClass = child.loadClass(PathableTestCase.class.getName()); + + // and return our custom TestSuite class + return new PathableTestSuite(testClass, context); + } + + public void testPaths() throws Exception { + // the context classloader is not expected to be null + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + assertNotNull("Context classloader is null", contextLoader); + assertEquals("Context classloader has unexpected type", + PathableClassLoader.class.getName(), + contextLoader.getClass().getName()); + + // the classloader that loaded this class is obviously not null + ClassLoader thisLoader = this.getClass().getClassLoader(); + assertNotNull("thisLoader is null", thisLoader); + assertEquals("thisLoader has unexpected type", + PathableClassLoader.class.getName(), + thisLoader.getClass().getName()); + + // the suite method specified that the context classloader's parent + // is the loader that loaded this test case. + assertSame("Context classloader is not child of thisLoader", + thisLoader, contextLoader.getParent()); + + // thisLoader's parent should be available + ClassLoader parentLoader = thisLoader.getParent(); + assertNotNull("Parent classloader is null", parentLoader); + assertEquals("Parent classloader has unexpected type", + PathableClassLoader.class.getName(), + parentLoader.getClass().getName()); + + // parent should have a parent of null + assertNull("Parent classloader has non-null parent", parentLoader.getParent()); + + // getSystemClassloader is not a PathableClassLoader; it's of a + // built-in type. This also verifies that system classloader is none of + // (context, child, parent). + ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); + assertNotNull("System classloader is null", systemLoader); + assertFalse("System classloader has unexpected type", + PathableClassLoader.class.getName().equals( + systemLoader.getClass().getName())); + + // junit classes should be visible; their classloader is system. + // this will of course throw an exception if not found. + Class junitTest = contextLoader.loadClass("junit.framework.Test"); + assertSame("Junit not loaded via systemloader", + systemLoader, junitTest.getClassLoader()); + + // jcl api classes should be visible via the parent + Class logClass = contextLoader.loadClass("org.apache.commons.logging.Log"); + assertSame("Log class not loaded via parent", + logClass.getClassLoader(), parentLoader); + + // jcl non-api classes should not be visible + try { + Class log4jClass = contextLoader.loadClass( + "org.apache.commons.logging.impl.Log4J12Logger"); + fail("Class Log4J12Logger is unexpectedly available"); + } catch(ClassNotFoundException ex) { + // ok + } + + // String class classloader is null + Class stringClass = contextLoader.loadClass("java.lang.String"); + assertNull("String class classloader is not null!", + stringClass.getClassLoader()); + } +} Propchange: jakarta/commons/proper/logging/trunk/src/test/org/apache/commons/logging/pathable/PathableTestCase.java ------------------------------------------------------------------------------ svn:keywords = Id --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]