diff --git a/src/test/org/apache/commons/logging/PathableClassLoader.java b/src/test/org/apache/commons/logging/PathableClassLoader.java new file mode 100644 index 0000000..ce563a3 --- /dev/null +++ b/src/test/org/apache/commons/logging/PathableClassLoader.java @@ -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. + *
+ * 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. + *
+ * 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. + *
+ * 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. + *
+ * This value defaults to true. + */ + public void setParentFirst(boolean state) { + parentFirst = state; + } + + /** + * For classes with the specified prefix, get them from the system + * classpath which is active at the point this method is called. + *
+ * This method is just a shortcut for + *
+ * useExplicitLoader(prefix, ClassLoader.getSystemClassLoader()); + *+ */ + 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
+ * 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. + *
+ * 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(); + } + } +} diff --git a/src/test/org/apache/commons/logging/PathableTestSuite.java b/src/test/org/apache/commons/logging/PathableTestSuite.java new file mode 100644 index 0000000..117dbae --- /dev/null +++ b/src/test/org/apache/commons/logging/PathableTestSuite.java @@ -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. + *
+ * For tests that need to control exactly what the classloader hierarchy is + * like when the test is run, something like the following is recommended: + *
+ * 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
+ * }
+ *
+ * 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.
+ * + * The use of PathableClassLoader is not required to use this class, but it + * is expected that using the two classes together is common practice. + *
+ * 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 + *
+ * // NB: pseudo-code only + * setContextClassLoader(getContextClassLoader().getParent()); + *+ * 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. + *
+ * 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. + *
+ * 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. + *
+ * Important! 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); + } + } +} diff --git a/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java b/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java new file mode 100644 index 0000000..9c01bd7 --- /dev/null +++ b/src/test/org/apache/commons/logging/jdk14/CustomConfigAPITestCase.java @@ -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); + } +} diff --git a/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java b/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java new file mode 100644 index 0000000..e82f2d1 --- /dev/null +++ b/src/test/org/apache/commons/logging/jdk14/CustomConfigFullTestCase.java @@ -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); + } +} diff --git a/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java b/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java index b6b821a..ac4de29 100644 --- a/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java +++ b/src/test/org/apache/commons/logging/jdk14/CustomConfigTestCase.java @@ -28,6 +28,9 @@ import java.util.logging.Logger; import junit.framework.Test; import junit.framework.TestSuite; +import org.apache.commons.logging.PathableTestSuite; +import org.apache.commons.logging.PathableClassLoader; + /** *
TestCase for JDK 1.4 logging when running on a JDK 1.4 system with @@ -114,8 +117,19 @@ public class CustomConfigTestCase extends DefaultConfigTestCase { /** * 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 @@ public class CustomConfigTestCase extends DefaultConfigTestCase { 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", diff --git a/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java b/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java index 55bacc4..22d3b09 100644 --- a/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java +++ b/src/test/org/apache/commons/logging/jdk14/DefaultConfigTestCase.java @@ -85,7 +85,7 @@ public class DefaultConfigTestCase extends TestCase { /** * Return the tests included in this test suite. */ - public static Test suite() { + public static Test suite() throws Exception { return (new TestSuite(DefaultConfigTestCase.class)); } diff --git a/src/test/org/apache/commons/logging/log4j/CustomConfigAPITestCase.java b/src/test/org/apache/commons/logging/log4j/CustomConfigAPITestCase.java new file mode 100644 index 0000000..63c22aa --- /dev/null +++ b/src/test/org/apache/commons/logging/log4j/CustomConfigAPITestCase.java @@ -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); + } +} diff --git a/src/test/org/apache/commons/logging/log4j/CustomConfigFullTestCase.java b/src/test/org/apache/commons/logging/log4j/CustomConfigFullTestCase.java new file mode 100644 index 0000000..6640281 --- /dev/null +++ b/src/test/org/apache/commons/logging/log4j/CustomConfigFullTestCase.java @@ -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); + } +} diff --git a/src/test/org/apache/commons/logging/log4j/CustomConfigTestCase.java b/src/test/org/apache/commons/logging/log4j/CustomConfigTestCase.java index 0e1efe6..99c0077 100644 --- a/src/test/org/apache/commons/logging/log4j/CustomConfigTestCase.java +++ b/src/test/org/apache/commons/logging/log4j/CustomConfigTestCase.java @@ -23,13 +23,15 @@ import java.util.Iterator; 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; + /** *
TestCase for Log4J logging when running on a system with Log4J present, @@ -103,8 +105,17 @@ public class CustomConfigTestCase extends DefaultConfigTestCase { /** * 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 @@ public class CustomConfigTestCase extends DefaultConfigTestCase { // Test logging message strings with exceptions public void testExceptionMessages() throws Exception { - logExceptionMessages(); checkLoggingEvents(true); diff --git a/src/test/org/apache/commons/logging/log4j/DefaultConfigTestCase.java b/src/test/org/apache/commons/logging/log4j/DefaultConfigTestCase.java index 9e16742..e322a70 100644 --- a/src/test/org/apache/commons/logging/log4j/DefaultConfigTestCase.java +++ b/src/test/org/apache/commons/logging/log4j/DefaultConfigTestCase.java @@ -28,6 +28,8 @@ import junit.framework.TestSuite; 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 @@ public class DefaultConfigTestCase extends TestCase { /** * 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); } /** diff --git a/src/test/org/apache/commons/logging/pathable/PathableTestCase.java b/src/test/org/apache/commons/logging/pathable/PathableTestCase.java new file mode 100644 index 0000000..5ffab3b --- /dev/null +++ b/src/test/org/apache/commons/logging/pathable/PathableTestCase.java @@ -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. + *
+ * These tests assume: + *