diff options
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/vfs')
4 files changed, 561 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/vfs/LocalPathAbstractTest.java b/src/test/java/com/google/devtools/build/lib/vfs/LocalPathAbstractTest.java new file mode 100644 index 0000000000..93869521ad --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/vfs/LocalPathAbstractTest.java @@ -0,0 +1,180 @@ +// Copyright 2017 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 com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows; +import static java.util.stream.Collectors.toList; + +import com.google.common.collect.Lists; +import com.google.common.testing.EqualsTester; +import com.google.devtools.build.lib.vfs.LocalPath.OsPathPolicy; +import java.util.Collections; +import java.util.List; +import org.junit.Before; +import org.junit.Test; + +/** Tests for {@link LocalPath}. */ +public abstract class LocalPathAbstractTest { + + private OsPathPolicy os; + + @Before + public void setup() { + os = getFilePathOs(); + } + + @Test + public void testEqualsAndHashCode() { + new EqualsTester() + .addEqualityGroup( + create("../relative/path"), create("..").getRelative("relative").getRelative("path")) + .addEqualityGroup(create("something/else")) + .addEqualityGroup(create(""), LocalPath.EMPTY) + .testEquals(); + } + + @Test + public void testRelativeTo() { + assertThat(create("").relativeTo(create("")).getPathString()).isEmpty(); + assertThat(create("foo").relativeTo(create("foo")).getPathString()).isEmpty(); + assertThat(create("foo/bar/baz").relativeTo(create("foo")).getPathString()) + .isEqualTo("bar/baz"); + assertThat(create("foo/bar/baz").relativeTo(create("foo/bar")).getPathString()) + .isEqualTo("baz"); + assertThat(create("foo").relativeTo(create("")).getPathString()).isEqualTo("foo"); + + // Cannot relativize non-ancestors + assertThrows(IllegalArgumentException.class, () -> create("foo/bar").relativeTo(create("fo"))); + + // Make sure partial directory matches aren't reported + assertThrows( + IllegalArgumentException.class, () -> create("foo/bar").relativeTo(create("foo/ba"))); + } + + @Test + public void testGetRelative() { + assertThat(create("a").getRelative("b").getPathString()).isEqualTo("a/b"); + assertThat(create("a/b").getRelative("c/d").getPathString()).isEqualTo("a/b/c/d"); + assertThat(create("a").getRelative("").getPathString()).isEqualTo("a"); + assertThat(create("a/b").getRelative("../c").getPathString()).isEqualTo("a/c"); + assertThat(create("a/b").getRelative("..").getPathString()).isEqualTo("a"); + } + + @Test + public void testEmptyPathToEmptyPath() { + // compare string forms + assertThat(create("").getPathString()).isEmpty(); + // compare fragment forms + assertThat(create("")).isEqualTo(create("")); + } + + @Test + public void testSimpleNameToSimpleName() { + // compare string forms + assertThat(create("foo").getPathString()).isEqualTo("foo"); + // compare fragment forms + assertThat(create("foo")).isEqualTo(create("foo")); + } + + @Test + public void testSimplePathToSimplePath() { + // compare string forms + assertThat(create("foo/bar").getPathString()).isEqualTo("foo/bar"); + // compare fragment forms + assertThat(create("foo/bar")).isEqualTo(create("foo/bar")); + } + + @Test + public void testStripsTrailingSlash() { + // compare string forms + assertThat(create("foo/bar/").getPathString()).isEqualTo("foo/bar"); + // compare fragment forms + assertThat(create("foo/bar/")).isEqualTo(create("foo/bar")); + } + + @Test + public void testGetParentDirectory() { + LocalPath fooBarWiz = create("foo/bar/wiz"); + LocalPath fooBar = create("foo/bar"); + LocalPath foo = create("foo"); + LocalPath empty = create(""); + assertThat(fooBarWiz.getParentDirectory()).isEqualTo(fooBar); + assertThat(fooBar.getParentDirectory()).isEqualTo(foo); + assertThat(foo.getParentDirectory()).isEqualTo(empty); + assertThat(empty.getParentDirectory()).isNull(); + } + + @Test + public void testBasename() throws Exception { + assertThat(create("foo/bar").getBaseName()).isEqualTo("bar"); + assertThat(create("foo/").getBaseName()).isEqualTo("foo"); + assertThat(create("foo").getBaseName()).isEqualTo("foo"); + assertThat(create("").getBaseName()).isEmpty(); + } + + @Test + public void testStartsWith() { + // (relative path, relative prefix) => true + assertThat(create("foo/bar").startsWith(create("foo/bar"))).isTrue(); + assertThat(create("foo/bar").startsWith(create("foo"))).isTrue(); + assertThat(create("foot/bar").startsWith(create("foo"))).isFalse(); + } + + @Test + public void testNormalize() { + assertThat(create("a/b")).isEqualTo(create("a/b")); + assertThat(create("a/../../b")).isEqualTo(create("../b")); + assertThat(create("a/../..")).isEqualTo(create("..")); + assertThat(create("a/../b")).isEqualTo(create("b")); + assertThat(create("a/b/../b")).isEqualTo(create("a/b")); + } + + @Test + public void testNormalStringsDoNotAllocate() { + String normal1 = "a/b/hello.txt"; + assertThat(create(normal1).getPathString()).isSameAs(normal1); + + // Sanity check our testing strategy + String notNormal = "a/../b"; + assertThat(create(notNormal).getPathString()).isNotSameAs(notNormal); + } + + @Test + public void testComparableSortOrder() { + List<LocalPath> list = + Lists.newArrayList( + create("zzz"), + create("ZZZ"), + create("ABC"), + create("aBc"), + create("AbC"), + create("abc")); + Collections.sort(list); + List<String> result = list.stream().map(LocalPath::getPathString).collect(toList()); + + if (os.isCaseSensitive()) { + assertThat(result).containsExactly("ABC", "AbC", "ZZZ", "aBc", "abc", "zzz").inOrder(); + } else { + // Partial ordering among case-insensitive items guaranteed by Collections.sort stability + assertThat(result).containsExactly("ABC", "aBc", "AbC", "abc", "zzz", "ZZZ").inOrder(); + } + } + + protected abstract OsPathPolicy getFilePathOs(); + + protected LocalPath create(String path) { + return LocalPath.createWithOs(path, os); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/vfs/MacOsLocalPathTest.java b/src/test/java/com/google/devtools/build/lib/vfs/MacOsLocalPathTest.java new file mode 100644 index 0000000000..c99ad487ee --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/vfs/MacOsLocalPathTest.java @@ -0,0 +1,48 @@ +// Copyright 2017 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 com.google.common.testing.EqualsTester; +import com.google.devtools.build.lib.vfs.LocalPath.MacOsPathPolicy; +import com.google.devtools.build.lib.vfs.LocalPath.OsPathPolicy; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests Mac-specific parts of {@link LocalPath}. */ +@RunWith(JUnit4.class) +public class MacOsLocalPathTest extends UnixLocalPathTest { + + @Override + protected OsPathPolicy getFilePathOs() { + return new MacOsPathPolicy(); + } + + @Test + public void testMacEqualsAndHashCode() { + new EqualsTester() + .addEqualityGroup(create("a/b"), create("A/B")) + .addEqualityGroup(create("/a/b"), create("/A/B")) + .addEqualityGroup(create("something/else")) + .addEqualityGroup(create("/something/else")) + .testEquals(); + } + + @Test + public void testCaseIsPreserved() { + assertThat(create("a/B").getPathString()).isEqualTo("a/B"); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/vfs/UnixLocalPathTest.java b/src/test/java/com/google/devtools/build/lib/vfs/UnixLocalPathTest.java new file mode 100644 index 0000000000..2cdb4014ae --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/vfs/UnixLocalPathTest.java @@ -0,0 +1,169 @@ +// Copyright 2017 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 com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows; + +import com.google.common.testing.EqualsTester; +import com.google.devtools.build.lib.vfs.LocalPath.OsPathPolicy; +import com.google.devtools.build.lib.vfs.LocalPath.UnixOsPathPolicy; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests the unix implementation of {@link LocalPath}. */ +@RunWith(JUnit4.class) +public class UnixLocalPathTest extends LocalPathAbstractTest { + + @Test + public void testEqualsAndHashCodeUnix() { + new EqualsTester() + .addEqualityGroup(create("/something/else")) + .addEqualityGroup(create("/"), create("//////")) + .testEquals(); + } + + @Test + public void testRelativeToUnix() { + // Cannot relativize absolute and non-absolute + assertThat(create("c/d").getRelative("/a/b").getPathString()).isEqualTo("/a/b"); + assertThat(create("/").relativeTo(create("/")).getPathString()).isEmpty(); + assertThat(create("/foo").relativeTo(create("/foo")).getPathString()).isEmpty(); + assertThat(create("/foo/bar/baz").relativeTo(create("/foo")).getPathString()) + .isEqualTo("bar/baz"); + assertThat(create("/foo/bar/baz").relativeTo(create("/foo/bar")).getPathString()) + .isEqualTo("baz"); + assertThat(create("/foo").relativeTo(create("/")).getPathString()).isEqualTo("foo"); + assertThrows( + IllegalArgumentException.class, () -> create("/foo/bar/baz").relativeTo(create("foo"))); + assertThrows( + IllegalArgumentException.class, () -> create("/foo").relativeTo(create("/foo/bar/baz"))); + } + + @Test + public void testIsAbsoluteUnix() { + assertThat(create("/absolute/test").isAbsolute()).isTrue(); + assertThat(create("relative/test").isAbsolute()).isFalse(); + } + + @Test + public void testGetRelativeUnix() { + assertThat(create("/a").getRelative("b").getPathString()).isEqualTo("/a/b"); + assertThat(create("/").getRelative("").getPathString()).isEqualTo("/"); + assertThat(create("c/d").getRelative("/a/b").getPathString()).isEqualTo("/a/b"); + } + + @Test + public void testEmptyPathToEmptyPathUnix() { + // compare string forms + assertThat(create("/").getPathString()).isEqualTo("/"); + // compare fragment forms + assertThat(create("/")).isEqualTo(create("/")); + } + + @Test + public void testRedundantSlashes() { + // compare string forms + assertThat(create("///").getPathString()).isEqualTo("/"); + // compare fragment forms + assertThat(create("///")).isEqualTo(create("/")); + // compare string forms + assertThat(create("/foo///bar").getPathString()).isEqualTo("/foo/bar"); + // compare fragment forms + assertThat(create("/foo///bar")).isEqualTo(create("/foo/bar")); + // compare string forms + assertThat(create("////foo//bar").getPathString()).isEqualTo("/foo/bar"); + // compare fragment forms + assertThat(create("////foo//bar")).isEqualTo(create("/foo/bar")); + } + + @Test + public void testSimpleNameToSimpleNameUnix() { + // compare string forms + assertThat(create("/foo").getPathString()).isEqualTo("/foo"); + // compare fragment forms + assertThat(create("/foo")).isEqualTo(create("/foo")); + } + + @Test + public void testSimplePathToSimplePathUnix() { + // compare string forms + assertThat(create("/foo/bar").getPathString()).isEqualTo("/foo/bar"); + // compare fragment forms + assertThat(create("/foo/bar")).isEqualTo(create("/foo/bar")); + } + + @Test + public void testGetParentDirectoryUnix() { + LocalPath fooBarWizAbs = create("/foo/bar/wiz"); + LocalPath fooBarAbs = create("/foo/bar"); + LocalPath fooAbs = create("/foo"); + LocalPath rootAbs = create("/"); + assertThat(fooBarWizAbs.getParentDirectory()).isEqualTo(fooBarAbs); + assertThat(fooBarAbs.getParentDirectory()).isEqualTo(fooAbs); + assertThat(fooAbs.getParentDirectory()).isEqualTo(rootAbs); + assertThat(rootAbs.getParentDirectory()).isNull(); + } + + @Test + public void testBasenameUnix() throws Exception { + assertThat(create("/foo/bar").getBaseName()).isEqualTo("bar"); + assertThat(create("/foo/").getBaseName()).isEqualTo("foo"); + assertThat(create("/foo").getBaseName()).isEqualTo("foo"); + assertThat(create("/").getBaseName()).isEmpty(); + } + + @Test + public void testStartsWithUnix() { + LocalPath foobar = create("/foo/bar"); + LocalPath foobarRelative = create("foo/bar"); + + // (path, prefix) => true + assertThat(foobar.startsWith(foobar)).isTrue(); + assertThat(foobar.startsWith(create("/"))).isTrue(); + assertThat(foobar.startsWith(create("/foo"))).isTrue(); + assertThat(foobar.startsWith(create("/foo/"))).isTrue(); + assertThat(foobar.startsWith(create("/foo/bar/"))).isTrue(); // Includes trailing slash. + + // (prefix, path) => false + assertThat(create("/foo").startsWith(foobar)).isFalse(); + assertThat(create("/").startsWith(foobar)).isFalse(); + + // (absolute, relative) => false + assertThat(foobar.startsWith(foobarRelative)).isFalse(); + assertThat(foobarRelative.startsWith(foobar)).isFalse(); + + // relative paths start with nothing, absolute paths do not + assertThat(foobar.startsWith(create(""))).isFalse(); + + // (path, sibling) => false + assertThat(create("/foo/wiz").startsWith(foobar)).isFalse(); + assertThat(foobar.startsWith(create("/foo/wiz"))).isFalse(); + } + + @Test + public void testNormalizeUnix() { + assertThat(create("/a/b")).isEqualTo(create("/a/b")); + assertThat(create("/a/b/")).isEqualTo(create("/a/b")); + assertThat(create("/a/./b")).isEqualTo(create("/a/b")); + assertThat(create("/a/../b")).isEqualTo(create("/b")); + assertThat(create("/..")).isEqualTo(create("/..")); + } + + @Override + protected OsPathPolicy getFilePathOs() { + return new UnixOsPathPolicy(); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/vfs/WindowsLocalPathTest.java b/src/test/java/com/google/devtools/build/lib/vfs/WindowsLocalPathTest.java new file mode 100644 index 0000000000..ac5acef1f4 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/vfs/WindowsLocalPathTest.java @@ -0,0 +1,164 @@ +// Copyright 2017 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 com.google.common.testing.EqualsTester; +import com.google.devtools.build.lib.testutil.MoreAsserts; +import com.google.devtools.build.lib.vfs.LocalPath.OsPathPolicy; +import com.google.devtools.build.lib.vfs.LocalPath.WindowsOsPathPolicy; +import com.google.devtools.build.lib.vfs.LocalPath.WindowsOsPathPolicy.ShortPathResolver; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests windows-specific parts of {@link LocalPath} */ +@RunWith(JUnit4.class) +public class WindowsLocalPathTest extends LocalPathAbstractTest { + + private static final class MockShortPathResolver implements ShortPathResolver { + // Full path to resolved child mapping. + private Map<String, String> resolutions = new HashMap<>(); + + @Override + public String resolveShortPath(String path) { + String[] segments = path.split("[\\\\/]+"); + String result = ""; + for (int i = 0; i < segments.length; ) { + String segment = segments[i]; + String queryString = (result + segment).toLowerCase(); + segment = resolutions.getOrDefault(queryString, segment); + result = result + segment; + ++i; + if (i != segments.length) { + result += "/"; + } + } + return result; + } + } + + private final MockShortPathResolver shortPathResolver = new MockShortPathResolver(); + + @Override + protected OsPathPolicy getFilePathOs() { + return new WindowsOsPathPolicy(shortPathResolver); + } + + @Test + public void testEqualsAndHashcodeWindows() { + new EqualsTester() + .addEqualityGroup(create("a/b"), create("A/B")) + .addEqualityGroup(create("/a/b"), create("/A/B")) + .addEqualityGroup(create("c:/a/b"), create("C:\\A\\B")) + .addEqualityGroup(create("something/else")) + .testEquals(); + } + + @Test + public void testCaseIsPreserved() { + assertThat(create("a/B").getPathString()).isEqualTo("a/B"); + } + + @Test + public void testNormalizeWindows() { + assertThat(create("C:/")).isEqualTo(create("C:/")); + assertThat(create("c:/")).isEqualTo(create("C:/")); + assertThat(create("c:\\")).isEqualTo(create("C:/")); + assertThat(create("c:\\foo\\..\\bar\\")).isEqualTo(create("C:/bar")); + } + + @Test + public void testStartsWithWindows() { + assertThat(create("C:/").startsWith(create("C:/"))).isTrue(); + assertThat(create("C:/foo").startsWith(create("C:/"))).isTrue(); + assertThat(create("C:/foo").startsWith(create("D:/"))).isFalse(); + + // Case insensitivity test + assertThat(create("C:/foo/bar").startsWith(create("C:/FOO"))).isTrue(); + } + + @Test + public void testGetParentDirectoryWindows() { + assertThat(create("C:/foo").getParentDirectory()).isEqualTo(create("C:/")); + assertThat(create("C:/").getParentDirectory()).isNull(); + } + + @Test + public void testisAbsoluteWindows() { + assertThat(create("C:/").isAbsolute()).isTrue(); + // test that msys paths turn into absolute paths + assertThat(create("/").isAbsolute()).isTrue(); + } + + @Test + public void testRelativeToWindows() { + assertThat(create("C:/foo").relativeTo(create("C:/"))).isEqualTo(create("foo")); + // Case insensitivity test + assertThat(create("C:/foo/bar").relativeTo(create("C:/FOO"))).isEqualTo(create("bar")); + MoreAsserts.assertThrows( + IllegalArgumentException.class, () -> create("D:/foo").relativeTo(create("C:/"))); + } + + @Test + public void testAbsoluteUnixPathIsRelativeToWindowsUnixRoot() { + assertThat(create("/").getPathString()).isEqualTo("C:/fake/msys"); + assertThat(create("/foo/bar").getPathString()).isEqualTo("C:/fake/msys/foo/bar"); + assertThat(create("/foo/bar").getPathString()).isEqualTo("C:/fake/msys/foo/bar"); + } + + @Test + public void testAbsoluteUnixPathReferringToDriveIsRecognized() { + assertThat(create("/c/foo").getPathString()).isEqualTo("C:/foo"); + assertThat(create("/c/foo").getPathString()).isEqualTo("C:/foo"); + assertThat(create("/c:").getPathString()).isNotEqualTo("C:/foo"); + } + + @Test + public void testResolvesShortenedPaths() { + shortPathResolver.resolutions.put("d:/progra~1", "program files"); + shortPathResolver.resolutions.put("d:/program files/micros~1", "microsoft something"); + shortPathResolver.resolutions.put( + "d:/program files/microsoft something/foo/~bar~1", "~bar_hello"); + + // Assert normal shortpath resolution. + LocalPath normal = create("d:/progra~1/micros~1/foo/~bar~1/baz"); + // The path string has an upper-case drive letter because that's how path printing works. + assertThat(normal.getPathString()) + .isEqualTo("D:/program files/microsoft something/foo/~bar_hello/baz"); + LocalPath notYetExistent = create("d:/progra~1/micros~1/foo/will~1.exi/bar"); + // The path string has an upper-case drive letter because that's how path printing works. + assertThat(notYetExistent.getPathString()) + .isEqualTo("D:/program files/microsoft something/foo/will~1.exi/bar"); + + LocalPath msRoot = create("d:/progra~1/micros~1"); + assertThat(msRoot.getPathString()).isEqualTo("D:/program files/microsoft something"); + + // Pretend that a path we already failed to resolve once came into existence. + shortPathResolver.resolutions.put( + "d:/program files/microsoft something/foo/will~1.exi", "will.exist"); + + // Assert that this time we can resolve the previously non-existent path. + LocalPath nowExists = create("d:/progra~1/micros~1/foo/will~1.exi/bar"); + // The path string has an upper-case drive letter because that's how path printing works. + assertThat(nowExists.getPathString()) + .isEqualTo("D:/program files/microsoft something/foo/will.exist/bar"); + + // Assert relative paths that look like short paths are untouched + assertThat(create("progra~1").getPathString()).isEqualTo("progra~1"); + } +} |