diff options
Diffstat (limited to 'jimfs/src/test/java/com/google/common/jimfs/ClassLoaderTest.java')
-rw-r--r-- | jimfs/src/test/java/com/google/common/jimfs/ClassLoaderTest.java | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/jimfs/src/test/java/com/google/common/jimfs/ClassLoaderTest.java b/jimfs/src/test/java/com/google/common/jimfs/ClassLoaderTest.java new file mode 100644 index 0000000..671a566 --- /dev/null +++ b/jimfs/src/test/java/com/google/common/jimfs/ClassLoaderTest.java @@ -0,0 +1,120 @@ +/* + * Copyright 2015 Google Inc. + * + * 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 com.google.common.jimfs; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URLClassLoader; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.spi.FileSystemProvider; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests behavior when user code loads Jimfs in a separate class loader from the system class loader + * (which is what {@link FileSystemProvider#installedProviders()} uses to load {@link + * FileSystemProvider}s as services from the classpath). + * + * @author Colin Decker + */ +@RunWith(JUnit4.class) +public class ClassLoaderTest { + + @Test + public void separateClassLoader() throws Exception { + ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); + ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); + + ClassLoader loader = MoreObjects.firstNonNull(contextLoader, systemLoader); + + if (loader instanceof URLClassLoader) { + // Anything we can do if it isn't a URLClassLoader? + URLClassLoader urlLoader = (URLClassLoader) loader; + + ClassLoader separateLoader = + new URLClassLoader( + urlLoader.getURLs(), systemLoader.getParent()); // either null or the boostrap loader + + Thread.currentThread().setContextClassLoader(separateLoader); + try { + Class<?> thisClass = separateLoader.loadClass(getClass().getName()); + Method createFileSystem = thisClass.getDeclaredMethod("createFileSystem"); + + // First, the call to Jimfs.newFileSystem in createFileSystem needs to succeed + Object fs = createFileSystem.invoke(null); + + // Next, some sanity checks: + + // The file system is a JimfsFileSystem + assertEquals("com.google.common.jimfs.JimfsFileSystem", fs.getClass().getName()); + + // But it is not seen as an instance of JimfsFileSystem here because it was loaded by a + // different ClassLoader + assertFalse(fs instanceof JimfsFileSystem); + + // But it should be an instance of FileSystem regardless, which is the important thing. + assertTrue(fs instanceof FileSystem); + + // And normal file operations should work on it despite its provenance from a different + // ClassLoader + writeAndRead((FileSystem) fs, "bar.txt", "blah blah"); + + // And for the heck of it, test the contents of the file that was created in + // createFileSystem too + assertEquals( + "blah", Files.readAllLines(((FileSystem) fs).getPath("foo.txt"), UTF_8).get(0)); + } finally { + Thread.currentThread().setContextClassLoader(contextLoader); + } + } + } + + /** + * This method is really just testing that {@code Jimfs.newFileSystem()} succeeds. Without special + * handling, when the system class loader loads our {@code FileSystemProvider} implementation as a + * service and this code (the user code) is loaded in a separate class loader, the system-loaded + * provider won't see the instance of {@code Configuration} we give it as being an instance of the + * {@code Configuration} it's expecting (they're completely separate classes) and creation of the + * file system will fail. + */ + public static FileSystem createFileSystem() throws IOException { + FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); + + // Just some random operations to verify that basic things work on the created file system. + writeAndRead(fs, "foo.txt", "blah"); + + return fs; + } + + private static void writeAndRead(FileSystem fs, String path, String text) throws IOException { + Path p = fs.getPath(path); + Files.write(p, ImmutableList.of(text), UTF_8); + List<String> lines = Files.readAllLines(p, UTF_8); + assertEquals(text, lines.get(0)); + } +} |