aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools/build/lib/vfs
diff options
context:
space:
mode:
authorGravatar tomlu <tomlu@google.com>2017-10-20 17:27:11 +0200
committerGravatar Dmitry Lomov <dslomov@google.com>2017-10-23 17:15:55 +0200
commit0b2f94d38f2d6cf27a47ce2e66e2423ccef770ce (patch)
treee49dfca6af8a51d6da8c824770546b886f1732d0 /src/test/java/com/google/devtools/build/lib/vfs
parent1a4f4264492a0b37a4132d629342aa961fa1c6b0 (diff)
Remove scope escaping capability from InMemoryFileSystem.
Nobody sets a delegate anymore, meaning it should be fine to crash hard if we try to resolve a file outside scope. The CL was created by inlining ScopeEscapableFileSystem into InMemoryFileSystem, making it impossible to return an outOfScope file status (instead throwing an exception), then trivially fixing the code. PiperOrigin-RevId: 172886769
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/vfs')
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/ScopeEscapableFileSystemTest.java818
-rw-r--r--src/test/java/com/google/devtools/build/lib/vfs/inmemoryfs/InMemoryFileSystemTest.java12
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