diff options
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/vfs/ScopeEscapableFileSystemTest.java | 818 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystemTest.java | 12 |
2 files changed, 5 insertions, 825 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/ScopeEscapableFileSystemTest.java b/src/test/java/com/google/devtools/build/lib/vfs/ScopeEscapableFileSystemTest.java deleted file mode 100644 index 9fd98b0f6d..0000000000 --- a/src/test/java/com/google/devtools/build/lib/vfs/ScopeEscapableFileSystemTest.java +++ /dev/null @@ -1,818 +0,0 @@ -// Copyright 2014 The Bazel Authors. All rights reserved. -// -// 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.devtools.build.lib.vfs; - -import static com.google.common.truth.Truth.assertThat; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.junit.Assert.fail; - -import com.google.common.collect.ImmutableList; -import com.google.devtools.build.lib.util.Preconditions; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Collection; -import org.junit.Before; -import org.junit.Test; - -/** - * Generic tests for any file system that implements {@link ScopeEscapableFileSystem}, - * i.e. any file system that supports symlinks that escape its scope. - * - * Each suitable file system test should inherit from this class, thereby obtaining - * all the tests. - */ -public abstract class ScopeEscapableFileSystemTest extends SymlinkAwareFileSystemTest { - - /** - * Trivial FileSystem implementation that can record the last path passed to each method - * and read/write to a unified "state" variable (which can then be checked by tests) for - * each data type this class manipulates. - * - * The default implementation of each method throws an exception. Each test case should - * selectively override the methods it expects to be invoked. - */ - private static class TestDelegator extends FileSystem { - protected Path lastPath; - protected boolean booleanState; - protected long longState; - protected Object objectState; - - public void setState(boolean state) { booleanState = state; } - public void setState(long state) { longState = state; } - public void setState(Object state) { objectState = state; } - - public boolean booleanState() { return booleanState; } - public long longState() { return longState; } - public Object objectState() { return objectState; } - - public PathFragment lastPath() { - Path ans = lastPath; - // Clear this out to protect against accidental matches when testing the same path multiple - // consecutive times. - lastPath = null; - return ans != null ? ans.asFragment() : null; - } - - @Override - public boolean supportsModifications(Path path) { - return true; - } - - @Override - public boolean supportsSymbolicLinksNatively(Path path) { - return true; - } - - @Override - public boolean supportsHardLinksNatively(Path path) { - return true; - } - - @Override - public boolean isFilePathCaseSensitive() { - return true; - } - - private static RuntimeException re() { - return new RuntimeException("This method should not be called in this context"); - } - - @Override protected boolean isReadable(Path path) { throw re(); } - @Override protected boolean isWritable(Path path) { throw re(); } - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { throw re(); } - @Override protected boolean isFile(Path path, boolean followSymlinks) { throw re(); } - @Override protected boolean isSpecialFile(Path path, boolean followSymlinks) { throw re(); } - @Override protected boolean isExecutable(Path path) { throw re(); } - @Override protected boolean exists(Path path, boolean followSymlinks) {throw re(); } - @Override protected boolean isSymbolicLink(Path path) { throw re(); } - @Override protected boolean createDirectory(Path path) { throw re(); } - @Override protected boolean delete(Path path) { throw re(); } - - @Override protected long getFileSize(Path path, boolean followSymlinks) { throw re(); } - @Override protected long getLastModifiedTime(Path path, boolean followSymlinks) { throw re(); } - - @Override protected void setWritable(Path path, boolean writable) { throw re(); } - @Override protected void setExecutable(Path path, boolean executable) { throw re(); } - @Override protected void setReadable(Path path, boolean readable) { throw re(); } - @Override protected void setLastModifiedTime(Path path, long newTime) { throw re(); } - @Override protected void renameTo(Path sourcePath, Path targetPath) { throw re(); } - @Override protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) { - throw re(); - } - @Override protected void createFSDependentHardLink(Path linkPath, Path originalPath) { - throw re(); - } - @Override protected PathFragment readSymbolicLink(Path path) { throw re(); } - @Override protected InputStream getInputStream(Path path) { throw re(); } - @Override protected Collection<Path> getDirectoryEntries(Path path) { throw re(); } - @Override protected OutputStream getOutputStream(Path path, boolean append) { throw re(); } - @Override - protected FileStatus statIfFound(Path path, boolean followSymlinks) throws IOException { - throw re(); - } - } - - protected static final PathFragment SCOPE_ROOT = PathFragment.create("/fs/root"); - - private Path fileLink; - private PathFragment fileLinkTarget; - private Path dirLink; - private PathFragment dirLinkTarget; - - @Before - public final void createLinks() throws Exception { - Preconditions.checkState( - testFS instanceof ScopeEscapableFileSystem, "Not ScopeEscapable: %s", testFS); - ((ScopeEscapableFileSystem) testFS).enableScopeChecking(false); - for (int i = 1; i <= SCOPE_ROOT.segmentCount(); i++) { - testFS.getPath(SCOPE_ROOT.subFragment(0, i)).createDirectory(); - } - - fileLink = testFS.getPath(SCOPE_ROOT.getRelative("link")); - fileLinkTarget = PathFragment.create("/should/be/delegated/fileLinkTarget"); - testFS.createSymbolicLink(fileLink, fileLinkTarget); - - dirLink = testFS.getPath(SCOPE_ROOT.getRelative("dirlink")); - dirLinkTarget = PathFragment.create("/should/be/delegated/dirLinkTarget"); - testFS.createSymbolicLink(dirLink, dirLinkTarget); - } - - /** - * Returns the file system supplied by {@link #getFreshFileSystem}, cast to - * a {@link ScopeEscapableFileSystem}. Also enables scope checking within - * the file system (which we keep disabled for inherited tests that aren't - * intended to test scope boundaries). - */ - private ScopeEscapableFileSystem scopedFS() { - ScopeEscapableFileSystem fs = (ScopeEscapableFileSystem) testFS; - fs.enableScopeChecking(true); - return fs; - } - - // Checks that the semi-resolved path passed to the delegator matches the expected value. - private void checkPath(TestDelegator delegator, PathFragment expectedDelegatedPath) { - assertThat(delegator.lastPath()).isEqualTo(expectedDelegatedPath); - } - - // Asserts that the condition is false and checks that the expected path was delegated. - private void assertFalseWithPathCheck(boolean result, TestDelegator delegator, - PathFragment expectedDelegatedPath) { - assertThat(result).isFalse(); - checkPath(delegator, expectedDelegatedPath); - } - - // Asserts that the condition is true and checks that the expected path was delegated. - private void assertTrueWithPathCheck(boolean result, TestDelegator delegator, - PathFragment expectedDelegatedPath) { - assertThat(result).isTrue(); - checkPath(delegator, expectedDelegatedPath); - } - - ///////////////////////////////////////////////////////////////////////////// - // Tests: - ///////////////////////////////////////////////////////////////////////////// - - @Test - public void testIsReadableCallOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected boolean isReadable(Path path) { - lastPath = path; - return booleanState(); - } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - assertFalseWithPathCheck(fileLink.isReadable(), delegator, fileLinkTarget); - assertFalseWithPathCheck(dirLink.getRelative("a").isReadable(), delegator, - dirLinkTarget.getRelative("a")); - - delegator.setState(true); - assertTrueWithPathCheck(fileLink.isReadable(), delegator, fileLinkTarget); - assertTrueWithPathCheck(dirLink.getRelative("a").isReadable(), delegator, - dirLinkTarget.getRelative("a")); - } - - @Test - public void testIsWritableCallOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected boolean isWritable(Path path) { - lastPath = path; - return booleanState(); - } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - assertFalseWithPathCheck(fileLink.isWritable(), delegator, fileLinkTarget); - assertFalseWithPathCheck(dirLink.getRelative("a").isWritable(), delegator, - dirLinkTarget.getRelative("a")); - - delegator.setState(true); - assertTrueWithPathCheck(fileLink.isWritable(), delegator, fileLinkTarget); - assertTrueWithPathCheck(dirLink.getRelative("a").isWritable(), delegator, - dirLinkTarget.getRelative("a")); - } - - @Test - public void testisExecutableCallOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected boolean isExecutable(Path path) { - lastPath = path; - return booleanState(); - } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - assertFalseWithPathCheck(fileLink.isExecutable(), delegator, fileLinkTarget); - assertFalseWithPathCheck(dirLink.getRelative("a").isExecutable(), delegator, - dirLinkTarget.getRelative("a")); - - delegator.setState(true); - assertTrueWithPathCheck(fileLink.isExecutable(), delegator, fileLinkTarget); - assertTrueWithPathCheck(dirLink.getRelative("a").isExecutable(), delegator, - dirLinkTarget.getRelative("a")); - } - - @Test - public void testIsDirectoryCallOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { - lastPath = path; - return booleanState(); - } - @Override protected boolean exists(Path path, boolean followSymlinks) { return true; } - @Override protected long getLastModifiedTime(Path path, boolean followSymlinks) { return 0; } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - assertFalseWithPathCheck(fileLink.isDirectory(), delegator, fileLinkTarget); - assertFalseWithPathCheck(dirLink.getRelative("a").isDirectory(), delegator, - dirLinkTarget.getRelative("a")); - - delegator.setState(true); - assertTrueWithPathCheck(fileLink.isDirectory(), delegator, fileLinkTarget); - assertTrueWithPathCheck(dirLink.getRelative("a").isDirectory(), delegator, - dirLinkTarget.getRelative("a")); - } - - @Test - public void testIsFileCallOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected boolean isFile(Path path, boolean followSymlinks) { - lastPath = path; - return booleanState(); - } - @Override protected boolean exists(Path path, boolean followSymlinks) { return true; } - @Override protected long getLastModifiedTime(Path path, boolean followSymlinks) { return 0; } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - assertFalseWithPathCheck(fileLink.isFile(), delegator, fileLinkTarget); - assertFalseWithPathCheck(dirLink.getRelative("a").isFile(), delegator, - dirLinkTarget.getRelative("a")); - - delegator.setState(true); - assertTrueWithPathCheck(fileLink.isFile(), delegator, fileLinkTarget); - assertTrueWithPathCheck(dirLink.getRelative("a").isFile(), delegator, - dirLinkTarget.getRelative("a")); - } - - @Test - public void testIsSymbolicLinkCallOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected boolean isSymbolicLink(Path path) { - lastPath = path; - return booleanState(); - } - @Override protected boolean exists(Path path, boolean followSymlinks) { return true; } - @Override protected long getLastModifiedTime(Path path, boolean followSymlinks) { return 0; } - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { return true; } - }; - scopedFS().setDelegator(delegator); - - // We shouldn't follow final-segment links, so they should never invoke the delegator. - delegator.setState(false); - assertThat(fileLink.isSymbolicLink()).isTrue(); - assertThat(delegator.lastPath()).isNull(); - - assertFalseWithPathCheck(dirLink.getRelative("a").isSymbolicLink(), delegator, - dirLinkTarget.getRelative("a")); - - delegator.setState(true); - assertTrueWithPathCheck(dirLink.getRelative("a").isSymbolicLink(), delegator, - dirLinkTarget.getRelative("a")); - } - - /** - * Returns a test delegator that reflects info passed to Path.exists() calls. - */ - private TestDelegator newExistsDelegator() { - return new TestDelegator() { - @Override protected boolean exists(Path path, boolean followSymlinks) { - lastPath = path; - return booleanState(); - } - @Override protected FileStatus stat(Path path, boolean followSymlinks) throws IOException { - if (!exists(path, followSymlinks)) { - throw new IOException("Expected exception on stat of non-existent file"); - } - return super.stat(path, followSymlinks); - } - @Override protected long getLastModifiedTime(Path path, boolean followSymlinks) { return 0; } - }; - } - - @Test - public void testExistsCallOnEscapingSymlink() throws Exception { - TestDelegator delegator = newExistsDelegator(); - scopedFS().setDelegator(delegator); - - delegator.setState(false); - assertFalseWithPathCheck(fileLink.exists(), delegator, fileLinkTarget); - assertFalseWithPathCheck(dirLink.getRelative("a").exists(), delegator, - dirLinkTarget.getRelative("a")); - - delegator.setState(true); - assertTrueWithPathCheck(fileLink.exists(), delegator, fileLinkTarget); - assertTrueWithPathCheck(dirLink.getRelative("a").exists(), delegator, - dirLinkTarget.getRelative("a")); - } - - @Test - public void testCreateDirectoryCallOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected boolean createDirectory(Path path) { - lastPath = path; - return booleanState(); - } - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { return true; } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - assertFalseWithPathCheck(dirLink.getRelative("a").createDirectory(), delegator, - dirLinkTarget.getRelative("a")); - - delegator.setState(true); - assertTrueWithPathCheck(dirLink.getRelative("a").createDirectory(), delegator, - dirLinkTarget.getRelative("a")); - } - - @Test - public void testDeleteCallOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected boolean delete(Path path) { - lastPath = path; - return booleanState(); - } - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { return true; } - @Override protected long getLastModifiedTime(Path path, boolean followSymlinks) { return 0; } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - assertThat(fileLink.delete()).isTrue(); - assertThat(delegator.lastPath()).isNull(); // Deleting a link shouldn't require delegation. - assertFalseWithPathCheck(dirLink.getRelative("a").delete(), delegator, - dirLinkTarget.getRelative("a")); - - delegator.setState(true); - assertTrueWithPathCheck(dirLink.getRelative("a").delete(), delegator, - dirLinkTarget.getRelative("a")); - } - - @Test - public void testCallGetFileSizeOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected long getFileSize(Path path, boolean followSymlinks) { - lastPath = path; - return longState(); - } - @Override protected long getLastModifiedTime(Path path, boolean followSymlinks) { return 0; } - }; - scopedFS().setDelegator(delegator); - - final int state1 = 10; - delegator.setState(state1); - assertThat(fileLink.getFileSize()).isEqualTo(state1); - checkPath(delegator, fileLinkTarget); - assertThat(dirLink.getRelative("a").getFileSize()).isEqualTo(state1); - checkPath(delegator, dirLinkTarget.getRelative("a")); - - final int state2 = 10; - delegator.setState(state2); - assertThat(fileLink.getFileSize()).isEqualTo(state2); - checkPath(delegator, fileLinkTarget); - assertThat(dirLink.getRelative("a").getFileSize()).isEqualTo(state2); - checkPath(delegator, dirLinkTarget.getRelative("a")); - } - - @Test - public void testCallGetLastModifiedTimeOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected long getLastModifiedTime(Path path, boolean followSymlinks) { - lastPath = path; - return longState(); - } - }; - scopedFS().setDelegator(delegator); - - final int state1 = 10; - delegator.setState(state1); - assertThat(fileLink.getLastModifiedTime()).isEqualTo(state1); - checkPath(delegator, fileLinkTarget); - assertThat(dirLink.getRelative("a").getLastModifiedTime()).isEqualTo(state1); - checkPath(delegator, dirLinkTarget.getRelative("a")); - - final int state2 = 10; - delegator.setState(state2); - assertThat(fileLink.getLastModifiedTime()).isEqualTo(state2); - checkPath(delegator, fileLinkTarget); - assertThat(dirLink.getRelative("a").getLastModifiedTime()).isEqualTo(state2); - checkPath(delegator, dirLinkTarget.getRelative("a")); - } - - @Test - public void testCallSetReadableOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected void setReadable(Path path, boolean readable) { - lastPath = path; - setState(readable); - } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - fileLink.setReadable(true); - assertThat(delegator.booleanState()).isTrue(); - checkPath(delegator, fileLinkTarget); - fileLink.setReadable(false); - assertThat(delegator.booleanState()).isFalse(); - checkPath(delegator, fileLinkTarget); - - delegator.setState(false); - dirLink.getRelative("a").setReadable(true); - assertThat(delegator.booleanState()).isTrue(); - checkPath(delegator, dirLinkTarget.getRelative("a")); - dirLink.getRelative("a").setReadable(false); - assertThat(delegator.booleanState()).isFalse(); - checkPath(delegator, dirLinkTarget.getRelative("a")); - } - - @Test - public void testCallSetWritableOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected void setWritable(Path path, boolean writable) { - lastPath = path; - setState(writable); - } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - fileLink.setWritable(true); - assertThat(delegator.booleanState()).isTrue(); - checkPath(delegator, fileLinkTarget); - fileLink.setWritable(false); - assertThat(delegator.booleanState()).isFalse(); - checkPath(delegator, fileLinkTarget); - - delegator.setState(false); - dirLink.getRelative("a").setWritable(true); - assertThat(delegator.booleanState()).isTrue(); - checkPath(delegator, dirLinkTarget.getRelative("a")); - dirLink.getRelative("a").setWritable(false); - assertThat(delegator.booleanState()).isFalse(); - checkPath(delegator, dirLinkTarget.getRelative("a")); - } - - @Test - public void testCallSetExecutableOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected void setReadable(Path path, boolean readable) { - lastPath = path; - setState(readable); - } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(false); - fileLink.setReadable(true); - assertThat(delegator.booleanState()).isTrue(); - checkPath(delegator, fileLinkTarget); - fileLink.setReadable(false); - assertThat(delegator.booleanState()).isFalse(); - checkPath(delegator, fileLinkTarget); - - delegator.setState(false); - dirLink.getRelative("a").setReadable(true); - assertThat(delegator.booleanState()).isTrue(); - checkPath(delegator, dirLinkTarget.getRelative("a")); - dirLink.getRelative("a").setReadable(false); - assertThat(delegator.booleanState()).isFalse(); - checkPath(delegator, dirLinkTarget.getRelative("a")); - } - - @Test - public void testCallSetLastModifiedTimeOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected void setLastModifiedTime(Path path, long newTime) { - lastPath = path; - setState(newTime); - } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(0); - fileLink.setLastModifiedTime(10); - assertThat(delegator.longState()).isEqualTo(10); - checkPath(delegator, fileLinkTarget); - fileLink.setLastModifiedTime(15); - assertThat(delegator.longState()).isEqualTo(15); - checkPath(delegator, fileLinkTarget); - - dirLink.getRelative("a").setLastModifiedTime(20); - assertThat(delegator.longState()).isEqualTo(20); - checkPath(delegator, dirLinkTarget.getRelative("a")); - dirLink.getRelative("a").setLastModifiedTime(25); - assertThat(delegator.longState()).isEqualTo(25); - checkPath(delegator, dirLinkTarget.getRelative("a")); - } - - @Test - public void testCallRenameToOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected void renameTo(Path sourcePath, Path targetPath) { - lastPath = sourcePath; - setState(targetPath); - } - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { return true; } - }; - scopedFS().setDelegator(delegator); - - // Renaming a link should work fine. - delegator.setState(null); - fileLink.renameTo(testFS.getPath(SCOPE_ROOT).getRelative("newname")); - assertThat(delegator.lastPath()).isNull(); // Renaming a link shouldn't require delegation. - assertThat(delegator.objectState()).isNull(); - - // Renaming an out-of-scope path to an in-scope path should fail due to filesystem mismatch - // errors. - Path newPath = testFS.getPath(SCOPE_ROOT.getRelative("blah")); - try { - dirLink.getRelative("a").renameTo(newPath); - fail("This is an attempt at a cross-filesystem renaming, which should fail"); - } catch (IOException e) { - // Expected. - } - - // Renaming an out-of-scope path to another out-of-scope path can be valid. - newPath = dirLink.getRelative("b"); - dirLink.getRelative("a").renameTo(newPath); - assertThat(delegator.lastPath()).isEqualTo(dirLinkTarget.getRelative("a")); - assertThat(((Path) delegator.objectState()).asFragment()) - .isEqualTo(dirLinkTarget.getRelative("b")); - } - - @Test - public void testCallCreateSymbolicLinkOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected void createSymbolicLink(Path linkPath, PathFragment targetFragment) { - lastPath = linkPath; - setState(targetFragment); - } - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { return true; } - }; - scopedFS().setDelegator(delegator); - - PathFragment newLinkTarget = PathFragment.create("/something/else"); - dirLink.getRelative("a").createSymbolicLink(newLinkTarget); - assertThat(delegator.lastPath()).isEqualTo(dirLinkTarget.getRelative("a")); - assertThat(delegator.objectState()).isSameAs(newLinkTarget); - } - - @Test - public void testCallReadSymbolicLinkOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected PathFragment readSymbolicLink(Path path) { - lastPath = path; - return (PathFragment) objectState; - } - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { return true; } - }; - scopedFS().setDelegator(delegator); - - // Since we're not following the link, this shouldn't invoke delegation. - delegator.setState(PathFragment.create("whatever")); - PathFragment p = fileLink.readSymbolicLink(); - assertThat(delegator.lastPath()).isNull(); - assertThat(p).isNotSameAs(delegator.objectState()); - - // This should. - p = dirLink.getRelative("a").readSymbolicLink(); - assertThat(delegator.lastPath()).isEqualTo(dirLinkTarget.getRelative("a")); - assertThat(p).isSameAs(delegator.objectState()); - } - - @Test - public void testCallGetInputStreamOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected InputStream getInputStream(Path path) { - lastPath = path; - return (InputStream) objectState; - } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(new ByteArrayInputStream("blah".getBytes(UTF_8))); - InputStream is = fileLink.getInputStream(); - assertThat(delegator.lastPath()).isEqualTo(fileLinkTarget); - assertThat(is).isSameAs(delegator.objectState()); - - delegator.setState(new ByteArrayInputStream("blah2".getBytes(UTF_8))); - is = dirLink.getInputStream(); - assertThat(delegator.lastPath()).isEqualTo(dirLinkTarget); - assertThat(is).isSameAs(delegator.objectState()); - } - - @Test - public void testCallGetOutputStreamOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected OutputStream getOutputStream(Path path, boolean append) { - lastPath = path; - return (OutputStream) objectState; - } - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { return true; } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(new ByteArrayOutputStream()); - OutputStream os = fileLink.getOutputStream(); - assertThat(delegator.lastPath()).isEqualTo(fileLinkTarget); - assertThat(os).isSameAs(delegator.objectState()); - - delegator.setState(new ByteArrayOutputStream()); - os = dirLink.getOutputStream(); - assertThat(delegator.lastPath()).isEqualTo(dirLinkTarget); - assertThat(os).isSameAs(delegator.objectState()); - } - - @Test - public void testCallGetDirectoryEntriesOnEscapingSymlink() throws Exception { - TestDelegator delegator = new TestDelegator() { - @Override protected Collection<Path> getDirectoryEntries(Path path) { - lastPath = path; - return ImmutableList.of((Path) objectState); - } - @Override protected boolean isDirectory(Path path, boolean followSymlinks) { return true; } - }; - scopedFS().setDelegator(delegator); - - delegator.setState(testFS.getPath("/anything")); - Collection<Path> entries = dirLink.getDirectoryEntries(); - assertThat(delegator.lastPath()).isEqualTo(dirLinkTarget); - assertThat(entries).hasSize(1); - assertThat(entries.iterator().next()).isSameAs(delegator.objectState()); - } - - /** - * Asserts that "link" is an in-scope link that doesn't result in an out-of-FS - * delegation. If link is relative, its path is relative to SCOPE_ROOT. - * - * Note that we don't actually check that the canonicalized target path matches - * the link's target value. Such testing should be covered by - * SymlinkAwareFileSystemTest. - */ - private void assertInScopeLink(String link, String target, TestDelegator d) throws IOException { - Path l = testFS.getPath(SCOPE_ROOT.getRelative(link)); - testFS.createSymbolicLink(l, PathFragment.create(target)); - l.exists(); - assertThat(d.lastPath()).isNull(); - } - - /** - * Asserts that "link" is an out-of-scope link and that the re-delegated path - * matches expectedPath. If link is relative, its path is relative to SCOPE_ROOT. - */ - private void assertOutOfScopeLink(String link, String target, String expectedPath, - TestDelegator d) throws IOException { - Path l = testFS.getPath(SCOPE_ROOT.getRelative(link)); - testFS.createSymbolicLink(l, PathFragment.create(target)); - l.exists(); - assertThat(d.lastPath().getPathString()).isEqualTo(expectedPath); - } - - /** - * Returns the scope root with the final n segments chopped off (or a 0-segment path - * if n > SCOPE_ROOT.segmentCount()). - */ - private String chopScopeRoot(int n) { - return SCOPE_ROOT - .subFragment(0, n > SCOPE_ROOT.segmentCount() ? 0 : SCOPE_ROOT.segmentCount() - n) - .getPathString(); - } - - /** - * Tests that absolute symlinks with ".." and "." segments are delegated to - * the expected paths. - */ - @Test - public void testAbsoluteSymlinksWithParentReferences() throws Exception { - TestDelegator d = newExistsDelegator(); - scopedFS().setDelegator(d); - testFS.createDirectory(testFS.getPath(SCOPE_ROOT.getRelative("dir"))); - String scopeRoot = SCOPE_ROOT.getPathString(); - String scopeBase = SCOPE_ROOT.getBaseName(); - - // Symlinks that should never escape our scope. - assertInScopeLink("ilink1", scopeRoot, d); - assertInScopeLink("ilink2", scopeRoot + "/target", d); - assertInScopeLink("ilink3", scopeRoot + "/dir/../target", d); - assertInScopeLink("ilink4", scopeRoot + "/dir/../dir/dir2/../target", d); - assertInScopeLink("ilink5", scopeRoot + "/./dir/.././target", d); - assertInScopeLink("ilink6", scopeRoot + "/../" + scopeBase + "/target", d); - assertInScopeLink("ilink7", "/some/path/../.." + scopeRoot + "/target", d); - - // Symlinks that should escape our scope. - assertOutOfScopeLink("olink1", scopeRoot + "/../target", chopScopeRoot(1) + "/target", d); - assertOutOfScopeLink("olink2", "/some/other/path", "/some/other/path", d); - assertOutOfScopeLink("olink3", scopeRoot + "/../target", chopScopeRoot(1) + "/target", d); - assertOutOfScopeLink("olink4", chopScopeRoot(1) + "/target", chopScopeRoot(1) + "/target", d); - assertOutOfScopeLink("olink5", scopeRoot + "/../../../../target", "/target", d); - - // In-scope symlink that's not the final segment in a query. - Path iDirLink = testFS.getPath(SCOPE_ROOT.getRelative("ilinkdir")); - testFS.createSymbolicLink(iDirLink, SCOPE_ROOT.getRelative("dir")); - iDirLink.getRelative("file").exists(); - assertThat(d.lastPath()).isNull(); - - // Out-of-scope symlink that's not the final segment in a query. - Path oDirLink = testFS.getPath(SCOPE_ROOT.getRelative("olinkdir")); - testFS.createSymbolicLink(oDirLink, PathFragment.create("/some/other/dir")); - oDirLink.getRelative("file").exists(); - assertThat(d.lastPath().getPathString()).isEqualTo("/some/other/dir/file"); - } - - /** - * Tests that relative symlinks with ".." and "." segments are delegated to - * the expected paths. - */ - @Test - public void testRelativeSymlinksWithParentReferences() throws Exception { - TestDelegator d = newExistsDelegator(); - scopedFS().setDelegator(d); - testFS.createDirectory(testFS.getPath(SCOPE_ROOT.getRelative("dir"))); - testFS.createDirectory(testFS.getPath(SCOPE_ROOT.getRelative("dir/dir2"))); - testFS.createDirectory(testFS.getPath(SCOPE_ROOT.getRelative("dir/dir2/dir3"))); - String scopeRoot = SCOPE_ROOT.getPathString(); - String scopeBase = SCOPE_ROOT.getBaseName(); - - // Symlinks that should never escape our scope. - assertInScopeLink("ilink1", "target", d); - assertInScopeLink("ilink2", "dir/../otherdir/target", d); - assertInScopeLink("dir/ilink3", "../target", d); - assertInScopeLink("dir/dir2/ilink4", "../../target", d); - assertInScopeLink("dir/dir2/ilink5", ".././../dir/./target", d); - assertInScopeLink("dir/dir2/ilink6", "../dir2/../../dir/dir2/dir3/../../../target", d); - - // Symlinks that should escape our scope. - assertOutOfScopeLink("olink1", "../target", chopScopeRoot(1) + "/target", d); - assertOutOfScopeLink("dir/olink2", "../../target", chopScopeRoot(1) + "/target", d); - assertOutOfScopeLink("olink3", "../" + scopeBase + "/target", scopeRoot + "/target", d); - assertOutOfScopeLink("dir/dir2/olink5", "../../../target", chopScopeRoot(1) + "/target", d); - assertOutOfScopeLink("dir/dir2/olink6", "../dir2/../../dir/dir2/../../../target", - chopScopeRoot(1) + "/target", d); - assertOutOfScopeLink("dir/olink7", "../../../target", chopScopeRoot(2) + "target", d); - assertOutOfScopeLink("olink8", "../../../../../target", "/target", d); - - // In-scope symlink that's not the final segment in a query. - Path iDirLink = testFS.getPath(SCOPE_ROOT.getRelative("dir/dir2/ilinkdir")); - testFS.createSymbolicLink(iDirLink, PathFragment.create("../../dir")); - iDirLink.getRelative("file").exists(); - assertThat(d.lastPath()).isNull(); - - // Out-of-scope symlink that's not the final segment in a query. - Path oDirLink = testFS.getPath(SCOPE_ROOT.getRelative("dir/dir2/olinkdir")); - testFS.createSymbolicLink(oDirLink, PathFragment.create("../../../other/dir")); - oDirLink.getRelative("file").exists(); - assertThat(d.lastPath().getPathString()).isEqualTo(chopScopeRoot(1) + "/other/dir/file"); - } -} diff --git a/src/test/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystemTest.java b/src/test/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystemTest.java index 355d96d089..2ebe0a5dd3 100644 --- a/src/test/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystemTest.java +++ b/src/test/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystemTest.java @@ -21,7 +21,7 @@ import com.google.devtools.build.lib.testutil.TestThread; import com.google.devtools.build.lib.vfs.FileSystem; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; -import com.google.devtools.build.lib.vfs.ScopeEscapableFileSystemTest; +import com.google.devtools.build.lib.vfs.SymlinkAwareFileSystemTest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -34,17 +34,15 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** - * Tests for {@link InMemoryFileSystem}. Note that most tests are inherited - * from {@link ScopeEscapableFileSystemTest} and ancestors. This specific - * file focuses only on concurrency tests. - * + * Tests for {@link InMemoryFileSystem}. Note that most tests are inherited from {@link + * SymlinkAwareFileSystemTest} and ancestors. This specific file focuses only on concurrency tests. */ @RunWith(JUnit4.class) -public class InMemoryFileSystemTest extends ScopeEscapableFileSystemTest { +public class InMemoryFileSystemTest extends SymlinkAwareFileSystemTest { @Override public FileSystem getFreshFileSystem() { - return new InMemoryFileSystem(BlazeClock.instance(), SCOPE_ROOT); + return new InMemoryFileSystem(BlazeClock.instance()); } @Override |