blob: 773daee80f7f34b8c6a8415fb1cd97998266ec25 [file] [log] [blame]
Laszlo Csomor4fca9882016-09-02 09:48:42 +00001// Copyright 2016 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.
14
15package com.google.devtools.build.lib.windows;
16
17import static com.google.common.truth.Truth.assertThat;
Laszlo Csomor4fca9882016-09-02 09:48:42 +000018import static org.junit.Assert.fail;
19
Laszlo Csomor4fca9882016-09-02 09:48:42 +000020import com.google.common.collect.ImmutableMap;
21import com.google.devtools.build.lib.testutil.TestSpec;
22import com.google.devtools.build.lib.util.OS;
Laszlo Csomor94d90582016-09-08 15:08:00 +000023import com.google.devtools.build.lib.vfs.WindowsFileSystem;
Laszlo Csomor4fca9882016-09-02 09:48:42 +000024import com.google.devtools.build.lib.windows.util.WindowsTestUtil;
25import java.io.File;
Laszlo Csomor4fca9882016-09-02 09:48:42 +000026import java.io.IOException;
Laszlo Csomor94d90582016-09-08 15:08:00 +000027import java.nio.file.Files;
Laszlo Csomor4fca9882016-09-02 09:48:42 +000028import java.util.Arrays;
29import java.util.HashMap;
Laszlo Csomor4fca9882016-09-02 09:48:42 +000030import java.util.Map;
Laszlo Csomor4fca9882016-09-02 09:48:42 +000031import org.junit.After;
32import org.junit.Before;
33import org.junit.Test;
34import org.junit.runner.RunWith;
35import org.junit.runners.JUnit4;
36
37/** Unit tests for {@link WindowsFileOperations}. */
38@RunWith(JUnit4.class)
39@TestSpec(localOnly = true, supportedOs = OS.WINDOWS)
40public class WindowsFileOperationsTest {
41
42 private String scratchRoot;
Laszlo Csomorb65d7542016-09-07 10:22:06 +000043 private WindowsTestUtil testUtil;
Laszlo Csomor4fca9882016-09-02 09:48:42 +000044
45 @Before
46 public void loadJni() throws Exception {
Laszlo Csomora2da3112016-09-07 08:06:15 +000047 WindowsTestUtil.loadJni();
Laszlo Csomor4fca9882016-09-02 09:48:42 +000048 scratchRoot = new File(System.getenv("TEST_TMPDIR")).getAbsolutePath() + "/x";
Laszlo Csomorb65d7542016-09-07 10:22:06 +000049 testUtil = new WindowsTestUtil(scratchRoot);
Laszlo Csomora2da3112016-09-07 08:06:15 +000050 cleanupScratchDir();
Laszlo Csomor4fca9882016-09-02 09:48:42 +000051 }
52
53 @After
54 public void cleanupScratchDir() throws Exception {
Laszlo Csomorb65d7542016-09-07 10:22:06 +000055 testUtil.deleteAllUnder("");
Laszlo Csomor4fca9882016-09-02 09:48:42 +000056 }
57
58 @Test
59 public void testMockJunctionCreation() throws Exception {
Laszlo Csomorb65d7542016-09-07 10:22:06 +000060 String root = testUtil.scratchDir("dir").getParent().toString();
61 testUtil.scratchFile("dir/file.txt", "hello");
62 testUtil.createJunctions(ImmutableMap.of("junc", "dir"));
Laszlo Csomor4fca9882016-09-02 09:48:42 +000063 String[] children = new File(root + "/junc").list();
64 assertThat(children).isNotNull();
65 assertThat(children).hasLength(1);
66 assertThat(Arrays.asList(children)).containsExactly("file.txt");
67 }
68
69 @Test
70 public void testIsJunction() throws Exception {
71 final Map<String, String> junctions = new HashMap<>();
72 junctions.put("shrtpath/a", "shrttrgt");
73 junctions.put("shrtpath/b", "longtargetpath");
74 junctions.put("shrtpath/c", "longta~1");
75 junctions.put("longlinkpath/a", "shrttrgt");
76 junctions.put("longlinkpath/b", "longtargetpath");
77 junctions.put("longlinkpath/c", "longta~1");
78 junctions.put("abbrev~1/a", "shrttrgt");
79 junctions.put("abbrev~1/b", "longtargetpath");
80 junctions.put("abbrev~1/c", "longta~1");
81
Laszlo Csomorb65d7542016-09-07 10:22:06 +000082 String root = testUtil.scratchDir("shrtpath").getParent().toAbsolutePath().toString();
83 testUtil.scratchDir("longlinkpath");
84 testUtil.scratchDir("abbreviated");
85 testUtil.scratchDir("control/a");
86 testUtil.scratchDir("control/b");
87 testUtil.scratchDir("control/c");
Laszlo Csomor4fca9882016-09-02 09:48:42 +000088
Laszlo Csomorb65d7542016-09-07 10:22:06 +000089 testUtil.scratchFile("shrttrgt/file1.txt", "hello");
90 testUtil.scratchFile("longtargetpath/file2.txt", "hello");
Laszlo Csomor4fca9882016-09-02 09:48:42 +000091
Laszlo Csomorb65d7542016-09-07 10:22:06 +000092 testUtil.createJunctions(junctions);
Laszlo Csomor4fca9882016-09-02 09:48:42 +000093
94 assertThat(WindowsFileOperations.isJunction(root + "/shrtpath/a")).isTrue();
95 assertThat(WindowsFileOperations.isJunction(root + "/shrtpath/b")).isTrue();
96 assertThat(WindowsFileOperations.isJunction(root + "/shrtpath/c")).isTrue();
97 assertThat(WindowsFileOperations.isJunction(root + "/longlinkpath/a")).isTrue();
98 assertThat(WindowsFileOperations.isJunction(root + "/longlinkpath/b")).isTrue();
99 assertThat(WindowsFileOperations.isJunction(root + "/longlinkpath/c")).isTrue();
100 assertThat(WindowsFileOperations.isJunction(root + "/longli~1/a")).isTrue();
101 assertThat(WindowsFileOperations.isJunction(root + "/longli~1/b")).isTrue();
102 assertThat(WindowsFileOperations.isJunction(root + "/longli~1/c")).isTrue();
103 assertThat(WindowsFileOperations.isJunction(root + "/abbreviated/a")).isTrue();
104 assertThat(WindowsFileOperations.isJunction(root + "/abbreviated/b")).isTrue();
105 assertThat(WindowsFileOperations.isJunction(root + "/abbreviated/c")).isTrue();
106 assertThat(WindowsFileOperations.isJunction(root + "/abbrev~1/a")).isTrue();
107 assertThat(WindowsFileOperations.isJunction(root + "/abbrev~1/b")).isTrue();
108 assertThat(WindowsFileOperations.isJunction(root + "/abbrev~1/c")).isTrue();
109 assertThat(WindowsFileOperations.isJunction(root + "/control/a")).isFalse();
110 assertThat(WindowsFileOperations.isJunction(root + "/control/b")).isFalse();
111 assertThat(WindowsFileOperations.isJunction(root + "/control/c")).isFalse();
112 assertThat(WindowsFileOperations.isJunction(root + "/shrttrgt/file1.txt")).isFalse();
113 assertThat(WindowsFileOperations.isJunction(root + "/longtargetpath/file2.txt")).isFalse();
114 assertThat(WindowsFileOperations.isJunction(root + "/longta~1/file2.txt")).isFalse();
115 try {
116 WindowsFileOperations.isJunction(root + "/non-existent");
117 fail("expected to throw");
118 } catch (IOException e) {
Laszlo Csomor4e33ac62016-12-06 17:24:53 +0000119 assertThat(e.getMessage()).contains("GetFileAttributes");
Laszlo Csomor4fca9882016-09-02 09:48:42 +0000120 }
121 assertThat(Arrays.asList(new File(root + "/shrtpath/a").list())).containsExactly("file1.txt");
122 assertThat(Arrays.asList(new File(root + "/shrtpath/b").list())).containsExactly("file2.txt");
123 assertThat(Arrays.asList(new File(root + "/shrtpath/c").list())).containsExactly("file2.txt");
124 assertThat(Arrays.asList(new File(root + "/longlinkpath/a").list()))
125 .containsExactly("file1.txt");
126 assertThat(Arrays.asList(new File(root + "/longlinkpath/b").list()))
127 .containsExactly("file2.txt");
128 assertThat(Arrays.asList(new File(root + "/longlinkpath/c").list()))
129 .containsExactly("file2.txt");
130 assertThat(Arrays.asList(new File(root + "/abbreviated/a").list()))
131 .containsExactly("file1.txt");
132 assertThat(Arrays.asList(new File(root + "/abbreviated/b").list()))
133 .containsExactly("file2.txt");
134 assertThat(Arrays.asList(new File(root + "/abbreviated/c").list()))
135 .containsExactly("file2.txt");
136 }
Laszlo Csomor94d90582016-09-08 15:08:00 +0000137
138 @Test
139 public void testIsJunctionIsTrueForDanglingJunction() throws Exception {
140 java.nio.file.Path helloPath = testUtil.scratchFile("target\\hello.txt", "hello");
141 testUtil.createJunctions(ImmutableMap.of("link", "target"));
142
143 File linkPath = new File(helloPath.getParent().getParent().toFile(), "link");
144 assertThat(Arrays.asList(linkPath.list())).containsExactly("hello.txt");
145 assertThat(WindowsFileOperations.isJunction(linkPath.getAbsolutePath())).isTrue();
146
147 assertThat(helloPath.toFile().delete()).isTrue();
148 assertThat(helloPath.getParent().toFile().delete()).isTrue();
149 assertThat(helloPath.getParent().toFile().exists()).isFalse();
150 assertThat(Arrays.asList(linkPath.getParentFile().list())).containsExactly("link");
151
152 assertThat(WindowsFileOperations.isJunction(linkPath.getAbsolutePath())).isTrue();
153 assertThat(
154 Files.exists(
155 linkPath.toPath(), WindowsFileSystem.symlinkOpts(/* followSymlinks */ false)))
156 .isTrue();
157 assertThat(
158 Files.exists(
159 linkPath.toPath(), WindowsFileSystem.symlinkOpts(/* followSymlinks */ true)))
160 .isFalse();
161 }
Laszlo Csomoraa1614b2016-12-15 11:16:44 +0000162
163 @Test
164 public void testIsJunctionHandlesFilesystemChangesCorrectly() throws Exception {
165 File helloFile =
166 testUtil.scratchFile("target\\helloworld.txt", "hello").toAbsolutePath().toFile();
167
168 // Assert that a file is identified as not a junction.
169 String longPath = helloFile.getAbsolutePath();
170 String shortPath = new File(helloFile.getParentFile(), "hellow~1.txt").getAbsolutePath();
171 assertThat(WindowsFileOperations.isJunction(longPath)).isFalse();
172 assertThat(WindowsFileOperations.isJunction(shortPath)).isFalse();
173
174 // Assert that after deleting the file and creating a junction with the same path, it is
175 // identified as a junction.
176 assertThat(helloFile.delete()).isTrue();
177 testUtil.createJunctions(ImmutableMap.of("target\\helloworld.txt", "target"));
178 assertThat(WindowsFileOperations.isJunction(longPath)).isTrue();
179 assertThat(WindowsFileOperations.isJunction(shortPath)).isTrue();
180
181 // Assert that after deleting the file and creating a directory with the same path, it is
182 // identified as not a junction.
183 assertThat(helloFile.delete()).isTrue();
184 assertThat(helloFile.mkdir()).isTrue();
185 assertThat(WindowsFileOperations.isJunction(longPath)).isFalse();
186 assertThat(WindowsFileOperations.isJunction(shortPath)).isFalse();
187 }
188
189 @Test
190 public void testGetLongPath() throws Exception {
191 File foo = testUtil.scratchDir("foo").toAbsolutePath().toFile();
192 assertThat(foo.exists()).isTrue();
193 assertThat(WindowsFileOperations.getLongPath(foo.getAbsolutePath())).endsWith("foo");
194
195 String longPath = foo.getAbsolutePath() + "\\will.exist\\helloworld.txt";
196 String shortPath = foo.getAbsolutePath() + "\\will~1.exi\\hellow~1.txt";
197
198 // Assert that the long path resolution fails for non-existent file.
199 try {
200 WindowsFileOperations.getLongPath(longPath);
201 fail("expected to throw");
202 } catch (IOException e) {
203 assertThat(e.getMessage()).contains("GetLongPathName");
204 }
205 try {
206 WindowsFileOperations.getLongPath(shortPath);
207 fail("expected to throw");
208 } catch (IOException e) {
209 assertThat(e.getMessage()).contains("GetLongPathName");
210 }
211
212 // Create the file, assert that long path resolution works and is correct.
213 File helloFile =
214 testUtil.scratchFile("foo/will.exist/helloworld.txt", "hello").toAbsolutePath().toFile();
215 assertThat(helloFile.getAbsolutePath()).isEqualTo(longPath);
216 assertThat(helloFile.exists()).isTrue();
217 assertThat(new File(longPath).exists()).isTrue();
218 assertThat(new File(shortPath).exists()).isTrue();
219 assertThat(WindowsFileOperations.getLongPath(longPath)).endsWith("will.exist\\helloworld.txt");
220 assertThat(WindowsFileOperations.getLongPath(shortPath)).endsWith("will.exist\\helloworld.txt");
221
222 // Delete the file and the directory, assert that long path resolution fails for them.
223 assertThat(helloFile.delete()).isTrue();
224 assertThat(helloFile.getParentFile().delete()).isTrue();
225 try {
226 WindowsFileOperations.getLongPath(longPath);
227 fail("expected to throw");
228 } catch (IOException e) {
229 assertThat(e.getMessage()).contains("GetLongPathName");
230 }
231 try {
232 WindowsFileOperations.getLongPath(shortPath);
233 fail("expected to throw");
234 } catch (IOException e) {
235 assertThat(e.getMessage()).contains("GetLongPathName");
236 }
237
238 // Create the directory and file with different names, but same 8dot3 names, assert that the
239 // resolution is still correct.
240 helloFile =
241 testUtil
242 .scratchFile("foo/will.exist_again/hellowelt.txt", "hello")
243 .toAbsolutePath()
244 .toFile();
245 assertThat(new File(shortPath).exists()).isTrue();
246 assertThat(WindowsFileOperations.getLongPath(shortPath))
247 .endsWith("will.exist_again\\hellowelt.txt");
248 assertThat(WindowsFileOperations.getLongPath(foo + "\\will.exist_again\\hellowelt.txt"))
249 .endsWith("will.exist_again\\hellowelt.txt");
250 try {
251 WindowsFileOperations.getLongPath(longPath);
252 fail("expected to throw");
253 } catch (IOException e) {
254 assertThat(e.getMessage()).contains("GetLongPathName");
255 }
256 }
Laszlo Csomor4fca9882016-09-02 09:48:42 +0000257}