diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/tar/TarFileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/tar/TarFileSystem.java index df472d49e3..e2d33a2441 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/tar/TarFileSystem.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/tar/TarFileSystem.java @@ -54,7 +54,54 @@ public class TarFileSystem extends AbstractFileSystem { private final File file; - private TarArchiveInputStream tarFile; + private TarFileThreadLocal tarFile = new TarFileThreadLocal(); + + private class TarFileCreationException extends RuntimeException { + TarFileCreationException(Throwable cause) { + super(cause); + } + } + + private class TarFileThreadLocal { + + private ThreadLocal isPresent = new ThreadLocal() { + @Override + protected Boolean initialValue() { + return Boolean.FALSE; + } + }; + private ThreadLocal tarFile = new ThreadLocal() { + @Override + public TarArchiveInputStream initialValue() { + if (isPresent.get()) { + throw new IllegalStateException("Creating an initial value but we already have one"); + } + try { + isPresent.set(Boolean.TRUE); + return createTarFile(TarFileSystem.this.file); + } catch (FileSystemException fse) { + throw new TarFileCreationException(fse); + } + } + }; + + public TarArchiveInputStream getFile() throws FileSystemException { + try { + return tarFile.get(); + } catch (TarFileCreationException e) { + throw new FileSystemException(e); + } + } + + public void closeFile() throws IOException { + if (isPresent.get()) { + TarArchiveInputStream file = tarFile.get(); + file.close(); + tarFile.remove(); + isPresent.set(Boolean.FALSE); + } + } + } /** * Cache doesn't need to be synchronized since it is read-only. @@ -117,10 +164,7 @@ protected TarFileObject createTarFileObject(final AbstractFileName name, final T protected void doCloseCommunicationLink() { // Release the tar file try { - if (tarFile != null) { - tarFile.close(); - tarFile = null; - } + tarFile.closeFile(); } catch (final IOException e) { // getLogger().warn("vfs.provider.tar/close-tar-file.error :" + file, e); VfsLog.warn(getLogger(), LOG, "vfs.provider.tar/close-tar-file.error :" + file, e); @@ -147,6 +191,7 @@ public InputStream getInputStream(final TarArchiveEntry entry) throws FileSystem resetTarFile(); try { ArchiveEntry next; + TarArchiveInputStream tarFile = getTarFile(); while ((next = tarFile.getNextEntry()) != null) { if (next.equals(entry)) { return tarFile; @@ -159,10 +204,7 @@ public InputStream getInputStream(final TarArchiveEntry entry) throws FileSystem } protected TarArchiveInputStream getTarFile() throws FileSystemException { - if (tarFile == null && this.file.exists()) { - recreateTarFile(); - } - return tarFile; + return tarFile.getFile(); } @Override @@ -225,15 +267,12 @@ protected void putFileToCache(final FileObject file) { */ private void recreateTarFile() throws FileSystemException { - if (this.tarFile != null) { - try { - this.tarFile.close(); - } catch (final IOException e) { - throw new FileSystemException("vfs.provider.tar/close-tar-file.error", file, e); - } - tarFile = null; + try { + tarFile.closeFile(); + } catch (final IOException e) { + throw new FileSystemException("vfs.provider.tar/close-tar-file.error", file, e); } - this.tarFile = createTarFile(this.file); + tarFile.getFile(); } /** diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/zip/ZipFileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/zip/ZipFileSystem.java index 78a57ae373..549f2d65ae 100644 --- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/zip/ZipFileSystem.java +++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/zip/ZipFileSystem.java @@ -49,7 +49,54 @@ public class ZipFileSystem extends AbstractFileSystem { private final File file; private final Charset charset; - private ZipFile zipFile; + private ZipFileThreadLocal zipFile = new ZipFileThreadLocal(); + + private class ZipFileCreationException extends RuntimeException { + ZipFileCreationException(Throwable cause) { + super(cause); + } + } + + private class ZipFileThreadLocal { + + private ThreadLocal isPresent = new ThreadLocal() { + @Override + protected Boolean initialValue() { + return Boolean.FALSE; + } + }; + private ThreadLocal zipFile = new ThreadLocal() { + @Override + public ZipFile initialValue() { + if (isPresent.get()) { + throw new IllegalStateException("Creating an initial value but we already have one"); + } + try { + isPresent.set(Boolean.TRUE); + return createZipFile(ZipFileSystem.this.file); + } catch (FileSystemException fse) { + throw new ZipFileCreationException(fse); + } + } + }; + + public ZipFile getFile() throws FileSystemException { + try { + return zipFile.get(); + } catch (ZipFileCreationException e) { + throw new FileSystemException(e); + } + } + + public void closeFile() throws IOException { + if (isPresent.get()) { + ZipFile file = zipFile.get(); + file.close(); + zipFile.remove(); + isPresent.set(Boolean.FALSE); + } + } + } /** * Cache doesn't need to be synchronized since it is read-only. @@ -71,12 +118,6 @@ public ZipFileSystem(final AbstractFileName rootFileName, final FileObject paren // Make a local copy of the file file = parentLayer.getFileSystem().replicateFile(parentLayer, Selectors.SELECT_SELF); this.charset = ZipFileSystemConfigBuilder.getInstance().getCharset(fileSystemOptions); - - // Open the Zip file - if (!file.exists()) { - // Don't need to do anything - zipFile = null; - } } /** @@ -111,12 +152,9 @@ protected ZipFileObject createZipFileObject(final AbstractFileName name, final Z @Override protected void doCloseCommunicationLink() { - // Release the zip file + // Release the zip files try { - if (zipFile != null) { - zipFile.close(); - zipFile = null; - } + zipFile.closeFile(); } catch (final IOException e) { // getLogger().warn("vfs.provider.zip/close-zip-file.error :" + file, e); VfsLog.warn(getLogger(), LOG, "vfs.provider.zip/close-zip-file.error :" + file, e); @@ -136,11 +174,7 @@ protected FileObject getFileFromCache(final FileName name) { } protected ZipFile getZipFile() throws FileSystemException { - if (zipFile == null && this.file.exists()) { - this.zipFile = createZipFile(this.file); - } - - return zipFile; + return zipFile.getFile(); } @Override diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/impl/VfsClassLoaderTests.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/impl/VfsClassLoaderTests.java index 533ba6763f..5f9bc530af 100644 --- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/impl/VfsClassLoaderTests.java +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/impl/VfsClassLoaderTests.java @@ -19,23 +19,11 @@ import static org.apache.commons.vfs2.VfsTestUtils.getTestDirectoryFile; import java.io.File; -import java.io.PrintWriter; import java.net.URL; import java.net.URLConnection; -import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import org.apache.commons.io.output.StringBuilderWriter; import org.apache.commons.vfs2.AbstractProviderTestCase; import org.apache.commons.vfs2.Capability; import org.apache.commons.vfs2.FileObject; @@ -215,93 +203,6 @@ public void testSealing() throws Exception { verifyPackage(pack, true); } - @Test - public void testThreadSafety() throws Exception { - final int THREADS = 40; - final BlockingQueue workQueue = new ArrayBlockingQueue<>(THREADS * 2); - final List exceptions = new ArrayList<>(); - final Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread t, Throwable e) { - synchronized (exceptions) { - exceptions.add(e); - } - } - }; - final ThreadFactory factory = new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - Thread thread = new Thread(r, "VfsClassLoaderTests.testThreadSafety"); - thread.setUncaughtExceptionHandler(handler); - return thread; - } - }; - final Queue rejections = new LinkedList<>(); - final RejectedExecutionHandler rejectionHandler = new RejectedExecutionHandler() { - @Override - public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { - synchronized (rejections) { - rejections.add(r); - } - } - }; - final ThreadPoolExecutor executor = new ThreadPoolExecutor(THREADS, THREADS, 0, TimeUnit.SECONDS, workQueue, factory, rejectionHandler); - executor.prestartAllCoreThreads(); - for (int i = 0; i < THREADS; i++) { - final VFSClassLoader loader = createClassLoader(); - workQueue.put(new VfsClassLoaderTests.LoadClass(loader)); - } - while (!workQueue.isEmpty()) { - Thread.sleep(10); - } - while (!rejections.isEmpty() && executor.getActiveCount() > 0) { - final List rejected = new ArrayList<>(); - synchronized(rejections) { - rejected.addAll(rejections); - rejections.clear(); - } - workQueue.addAll(rejected); - } - executor.shutdown(); - executor.awaitTermination(30, TimeUnit.SECONDS); - assertEquals(THREADS, executor.getCompletedTaskCount()); - if (!exceptions.isEmpty()) { - StringBuilder exceptionMsg = new StringBuilder(); - StringBuilderWriter writer = new StringBuilderWriter(exceptionMsg); - PrintWriter pWriter = new PrintWriter(writer); - for (Throwable t : exceptions) { - pWriter.write(t.getMessage()); - pWriter.write('\n'); - t.printStackTrace(pWriter); - pWriter.write('\n'); - } - pWriter.flush(); - assertTrue(exceptions.size() + " threads failed: " + exceptionMsg, exceptions.isEmpty()); - } - } - - private class LoadClass implements Runnable { - private final VFSClassLoader loader; - public LoadClass(VFSClassLoader loader) { - this.loader = loader; - } - - @Override - public void run() { - try { - final Class testClass = loader.findClass("code.ClassToLoad"); - final Package pack = testClass.getPackage(); - assertEquals("code", pack.getName()); - verifyPackage(pack, false); - - final Object testObject = testClass.newInstance(); - assertEquals("**PRIVATE**", testObject.toString()); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } - } - /** * Verify the package loaded with class loader. */ diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/impl/VfsThreadedClassLoaderTests.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/impl/VfsThreadedClassLoaderTests.java new file mode 100644 index 0000000000..c797579035 --- /dev/null +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/impl/VfsThreadedClassLoaderTests.java @@ -0,0 +1,280 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.vfs2.impl; + +import org.apache.commons.io.output.StringBuilderWriter; +import org.apache.commons.vfs2.AbstractProviderTestCase; +import org.apache.commons.vfs2.Capability; +import org.apache.commons.vfs2.FileSystemException; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * VfsClassLoader test cases. + */ +public class VfsThreadedClassLoaderTests extends AbstractProviderTestCase { + + final static Map TEST_FILES = Arrays.asList(new Object[][] { + {"read-tests/empty.txt",0L}, + {"read-tests/file1.txt",20L}, + {"read-tests/dir1/file1.txt",12L}, + {"read-tests/dir1/file2.txt",12L}, + {"read-tests/dir1/subdir2/file1.txt",12L}, + {"read-tests/dir1/subdir2/file2.txt",12L}, + {"read-tests/dir1/subdir2/file3.txt",12L}, + {"read-tests/dir1/subdir3/file1.txt",12L}, + {"read-tests/dir1/subdir3/file2.txt",12L}, + {"read-tests/dir1/subdir3/file3.txt",12L}, + {"read-tests/dir1/file3.txt",12L}, + {"read-tests/dir1/subdir4.jar/file1.txt",12L}, + {"read-tests/dir1/subdir4.jar/file2.txt",12L}, + {"read-tests/dir1/subdir4.jar/file3.txt",12L}, + {"read-tests/dir1/subdir1/file1.txt",12L}, + {"read-tests/dir1/subdir1/file2.txt",12L}, + {"read-tests/dir1/subdir1/file3.txt",12L}, + //{"read-tests/largefile.txt", 3221225472L}, + {"read-tests/file space.txt",20L} + }).stream().collect(Collectors.toMap(o -> (String)o[0], o -> (Long)o[1])); + + /** + * Creates the classloader to use when testing. + */ + private VFSClassLoader createClassLoader() throws FileSystemException { + return new VFSClassLoader(getBaseFolder(), getManager()); + } + + /** + * Returns the capabilities required by the tests of this test case. + */ + @Override + protected Capability[] getRequiredCapabilities() { + return new Capability[] { Capability.READ_CONTENT, Capability.URI }; + } + + @Test + public void testThreadSafety() throws Exception { + // note THREADS must be an even number + final int THREADS = 20; + final BlockingQueue workQueue = new ArrayBlockingQueue<>(THREADS * 2); + final List exceptions = new ArrayList<>(); + final Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread t, Throwable e) { + synchronized (exceptions) { + exceptions.add(e); + } + } + }; + final ThreadFactory factory = new ThreadFactory() { + private int count = 0; + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r, "VfsClassLoaderTests.testThreadSafety #" + count++); + thread.setUncaughtExceptionHandler(handler); + return thread; + } + }; + final Queue rejections = new LinkedList<>(); + final RejectedExecutionHandler rejectionHandler = new RejectedExecutionHandler() { + @Override + public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { + synchronized (rejections) { + rejections.add(r); + } + } + }; + final ThreadPoolExecutor executor = new ThreadPoolExecutor(THREADS, THREADS, 0, TimeUnit.SECONDS, workQueue, factory, rejectionHandler); + executor.prestartAllCoreThreads(); + VFSClassLoader resourceLoader = createClassLoader(); + final CyclicBarrier barrier = new CyclicBarrier(THREADS); + for (int i = 0; i < THREADS/2; i++) { + final VFSClassLoader loader = createClassLoader(); + workQueue.put(new VfsThreadedClassLoaderTests.LoadClass(barrier, loader)); + workQueue.put(new VfsThreadedClassLoaderTests.ReadResource(barrier, resourceLoader)); + } + while (!workQueue.isEmpty()) { + Thread.sleep(10); + } + while (!rejections.isEmpty() && executor.getActiveCount() > 0) { + final List rejected = new ArrayList<>(); + synchronized(rejections) { + rejected.addAll(rejections); + rejections.clear(); + } + workQueue.addAll(rejected); + } + executor.shutdown(); + executor.awaitTermination(60, TimeUnit.SECONDS); + assertEquals(THREADS, executor.getCompletedTaskCount()); + if (!exceptions.isEmpty()) { + StringBuilder exceptionMsg = new StringBuilder(); + StringBuilderWriter writer = new StringBuilderWriter(exceptionMsg); + PrintWriter pWriter = new PrintWriter(writer); + for (Throwable t : exceptions) { + pWriter.write(String.valueOf(t.getMessage())); + pWriter.write('\n'); + t.printStackTrace(pWriter); + pWriter.write('\n'); + } + pWriter.flush(); + assertTrue(exceptions.size() + " threads failed: " + exceptionMsg, exceptions.isEmpty()); + } + } + + private class LoadClass implements Runnable { + private final VFSClassLoader loader; + private final CyclicBarrier barrier; + + public LoadClass(CyclicBarrier barrier, VFSClassLoader loader) { + this.barrier = barrier; + this.loader = loader; + } + + @Override + public void run() { + try { + barrier.await(); + final Class testClass = loader.findClass("code.ClassToLoad"); + final Package pack = testClass.getPackage(); + assertEquals("code", pack.getName()); + verifyPackage(pack, false); + + final Object testObject = testClass.newInstance(); + assertEquals("**PRIVATE**", testObject.toString()); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } + } + } + + private class ReadResource implements Runnable { + private final VFSClassLoader loader; + private final CyclicBarrier barrier; + + public ReadResource(CyclicBarrier barrier, VFSClassLoader loader) { + this.barrier = barrier; + this.loader = loader; + } + + @Override + public void run() { + try { + barrier.await(); + List> files = new ArrayList<>(TEST_FILES.entrySet()); + Collections.shuffle(files); + for (int i = 0; i < 10; i++) { + for (Map.Entry file : files) { + testFindResource(file.getKey(), file.getValue()); + testGetResource(file.getKey(), file.getValue()); + testResourceAsStream(file.getKey(), file.getValue()); + } + } + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } + } + + private void testResourceAsStream(String file, long size) { + try { + try (InputStream stream = loader.getResourceAsStream(file)) { + if (stream == null) { + loader.getResourceAsStream(file); + } + readStream(file, stream, size); + } + } catch (Exception e) { + throw new RuntimeException("Failed to read " + file + " on thread " + Thread.currentThread(), e); + } + } + private void testGetResource(String file, long size) { + try { + URL url = loader.getResource(file); + try (InputStream stream = url.openStream()) { + readStream(file, stream, size); + } + } catch (Exception e) { + throw new RuntimeException("Failed to read " + file + " on thread " + Thread.currentThread(), e); + } + } + private void testFindResource(String file, long size) { + try { + URL url = loader.findResource(file); + try (InputStream stream = url.openStream()) { + readStream(file, stream, size); + } + } catch (Exception e) { + throw new RuntimeException("Failed to read " + file + " on thread " + Thread.currentThread(), e); + } + } + private void readStream(String file, InputStream stream, long size) throws IOException { + long length = 0; + byte[] bytes = new byte[1024]; + int readBytes = stream.read(bytes); + while (readBytes >= 0) { + length += readBytes; + readBytes = stream.read(bytes); + } + assertEquals("Incorrect length for " + file + " on thread " + Thread.currentThread(), length, size); + } + } + + /** + * Verify the package loaded with class loader. + */ + private void verifyPackage(final Package pack, final boolean sealed) { + if (getBaseFolder().getFileSystem().hasCapability(Capability.MANIFEST_ATTRIBUTES)) { + assertEquals("ImplTitle", pack.getImplementationTitle()); + assertEquals("ImplVendor", pack.getImplementationVendor()); + assertEquals("1.1", pack.getImplementationVersion()); + assertEquals("SpecTitle", pack.getSpecificationTitle()); + assertEquals("SpecVendor", pack.getSpecificationVendor()); + assertEquals("1.0", pack.getSpecificationVersion()); + assertEquals(sealed, pack.isSealed()); + } else { + assertNull(pack.getImplementationTitle()); + assertNull(pack.getImplementationVendor()); + assertNull(pack.getImplementationVersion()); + assertNull(pack.getSpecificationTitle()); + assertNull(pack.getSpecificationVendor()); + assertNull(pack.getSpecificationVersion()); + assertFalse(pack.isSealed()); + } + } + +} diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/jar/JarProviderTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/jar/JarProviderTestCase.java index 64defb9213..60c353ded6 100644 --- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/jar/JarProviderTestCase.java +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/jar/JarProviderTestCase.java @@ -27,6 +27,8 @@ import org.apache.commons.vfs2.impl.DefaultFileSystemManager; import junit.framework.Test; +import org.apache.commons.vfs2.impl.VfsThreadedClassLoaderTests; +import org.apache.commons.vfs2.provider.tar.TarProviderTestCase; /** * Tests for the Jar file system. @@ -43,7 +45,9 @@ static FileObject getTestJar(final FileSystemManager manager, final String name) * Creates the test suite for the jar file system. */ public static Test suite() throws Exception { - return new ProviderTestSuite(new JarProviderTestCase(), true); + final ProviderTestSuite testSuite = new ProviderTestSuite(new JarProviderTestCase(), true); + testSuite.addTests(VfsThreadedClassLoaderTests.class); + return testSuite; } /** diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/local/LocalProviderTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/local/LocalProviderTestCase.java index 538a16ea3e..732dcbfae8 100644 --- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/local/LocalProviderTestCase.java +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/local/LocalProviderTestCase.java @@ -26,6 +26,7 @@ import org.apache.commons.vfs2.ProviderTestSuite; import junit.framework.Test; +import org.apache.commons.vfs2.impl.VfsThreadedClassLoaderTests; /** * Tests for the local file system. @@ -48,6 +49,8 @@ public static Test suite() throws Exception { testSuite.addTests(WindowsFileNameTests.class); } + testSuite.addTests(VfsThreadedClassLoaderTests.class); + return testSuite; } diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/ram/RamProviderTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/ram/RamProviderTestCase.java index e19b2b9ef9..c9f24b5254 100644 --- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/ram/RamProviderTestCase.java +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/ram/RamProviderTestCase.java @@ -25,6 +25,7 @@ import org.apache.commons.vfs2.FileSystemManager; import org.apache.commons.vfs2.ProviderTestSuite; import org.apache.commons.vfs2.impl.DefaultFileSystemManager; +import org.apache.commons.vfs2.impl.VfsThreadedClassLoaderTests; import org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider; import junit.framework.Test; @@ -43,7 +44,9 @@ public class RamProviderTestCase extends AbstractProviderTestConfig { * Creates the test suite for the ram file system. */ public static Test suite() throws Exception { - return new ProviderTestSuite(new RamProviderTestCase()); + final ProviderTestSuite testSuite = new ProviderTestSuite(new RamProviderTestCase()); + testSuite.addTests(VfsThreadedClassLoaderTests.class); + return testSuite; } /** diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/tar/TarProviderTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/tar/TarProviderTestCase.java index de229430fc..74671d38dc 100644 --- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/tar/TarProviderTestCase.java +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/tar/TarProviderTestCase.java @@ -27,6 +27,7 @@ import org.apache.commons.vfs2.impl.DefaultFileSystemManager; import junit.framework.Test; +import org.apache.commons.vfs2.impl.VfsThreadedClassLoaderTests; /** * Tests for the Tar file system. @@ -37,7 +38,9 @@ public class TarProviderTestCase extends AbstractProviderTestConfig { * Creates the test suite for the tar file system. */ public static Test suite() throws Exception { - return new ProviderTestSuite(new TarProviderTestCase(), true); + final ProviderTestSuite testSuite = new ProviderTestSuite(new TarProviderTestCase(), true); + testSuite.addTests(VfsThreadedClassLoaderTests.class); + return testSuite; } /** diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/zip/ZipProviderTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/zip/ZipProviderTestCase.java index 45d7fb0497..b1589b2ff5 100644 --- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/zip/ZipProviderTestCase.java +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/zip/ZipProviderTestCase.java @@ -27,6 +27,7 @@ import org.apache.commons.vfs2.impl.DefaultFileSystemManager; import junit.framework.Test; +import org.apache.commons.vfs2.impl.VfsThreadedClassLoaderTests; /** * Tests for the Zip file system. @@ -37,7 +38,9 @@ public class ZipProviderTestCase extends AbstractProviderTestConfig { * Creates the test suite for the ZIP file system. */ public static Test suite() throws Exception { - return new ProviderTestSuite(new ZipProviderTestCase(), true); + final ProviderTestSuite testSuite = new ProviderTestSuite(new ZipProviderTestCase(), true); + testSuite.addTests(VfsThreadedClassLoaderTests.class); + return testSuite; } /** diff --git a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/zip/ZipProviderWithCharsetTestCase.java b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/zip/ZipProviderWithCharsetTestCase.java index bc5714a2ff..f3711b5bc8 100644 --- a/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/zip/ZipProviderWithCharsetTestCase.java +++ b/commons-vfs2/src/test/java/org/apache/commons/vfs2/provider/zip/ZipProviderWithCharsetTestCase.java @@ -28,6 +28,7 @@ import org.apache.commons.vfs2.FileSystemOptions; import org.apache.commons.vfs2.ProviderTestSuite; import org.apache.commons.vfs2.impl.DefaultFileSystemManager; +import org.apache.commons.vfs2.impl.VfsThreadedClassLoaderTests; import org.junit.jupiter.api.Assertions; import junit.framework.Test; @@ -41,7 +42,9 @@ public class ZipProviderWithCharsetTestCase extends AbstractProviderTestConfig { * Creates the test suite for the ZIP file system. */ public static Test suite() throws Exception { - return new ProviderTestSuite(new ZipProviderWithCharsetTestCase(), true); + final ProviderTestSuite testSuite = new ProviderTestSuite(new ZipProviderWithCharsetTestCase(), true); + testSuite.addTests(VfsThreadedClassLoaderTests.class); + return testSuite; } /**