blob: 107f620c26e4e8cae29d9e0a20efd337c830c9ab [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 Csomor13f92262017-06-30 16:22:41 +020023import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
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 Csomor4fca9882016-09-02 09:48:42 +000047 scratchRoot = new File(System.getenv("TEST_TMPDIR")).getAbsolutePath() + "/x";
Laszlo Csomorb65d7542016-09-07 10:22:06 +000048 testUtil = new WindowsTestUtil(scratchRoot);
Laszlo Csomora2da3112016-09-07 08:06:15 +000049 cleanupScratchDir();
Laszlo Csomor4fca9882016-09-02 09:48:42 +000050 }
51
52 @After
53 public void cleanupScratchDir() throws Exception {
Laszlo Csomorb65d7542016-09-07 10:22:06 +000054 testUtil.deleteAllUnder("");
Laszlo Csomor4fca9882016-09-02 09:48:42 +000055 }
56
57 @Test
58 public void testMockJunctionCreation() throws Exception {
Laszlo Csomorb65d7542016-09-07 10:22:06 +000059 String root = testUtil.scratchDir("dir").getParent().toString();
60 testUtil.scratchFile("dir/file.txt", "hello");
61 testUtil.createJunctions(ImmutableMap.of("junc", "dir"));
Laszlo Csomor4fca9882016-09-02 09:48:42 +000062 String[] children = new File(root + "/junc").list();
63 assertThat(children).isNotNull();
64 assertThat(children).hasLength(1);
65 assertThat(Arrays.asList(children)).containsExactly("file.txt");
66 }
67
68 @Test
69 public void testIsJunction() throws Exception {
70 final Map<String, String> junctions = new HashMap<>();
71 junctions.put("shrtpath/a", "shrttrgt");
72 junctions.put("shrtpath/b", "longtargetpath");
73 junctions.put("shrtpath/c", "longta~1");
74 junctions.put("longlinkpath/a", "shrttrgt");
75 junctions.put("longlinkpath/b", "longtargetpath");
76 junctions.put("longlinkpath/c", "longta~1");
77 junctions.put("abbrev~1/a", "shrttrgt");
78 junctions.put("abbrev~1/b", "longtargetpath");
79 junctions.put("abbrev~1/c", "longta~1");
80
Laszlo Csomorb65d7542016-09-07 10:22:06 +000081 String root = testUtil.scratchDir("shrtpath").getParent().toAbsolutePath().toString();
82 testUtil.scratchDir("longlinkpath");
83 testUtil.scratchDir("abbreviated");
84 testUtil.scratchDir("control/a");
85 testUtil.scratchDir("control/b");
86 testUtil.scratchDir("control/c");
Laszlo Csomor4fca9882016-09-02 09:48:42 +000087
Laszlo Csomorb65d7542016-09-07 10:22:06 +000088 testUtil.scratchFile("shrttrgt/file1.txt", "hello");
89 testUtil.scratchFile("longtargetpath/file2.txt", "hello");
Laszlo Csomor4fca9882016-09-02 09:48:42 +000090
Laszlo Csomorb65d7542016-09-07 10:22:06 +000091 testUtil.createJunctions(junctions);
Laszlo Csomor4fca9882016-09-02 09:48:42 +000092
93 assertThat(WindowsFileOperations.isJunction(root + "/shrtpath/a")).isTrue();
94 assertThat(WindowsFileOperations.isJunction(root + "/shrtpath/b")).isTrue();
95 assertThat(WindowsFileOperations.isJunction(root + "/shrtpath/c")).isTrue();
96 assertThat(WindowsFileOperations.isJunction(root + "/longlinkpath/a")).isTrue();
97 assertThat(WindowsFileOperations.isJunction(root + "/longlinkpath/b")).isTrue();
98 assertThat(WindowsFileOperations.isJunction(root + "/longlinkpath/c")).isTrue();
99 assertThat(WindowsFileOperations.isJunction(root + "/longli~1/a")).isTrue();
100 assertThat(WindowsFileOperations.isJunction(root + "/longli~1/b")).isTrue();
101 assertThat(WindowsFileOperations.isJunction(root + "/longli~1/c")).isTrue();
102 assertThat(WindowsFileOperations.isJunction(root + "/abbreviated/a")).isTrue();
103 assertThat(WindowsFileOperations.isJunction(root + "/abbreviated/b")).isTrue();
104 assertThat(WindowsFileOperations.isJunction(root + "/abbreviated/c")).isTrue();
105 assertThat(WindowsFileOperations.isJunction(root + "/abbrev~1/a")).isTrue();
106 assertThat(WindowsFileOperations.isJunction(root + "/abbrev~1/b")).isTrue();
107 assertThat(WindowsFileOperations.isJunction(root + "/abbrev~1/c")).isTrue();
108 assertThat(WindowsFileOperations.isJunction(root + "/control/a")).isFalse();
109 assertThat(WindowsFileOperations.isJunction(root + "/control/b")).isFalse();
110 assertThat(WindowsFileOperations.isJunction(root + "/control/c")).isFalse();
111 assertThat(WindowsFileOperations.isJunction(root + "/shrttrgt/file1.txt")).isFalse();
112 assertThat(WindowsFileOperations.isJunction(root + "/longtargetpath/file2.txt")).isFalse();
113 assertThat(WindowsFileOperations.isJunction(root + "/longta~1/file2.txt")).isFalse();
114 try {
115 WindowsFileOperations.isJunction(root + "/non-existent");
116 fail("expected to throw");
117 } catch (IOException e) {
Laszlo Csomor4e33ac62016-12-06 17:24:53 +0000118 assertThat(e.getMessage()).contains("GetFileAttributes");
Laszlo Csomor4fca9882016-09-02 09:48:42 +0000119 }
120 assertThat(Arrays.asList(new File(root + "/shrtpath/a").list())).containsExactly("file1.txt");
121 assertThat(Arrays.asList(new File(root + "/shrtpath/b").list())).containsExactly("file2.txt");
122 assertThat(Arrays.asList(new File(root + "/shrtpath/c").list())).containsExactly("file2.txt");
123 assertThat(Arrays.asList(new File(root + "/longlinkpath/a").list()))
124 .containsExactly("file1.txt");
125 assertThat(Arrays.asList(new File(root + "/longlinkpath/b").list()))
126 .containsExactly("file2.txt");
127 assertThat(Arrays.asList(new File(root + "/longlinkpath/c").list()))
128 .containsExactly("file2.txt");
129 assertThat(Arrays.asList(new File(root + "/abbreviated/a").list()))
130 .containsExactly("file1.txt");
131 assertThat(Arrays.asList(new File(root + "/abbreviated/b").list()))
132 .containsExactly("file2.txt");
133 assertThat(Arrays.asList(new File(root + "/abbreviated/c").list()))
134 .containsExactly("file2.txt");
135 }
Laszlo Csomor94d90582016-09-08 15:08:00 +0000136
137 @Test
138 public void testIsJunctionIsTrueForDanglingJunction() throws Exception {
139 java.nio.file.Path helloPath = testUtil.scratchFile("target\\hello.txt", "hello");
140 testUtil.createJunctions(ImmutableMap.of("link", "target"));
141
142 File linkPath = new File(helloPath.getParent().getParent().toFile(), "link");
143 assertThat(Arrays.asList(linkPath.list())).containsExactly("hello.txt");
144 assertThat(WindowsFileOperations.isJunction(linkPath.getAbsolutePath())).isTrue();
145
146 assertThat(helloPath.toFile().delete()).isTrue();
147 assertThat(helloPath.getParent().toFile().delete()).isTrue();
148 assertThat(helloPath.getParent().toFile().exists()).isFalse();
149 assertThat(Arrays.asList(linkPath.getParentFile().list())).containsExactly("link");
150
151 assertThat(WindowsFileOperations.isJunction(linkPath.getAbsolutePath())).isTrue();
152 assertThat(
153 Files.exists(
154 linkPath.toPath(), WindowsFileSystem.symlinkOpts(/* followSymlinks */ false)))
155 .isTrue();
156 assertThat(
157 Files.exists(
158 linkPath.toPath(), WindowsFileSystem.symlinkOpts(/* followSymlinks */ true)))
159 .isFalse();
160 }
Laszlo Csomoraa1614b2016-12-15 11:16:44 +0000161
162 @Test
163 public void testIsJunctionHandlesFilesystemChangesCorrectly() throws Exception {
164 File helloFile =
165 testUtil.scratchFile("target\\helloworld.txt", "hello").toAbsolutePath().toFile();
166
167 // Assert that a file is identified as not a junction.
168 String longPath = helloFile.getAbsolutePath();
169 String shortPath = new File(helloFile.getParentFile(), "hellow~1.txt").getAbsolutePath();
170 assertThat(WindowsFileOperations.isJunction(longPath)).isFalse();
171 assertThat(WindowsFileOperations.isJunction(shortPath)).isFalse();
172
173 // Assert that after deleting the file and creating a junction with the same path, it is
174 // identified as a junction.
175 assertThat(helloFile.delete()).isTrue();
176 testUtil.createJunctions(ImmutableMap.of("target\\helloworld.txt", "target"));
177 assertThat(WindowsFileOperations.isJunction(longPath)).isTrue();
178 assertThat(WindowsFileOperations.isJunction(shortPath)).isTrue();
179
180 // Assert that after deleting the file and creating a directory with the same path, it is
181 // identified as not a junction.
182 assertThat(helloFile.delete()).isTrue();
183 assertThat(helloFile.mkdir()).isTrue();
184 assertThat(WindowsFileOperations.isJunction(longPath)).isFalse();
185 assertThat(WindowsFileOperations.isJunction(shortPath)).isFalse();
186 }
187
188 @Test
189 public void testGetLongPath() throws Exception {
190 File foo = testUtil.scratchDir("foo").toAbsolutePath().toFile();
191 assertThat(foo.exists()).isTrue();
192 assertThat(WindowsFileOperations.getLongPath(foo.getAbsolutePath())).endsWith("foo");
193
194 String longPath = foo.getAbsolutePath() + "\\will.exist\\helloworld.txt";
195 String shortPath = foo.getAbsolutePath() + "\\will~1.exi\\hellow~1.txt";
196
197 // Assert that the long path resolution fails for non-existent file.
198 try {
199 WindowsFileOperations.getLongPath(longPath);
200 fail("expected to throw");
201 } catch (IOException e) {
202 assertThat(e.getMessage()).contains("GetLongPathName");
203 }
204 try {
205 WindowsFileOperations.getLongPath(shortPath);
206 fail("expected to throw");
207 } catch (IOException e) {
208 assertThat(e.getMessage()).contains("GetLongPathName");
209 }
210
211 // Create the file, assert that long path resolution works and is correct.
212 File helloFile =
213 testUtil.scratchFile("foo/will.exist/helloworld.txt", "hello").toAbsolutePath().toFile();
214 assertThat(helloFile.getAbsolutePath()).isEqualTo(longPath);
215 assertThat(helloFile.exists()).isTrue();
216 assertThat(new File(longPath).exists()).isTrue();
217 assertThat(new File(shortPath).exists()).isTrue();
218 assertThat(WindowsFileOperations.getLongPath(longPath)).endsWith("will.exist\\helloworld.txt");
219 assertThat(WindowsFileOperations.getLongPath(shortPath)).endsWith("will.exist\\helloworld.txt");
220
221 // Delete the file and the directory, assert that long path resolution fails for them.
222 assertThat(helloFile.delete()).isTrue();
223 assertThat(helloFile.getParentFile().delete()).isTrue();
224 try {
225 WindowsFileOperations.getLongPath(longPath);
226 fail("expected to throw");
227 } catch (IOException e) {
228 assertThat(e.getMessage()).contains("GetLongPathName");
229 }
230 try {
231 WindowsFileOperations.getLongPath(shortPath);
232 fail("expected to throw");
233 } catch (IOException e) {
234 assertThat(e.getMessage()).contains("GetLongPathName");
235 }
236
237 // Create the directory and file with different names, but same 8dot3 names, assert that the
238 // resolution is still correct.
239 helloFile =
240 testUtil
241 .scratchFile("foo/will.exist_again/hellowelt.txt", "hello")
242 .toAbsolutePath()
243 .toFile();
244 assertThat(new File(shortPath).exists()).isTrue();
245 assertThat(WindowsFileOperations.getLongPath(shortPath))
246 .endsWith("will.exist_again\\hellowelt.txt");
247 assertThat(WindowsFileOperations.getLongPath(foo + "\\will.exist_again\\hellowelt.txt"))
248 .endsWith("will.exist_again\\hellowelt.txt");
249 try {
250 WindowsFileOperations.getLongPath(longPath);
251 fail("expected to throw");
252 } catch (IOException e) {
253 assertThat(e.getMessage()).contains("GetLongPathName");
254 }
255 }
Laszlo Csomor4fca9882016-09-02 09:48:42 +0000256}