blob: c7592197e1e4a95eb02bf7b928c405b1d278a4a2 [file] [log] [blame]
tomlu4a2f2c52017-12-12 12:32:22 -08001// Copyright 2017 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.vfs;
15
16import static com.google.common.truth.Truth.assertThat;
17
18import com.google.common.testing.EqualsTester;
aehligc801c392017-12-19 07:12:25 -080019import com.google.devtools.build.lib.testutil.MoreAsserts;
tomlua729b9b2018-02-08 15:32:00 -080020import com.google.devtools.build.lib.vfs.WindowsOsPathPolicy.ShortPathResolver;
tomlu4a2f2c52017-12-12 12:32:22 -080021import java.util.HashMap;
22import java.util.Map;
23import org.junit.Test;
24import org.junit.runner.RunWith;
25import org.junit.runners.JUnit4;
26
tomlua729b9b2018-02-08 15:32:00 -080027/** Tests windows-specific parts of {@link Path} */
tomlu4a2f2c52017-12-12 12:32:22 -080028@RunWith(JUnit4.class)
tomlua729b9b2018-02-08 15:32:00 -080029public class WindowsPathTest extends PathAbstractTest {
tomlu4a2f2c52017-12-12 12:32:22 -080030
31 private static final class MockShortPathResolver implements ShortPathResolver {
32 // Full path to resolved child mapping.
33 private Map<String, String> resolutions = new HashMap<>();
34
35 @Override
36 public String resolveShortPath(String path) {
37 String[] segments = path.split("[\\\\/]+");
38 String result = "";
39 for (int i = 0; i < segments.length; ) {
40 String segment = segments[i];
41 String queryString = (result + segment).toLowerCase();
42 segment = resolutions.getOrDefault(queryString, segment);
43 result = result + segment;
44 ++i;
45 if (i != segments.length) {
46 result += "/";
47 }
48 }
49 return result;
50 }
51 }
52
tomlu4a2f2c52017-12-12 12:32:22 -080053 @Test
54 public void testEqualsAndHashcodeWindows() {
55 new EqualsTester()
tomlu4a2f2c52017-12-12 12:32:22 -080056 .addEqualityGroup(create("/a/b"), create("/A/B"))
57 .addEqualityGroup(create("c:/a/b"), create("C:\\A\\B"))
tomlua729b9b2018-02-08 15:32:00 -080058 .addEqualityGroup(create("C:/something/else"))
tomlu4a2f2c52017-12-12 12:32:22 -080059 .testEquals();
60 }
61
62 @Test
63 public void testCaseIsPreserved() {
tomlua729b9b2018-02-08 15:32:00 -080064 assertThat(create("C:/a/B").getPathString()).isEqualTo("C:/a/B");
tomlu4a2f2c52017-12-12 12:32:22 -080065 }
66
67 @Test
68 public void testNormalizeWindows() {
69 assertThat(create("C:/")).isEqualTo(create("C:/"));
70 assertThat(create("c:/")).isEqualTo(create("C:/"));
71 assertThat(create("c:\\")).isEqualTo(create("C:/"));
72 assertThat(create("c:\\foo\\..\\bar\\")).isEqualTo(create("C:/bar"));
73 }
74
75 @Test
76 public void testStartsWithWindows() {
77 assertThat(create("C:/").startsWith(create("C:/"))).isTrue();
78 assertThat(create("C:/foo").startsWith(create("C:/"))).isTrue();
79 assertThat(create("C:/foo").startsWith(create("D:/"))).isFalse();
80
81 // Case insensitivity test
82 assertThat(create("C:/foo/bar").startsWith(create("C:/FOO"))).isTrue();
83 }
84
85 @Test
86 public void testGetParentDirectoryWindows() {
87 assertThat(create("C:/foo").getParentDirectory()).isEqualTo(create("C:/"));
88 assertThat(create("C:/").getParentDirectory()).isNull();
tomlua729b9b2018-02-08 15:32:00 -080089 assertThat(create("/").getParentDirectory()).isNull();
tomlu4a2f2c52017-12-12 12:32:22 -080090 }
91
92 @Test
tomlua729b9b2018-02-08 15:32:00 -080093 public void testParentOfRootIsRootWindows() {
94 assertThat(create("C:/..")).isEqualTo(create("C:/"));
95 assertThat(create("C:/../../../../../..")).isEqualTo(create("C:/"));
96 assertThat(create("C:/../../../foo")).isEqualTo(create("C:/foo"));
tomlu4a2f2c52017-12-12 12:32:22 -080097 }
98
99 @Test
100 public void testRelativeToWindows() {
tomlua729b9b2018-02-08 15:32:00 -0800101 assertThat(create("C:/foo").relativeTo(create("C:/")).getPathString()).isEqualTo("foo");
tomlu4a2f2c52017-12-12 12:32:22 -0800102 // Case insensitivity test
tomlua729b9b2018-02-08 15:32:00 -0800103 assertThat(create("C:/foo/bar").relativeTo(create("C:/FOO")).getPathString()).isEqualTo("bar");
aehligc801c392017-12-19 07:12:25 -0800104 MoreAsserts.assertThrows(
105 IllegalArgumentException.class, () -> create("D:/foo").relativeTo(create("C:/")));
106 }
107
108 @Test
tomlu4a2f2c52017-12-12 12:32:22 -0800109 public void testResolvesShortenedPaths() {
tomlua729b9b2018-02-08 15:32:00 -0800110 MockShortPathResolver shortPathResolver = new MockShortPathResolver();
111 WindowsOsPathPolicy osPathPolicy = new WindowsOsPathPolicy(shortPathResolver);
tomlu4a2f2c52017-12-12 12:32:22 -0800112 shortPathResolver.resolutions.put("d:/progra~1", "program files");
113 shortPathResolver.resolutions.put("d:/program files/micros~1", "microsoft something");
114 shortPathResolver.resolutions.put(
115 "d:/program files/microsoft something/foo/~bar~1", "~bar_hello");
116
117 // Assert normal shortpath resolution.
tomlua729b9b2018-02-08 15:32:00 -0800118 assertThat(normalize(osPathPolicy, "d:/progra~1/micros~1/foo/~bar~1/baz"))
tomlu4a2f2c52017-12-12 12:32:22 -0800119 .isEqualTo("D:/program files/microsoft something/foo/~bar_hello/baz");
tomlua729b9b2018-02-08 15:32:00 -0800120 assertThat(normalize(osPathPolicy, "d:/progra~1/micros~1/foo/will~1.exi/bar"))
tomlu4a2f2c52017-12-12 12:32:22 -0800121 .isEqualTo("D:/program files/microsoft something/foo/will~1.exi/bar");
122
tomlua729b9b2018-02-08 15:32:00 -0800123 assertThat(normalize(osPathPolicy, "d:/progra~1/micros~1"))
124 .isEqualTo("D:/program files/microsoft something");
tomlu4a2f2c52017-12-12 12:32:22 -0800125
126 // Pretend that a path we already failed to resolve once came into existence.
127 shortPathResolver.resolutions.put(
128 "d:/program files/microsoft something/foo/will~1.exi", "will.exist");
129
130 // Assert that this time we can resolve the previously non-existent path.
tomlu4a2f2c52017-12-12 12:32:22 -0800131 // The path string has an upper-case drive letter because that's how path printing works.
tomlua729b9b2018-02-08 15:32:00 -0800132 assertThat(normalize(osPathPolicy, "d:/progra~1/micros~1/foo/will~1.exi/bar"))
tomlu4a2f2c52017-12-12 12:32:22 -0800133 .isEqualTo("D:/program files/microsoft something/foo/will.exist/bar");
134
tomlua729b9b2018-02-08 15:32:00 -0800135 // Check needsToNormalized
136 assertThat(osPathPolicy.needsToNormalize("d:/progra~1/micros~1/foo/will~1.exi/bar"))
137 .isEqualTo(WindowsOsPathPolicy.NEEDS_SHORT_PATH_NORMALIZATION);
138 assertThat(osPathPolicy.needsToNormalize("will~1.exi"))
139 .isEqualTo(WindowsOsPathPolicy.NEEDS_SHORT_PATH_NORMALIZATION);
140 assertThat(osPathPolicy.needsToNormalize("d:/no-normalization"))
141 .isEqualTo(WindowsOsPathPolicy.NORMALIZED); // Sanity check
142 }
143
144 private static String normalize(OsPathPolicy osPathPolicy, String str) {
145 return osPathPolicy.normalize(str, osPathPolicy.needsToNormalize(str));
tomlu4a2f2c52017-12-12 12:32:22 -0800146 }
tomlu4a2f2c52017-12-12 12:32:22 -0800147}