blob: 80c62c7b3a0c67fe1767d18ea8457fc19e04192d [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +01002//
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
Googler2258b812017-12-19 12:25:43 -080016import static com.google.common.collect.ImmutableList.toImmutableList;
Ulf Adams795895a2015-03-06 15:58:35 +000017import static com.google.common.truth.Truth.assertThat;
ajurkowski8d7e8ff2021-01-13 11:10:22 -080018import static com.google.devtools.build.lib.vfs.PathFragment.EMPTY_FRAGMENT;
tomlua729b9b2018-02-08 15:32:00 -080019import static com.google.devtools.build.lib.vfs.PathFragment.create;
michajlo660d17f2020-03-27 09:01:57 -070020import static org.junit.Assert.assertThrows;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010021
jhorvitz5fa47192021-04-19 10:25:53 -070022import com.google.common.collect.ImmutableClassToInstanceMap;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010023import com.google.common.collect.ImmutableList;
Mark Schallerb8154322015-06-22 16:02:24 +000024import com.google.common.collect.ImmutableSet;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010025import com.google.common.collect.Lists;
26import com.google.common.testing.EqualsTester;
janakr5b02f722020-04-29 08:06:46 -070027import com.google.devtools.build.lib.skyframe.serialization.DeserializationContext;
jhorvitz5fa47192021-04-19 10:25:53 -070028import com.google.devtools.build.lib.skyframe.serialization.SerializationContext;
shahan20f35b42018-02-28 15:57:33 -080029import com.google.devtools.build.lib.skyframe.serialization.testutils.SerializationTester;
janakr5b02f722020-04-29 08:06:46 -070030import com.google.devtools.build.lib.skyframe.serialization.testutils.TestUtils;
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010031import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
janakr5b02f722020-04-29 08:06:46 -070032import com.google.protobuf.ByteString;
jhorvitzbc9fc612021-04-01 13:50:43 -070033import com.google.testing.junit.testparameterinjector.TestParameter;
34import com.google.testing.junit.testparameterinjector.TestParameterInjector;
Philipp Wollermannd628b802016-10-19 12:14:38 +000035import java.io.File;
36import java.util.Collections;
37import java.util.List;
Laszlo Csomorca99bb72016-10-25 13:15:55 +000038import org.junit.Test;
39import org.junit.runner.RunWith;
Philipp Wollermannd628b802016-10-19 12:14:38 +000040
jhorvitzbc9fc612021-04-01 13:50:43 -070041/** Tests for {@link PathFragment}. */
42@RunWith(TestParameterInjector.class)
43public final class PathFragmentTest {
Michajlo Matijkiwbaf44c92016-06-23 21:54:05 +000044
45 @Test
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010046 public void testEqualsAndHashCode() {
janakr97c0bd12020-09-08 13:19:03 -070047 InMemoryFileSystem filesystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010048
49 new EqualsTester()
Laszlo Csomorca99bb72016-10-25 13:15:55 +000050 .addEqualityGroup(
tomlua729b9b2018-02-08 15:32:00 -080051 create("../relative/path"),
52 create("..").getRelative("relative").getRelative("path"),
53 create(new File("../relative/path").getPath()))
54 .addEqualityGroup(create("something/else"))
55 .addEqualityGroup(create("/something/else"))
56 .addEqualityGroup(create("/"), create("//////"))
57 .addEqualityGroup(create(""), PathFragment.EMPTY_FRAGMENT)
tomlu6c919062018-01-11 17:32:09 -080058 .addEqualityGroup(filesystem.getPath("/")) // A Path object.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010059 .testEquals();
60 }
61
62 @Test
63 public void testHashCodeCache() {
tomlua729b9b2018-02-08 15:32:00 -080064 PathFragment relativePath = create("../relative/path");
65 PathFragment rootPath = create("/");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010066
67 int oldResult = relativePath.hashCode();
68 int rootResult = rootPath.hashCode();
lberkiaea56b32017-05-30 12:35:33 +020069 assertThat(relativePath.hashCode()).isEqualTo(oldResult);
70 assertThat(rootPath.hashCode()).isEqualTo(rootResult);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010071 }
72
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010073 @Test
74 public void testRelativeTo() {
tomlua729b9b2018-02-08 15:32:00 -080075 assertThat(create("foo/bar/baz").relativeTo("foo").getPathString()).isEqualTo("bar/baz");
76 assertThat(create("/foo/bar/baz").relativeTo("/foo").getPathString()).isEqualTo("bar/baz");
77 assertThat(create("foo/bar/baz").relativeTo("foo/bar").getPathString()).isEqualTo("baz");
78 assertThat(create("/foo/bar/baz").relativeTo("/foo/bar").getPathString()).isEqualTo("baz");
79 assertThat(create("/foo").relativeTo("/").getPathString()).isEqualTo("foo");
80 assertThat(create("foo").relativeTo("").getPathString()).isEqualTo("foo");
81 assertThat(create("foo/bar").relativeTo("").getPathString()).isEqualTo("foo/bar");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010082 }
83
84 @Test
85 public void testIsAbsolute() {
tomlua729b9b2018-02-08 15:32:00 -080086 assertThat(create("/absolute/test").isAbsolute()).isTrue();
87 assertThat(create("relative/test").isAbsolute()).isFalse();
88 assertThat(create(new File("/absolute/test").getPath()).isAbsolute()).isTrue();
89 assertThat(create(new File("relative/test").getPath()).isAbsolute()).isFalse();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +010090 }
91
92 @Test
93 public void testIsNormalized() {
tomlua729b9b2018-02-08 15:32:00 -080094 assertThat(PathFragment.isNormalized("/absolute/path")).isTrue();
95 assertThat(PathFragment.isNormalized("some//path")).isTrue();
96 assertThat(PathFragment.isNormalized("some/./path")).isFalse();
97 assertThat(PathFragment.isNormalized("../some/path")).isFalse();
98 assertThat(PathFragment.isNormalized("./some/path")).isFalse();
99 assertThat(PathFragment.isNormalized("some/path/..")).isFalse();
100 assertThat(PathFragment.isNormalized("some/path/.")).isFalse();
101 assertThat(PathFragment.isNormalized("some/other/../path")).isFalse();
102 assertThat(PathFragment.isNormalized("some/other//tricky..path..")).isTrue();
103 assertThat(PathFragment.isNormalized("/some/other//tricky..path..")).isTrue();
104 }
105
106 @Test
107 public void testContainsUpLevelReferences() {
108 assertThat(PathFragment.containsUplevelReferences("/absolute/path")).isFalse();
109 assertThat(PathFragment.containsUplevelReferences("some//path")).isFalse();
110 assertThat(PathFragment.containsUplevelReferences("some/./path")).isFalse();
111 assertThat(PathFragment.containsUplevelReferences("../some/path")).isTrue();
112 assertThat(PathFragment.containsUplevelReferences("./some/path")).isFalse();
113 assertThat(PathFragment.containsUplevelReferences("some/path/..")).isTrue();
114 assertThat(PathFragment.containsUplevelReferences("some/path/.")).isFalse();
115 assertThat(PathFragment.containsUplevelReferences("some/other/../path")).isTrue();
116 assertThat(PathFragment.containsUplevelReferences("some/other//tricky..path..")).isFalse();
117 assertThat(PathFragment.containsUplevelReferences("/some/other//tricky..path..")).isFalse();
118
119 // Normalization cannot remove leading uplevel references, so this will be true
120 assertThat(create("../some/path").containsUplevelReferences()).isTrue();
121 // Normalization will remove these, so no uplevel references left
122 assertThat(create("some/path/..").containsUplevelReferences()).isFalse();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100123 }
124
125 @Test
126 public void testRootNodeReturnsRootString() {
tomlua729b9b2018-02-08 15:32:00 -0800127 PathFragment rootFragment = create("/");
lberkiaea56b32017-05-30 12:35:33 +0200128 assertThat(rootFragment.getPathString()).isEqualTo("/");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100129 }
130
131 @Test
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100132 public void testGetRelative() {
tomlua729b9b2018-02-08 15:32:00 -0800133 assertThat(create("a").getRelative("b").getPathString()).isEqualTo("a/b");
134 assertThat(create("a/b").getRelative("c/d").getPathString()).isEqualTo("a/b/c/d");
135 assertThat(create("c/d").getRelative("/a/b").getPathString()).isEqualTo("/a/b");
136 assertThat(create("a").getRelative("").getPathString()).isEqualTo("a");
137 assertThat(create("/").getRelative("").getPathString()).isEqualTo("/");
138 assertThat(create("a/b").getRelative("../foo").getPathString()).isEqualTo("a/foo");
139 assertThat(create("/a/b").getRelative("../foo").getPathString()).isEqualTo("/a/foo");
140
141 // Make sure any fast path of PathFragment#getRelative(PathFragment) works
142 assertThat(create("a/b").getRelative(create("../foo")).getPathString()).isEqualTo("a/foo");
143 assertThat(create("/a/b").getRelative(create("../foo")).getPathString()).isEqualTo("/a/foo");
144
145 // Make sure any fast path of PathFragment#getRelative(PathFragment) works
146 assertThat(create("c/d").getRelative(create("/a/b")).getPathString()).isEqualTo("/a/b");
147
148 // Test normalization
149 assertThat(create("a").getRelative(".").getPathString()).isEqualTo("a");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100150 }
151
152 @Test
nharmata90750e62018-03-15 09:35:48 -0700153 public void testIsNormalizedRelativePath() {
154 assertThat(PathFragment.isNormalizedRelativePath("/a")).isFalse();
155 assertThat(PathFragment.isNormalizedRelativePath("a///b")).isFalse();
156 assertThat(PathFragment.isNormalizedRelativePath("../a")).isFalse();
157 assertThat(PathFragment.isNormalizedRelativePath("a/../b")).isFalse();
158 assertThat(PathFragment.isNormalizedRelativePath("a/b")).isTrue();
159 assertThat(PathFragment.isNormalizedRelativePath("ab")).isTrue();
160 }
161
162 @Test
163 public void testContainsSeparator() {
164 assertThat(PathFragment.containsSeparator("/a")).isTrue();
165 assertThat(PathFragment.containsSeparator("a///b")).isTrue();
166 assertThat(PathFragment.containsSeparator("../a")).isTrue();
167 assertThat(PathFragment.containsSeparator("a/../b")).isTrue();
168 assertThat(PathFragment.containsSeparator("a/b")).isTrue();
169 assertThat(PathFragment.containsSeparator("ab")).isFalse();
170 }
171
172 @Test
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100173 public void testGetChildWorks() {
tomlua729b9b2018-02-08 15:32:00 -0800174 PathFragment pf = create("../some/path");
175 assertThat(pf.getChild("hi")).isEqualTo(create("../some/path/hi"));
janakrd1ad61c2020-11-11 07:13:40 -0800176 assertThat(pf.getChild("h\\i")).isEqualTo(create("../some/path/h\\i"));
177 assertThat(create("../some/path").getChild(".hi")).isEqualTo(create("../some/path/.hi"));
178 assertThat(create("../some/path").getChild("..hi")).isEqualTo(create("../some/path/..hi"));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100179 }
180
181 @Test
182 public void testGetChildRejectsInvalidBaseNames() {
tomlua729b9b2018-02-08 15:32:00 -0800183 PathFragment pf = create("../some/path");
jcaterb0c7ee52019-05-02 12:33:13 -0700184 assertThrows(IllegalArgumentException.class, () -> pf.getChild("."));
185 assertThrows(IllegalArgumentException.class, () -> pf.getChild(".."));
186 assertThrows(IllegalArgumentException.class, () -> pf.getChild("x/y"));
187 assertThrows(IllegalArgumentException.class, () -> pf.getChild("/y"));
188 assertThrows(IllegalArgumentException.class, () -> pf.getChild("y/"));
189 assertThrows(IllegalArgumentException.class, () -> pf.getChild(""));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100190 }
191
192 @Test
193 public void testEmptyPathToEmptyPath() {
tomlua729b9b2018-02-08 15:32:00 -0800194 assertThat(create("/").getPathString()).isEqualTo("/");
195 assertThat(create("").getPathString()).isEqualTo("");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100196 }
197
198 @Test
199 public void testRedundantSlashes() {
tomlua729b9b2018-02-08 15:32:00 -0800200 assertThat(create("///").getPathString()).isEqualTo("/");
201 assertThat(create("/foo///bar").getPathString()).isEqualTo("/foo/bar");
202 assertThat(create("////foo//bar").getPathString()).isEqualTo("/foo/bar");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100203 }
204
205 @Test
206 public void testSimpleNameToSimpleName() {
tomlua729b9b2018-02-08 15:32:00 -0800207 assertThat(create("/foo").getPathString()).isEqualTo("/foo");
208 assertThat(create("foo").getPathString()).isEqualTo("foo");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100209 }
210
211 @Test
212 public void testSimplePathToSimplePath() {
tomlua729b9b2018-02-08 15:32:00 -0800213 assertThat(create("/foo/bar").getPathString()).isEqualTo("/foo/bar");
214 assertThat(create("foo/bar").getPathString()).isEqualTo("foo/bar");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100215 }
216
217 @Test
218 public void testStripsTrailingSlash() {
tomlua729b9b2018-02-08 15:32:00 -0800219 assertThat(create("/foo/bar/").getPathString()).isEqualTo("/foo/bar");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100220 }
221
222 @Test
223 public void testGetParentDirectory() {
tomlua729b9b2018-02-08 15:32:00 -0800224 PathFragment fooBarWiz = create("foo/bar/wiz");
225 PathFragment fooBar = create("foo/bar");
226 PathFragment foo = create("foo");
227 PathFragment empty = create("");
lberkiaea56b32017-05-30 12:35:33 +0200228 assertThat(fooBarWiz.getParentDirectory()).isEqualTo(fooBar);
229 assertThat(fooBar.getParentDirectory()).isEqualTo(foo);
230 assertThat(foo.getParentDirectory()).isEqualTo(empty);
231 assertThat(empty.getParentDirectory()).isNull();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100232
tomlua729b9b2018-02-08 15:32:00 -0800233 PathFragment fooBarWizAbs = create("/foo/bar/wiz");
234 PathFragment fooBarAbs = create("/foo/bar");
235 PathFragment fooAbs = create("/foo");
236 PathFragment rootAbs = create("/");
lberkiaea56b32017-05-30 12:35:33 +0200237 assertThat(fooBarWizAbs.getParentDirectory()).isEqualTo(fooBarAbs);
238 assertThat(fooBarAbs.getParentDirectory()).isEqualTo(fooAbs);
239 assertThat(fooAbs.getParentDirectory()).isEqualTo(rootAbs);
240 assertThat(rootAbs.getParentDirectory()).isNull();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100241 }
Michajlo Matijkiwbaf44c92016-06-23 21:54:05 +0000242
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100243 @Test
244 public void testSegmentsCount() {
tomlua729b9b2018-02-08 15:32:00 -0800245 assertThat(create("foo/bar").segmentCount()).isEqualTo(2);
246 assertThat(create("/foo/bar").segmentCount()).isEqualTo(2);
247 assertThat(create("foo//bar").segmentCount()).isEqualTo(2);
248 assertThat(create("/foo//bar").segmentCount()).isEqualTo(2);
249 assertThat(create("foo/").segmentCount()).isEqualTo(1);
250 assertThat(create("/foo/").segmentCount()).isEqualTo(1);
251 assertThat(create("foo").segmentCount()).isEqualTo(1);
252 assertThat(create("/foo").segmentCount()).isEqualTo(1);
253 assertThat(create("/").segmentCount()).isEqualTo(0);
254 assertThat(create("").segmentCount()).isEqualTo(0);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100255 }
256
jhorvitzbc9fc612021-04-01 13:50:43 -0700257 @Test
258 public void isSingleSegment_true(@TestParameter({"/foo", "foo"}) String path) {
259 assertThat(create(path).isSingleSegment()).isTrue();
260 }
261
262 @Test
263 public void isSingleSegment_false(
264 @TestParameter({"/", "", "/foo/bar", "foo/bar", "/foo/bar/baz", "foo/bar/baz"}) String path) {
265 assertThat(create(path).isSingleSegment()).isFalse();
266 }
267
268 @Test
269 public void isMultiSegment_true(
270 @TestParameter({"/foo/bar", "foo/bar", "/foo/bar/baz", "foo/bar/baz"}) String path) {
271 assertThat(create(path).isMultiSegment()).isTrue();
272 }
273
274 @Test
275 public void isMultiSegment_false(@TestParameter({"/", "", "/foo", "foo"}) String path) {
276 assertThat(create(path).isMultiSegment()).isFalse();
277 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100278
279 @Test
280 public void testGetSegment() {
tomlua729b9b2018-02-08 15:32:00 -0800281 assertThat(create("foo/bar").getSegment(0)).isEqualTo("foo");
282 assertThat(create("foo/bar").getSegment(1)).isEqualTo("bar");
283 assertThat(create("/foo/bar").getSegment(0)).isEqualTo("foo");
284 assertThat(create("/foo/bar").getSegment(1)).isEqualTo("bar");
285 assertThat(create("foo/").getSegment(0)).isEqualTo("foo");
286 assertThat(create("/foo/").getSegment(0)).isEqualTo("foo");
287 assertThat(create("foo").getSegment(0)).isEqualTo("foo");
288 assertThat(create("/foo").getSegment(0)).isEqualTo("foo");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100289 }
290
291 @Test
jhorvitz60347952021-02-18 10:05:05 -0800292 public void segments() {
293 assertThat(create("/this/is/a/path").segments())
294 .containsExactly("this", "is", "a", "path")
295 .inOrder();
296 }
297
298 @Test
jhorvitz5fa47192021-04-19 10:25:53 -0700299 public void testBasename() {
tomlua729b9b2018-02-08 15:32:00 -0800300 assertThat(create("foo/bar").getBaseName()).isEqualTo("bar");
301 assertThat(create("/foo/bar").getBaseName()).isEqualTo("bar");
302 assertThat(create("foo/").getBaseName()).isEqualTo("foo");
303 assertThat(create("/foo/").getBaseName()).isEqualTo("foo");
304 assertThat(create("foo").getBaseName()).isEqualTo("foo");
305 assertThat(create("/foo").getBaseName()).isEqualTo("foo");
306 assertThat(create("/").getBaseName()).isEmpty();
307 assertThat(create("").getBaseName()).isEmpty();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100308 }
309
Paul Roberts8c443ef2016-10-18 02:04:25 +0000310 @Test
jhorvitz5fa47192021-04-19 10:25:53 -0700311 public void testFileExtension() {
tomlua729b9b2018-02-08 15:32:00 -0800312 assertThat(create("foo.bar").getFileExtension()).isEqualTo("bar");
313 assertThat(create("foo.barr").getFileExtension()).isEqualTo("barr");
314 assertThat(create("foo.b").getFileExtension()).isEqualTo("b");
315 assertThat(create("foo.").getFileExtension()).isEmpty();
316 assertThat(create("foo").getFileExtension()).isEmpty();
317 assertThat(create(".").getFileExtension()).isEmpty();
318 assertThat(create("").getFileExtension()).isEmpty();
319 assertThat(create("foo/bar.baz").getFileExtension()).isEqualTo("baz");
320 assertThat(create("foo.bar.baz").getFileExtension()).isEqualTo("baz");
321 assertThat(create("foo.bar/baz").getFileExtension()).isEmpty();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100322 }
323
324 @Test
jhorvitz5fa47192021-04-19 10:25:53 -0700325 public void testReplaceName() {
tomlua729b9b2018-02-08 15:32:00 -0800326 assertThat(create("foo/bar").replaceName("baz").getPathString()).isEqualTo("foo/baz");
327 assertThat(create("/foo/bar").replaceName("baz").getPathString()).isEqualTo("/foo/baz");
328 assertThat(create("foo/bar").replaceName("").getPathString()).isEqualTo("foo");
329 assertThat(create("foo/").replaceName("baz").getPathString()).isEqualTo("baz");
330 assertThat(create("/foo/").replaceName("baz").getPathString()).isEqualTo("/baz");
331 assertThat(create("foo").replaceName("baz").getPathString()).isEqualTo("baz");
332 assertThat(create("/foo").replaceName("baz").getPathString()).isEqualTo("/baz");
333 assertThat(create("/").replaceName("baz")).isNull();
334 assertThat(create("/").replaceName("")).isNull();
335 assertThat(create("").replaceName("baz")).isNull();
336 assertThat(create("").replaceName("")).isNull();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100337
tomlua729b9b2018-02-08 15:32:00 -0800338 assertThat(create("foo/bar").replaceName("bar/baz").getPathString()).isEqualTo("foo/bar/baz");
339 assertThat(create("foo/bar").replaceName("bar/baz/").getPathString()).isEqualTo("foo/bar/baz");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100340
341 // Absolute path arguments will clobber the original path.
tomlua729b9b2018-02-08 15:32:00 -0800342 assertThat(create("foo/bar").replaceName("/absolute").getPathString()).isEqualTo("/absolute");
343 assertThat(create("foo/bar").replaceName("/").getPathString()).isEqualTo("/");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100344 }
jhorvitz5fa47192021-04-19 10:25:53 -0700345
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100346 @Test
jhorvitz5fa47192021-04-19 10:25:53 -0700347 public void testSubFragment() {
tomlua729b9b2018-02-08 15:32:00 -0800348 assertThat(create("/foo/bar/baz").subFragment(0, 3).getPathString()).isEqualTo("/foo/bar/baz");
349 assertThat(create("foo/bar/baz").subFragment(0, 3).getPathString()).isEqualTo("foo/bar/baz");
350 assertThat(create("/foo/bar/baz").subFragment(0, 2).getPathString()).isEqualTo("/foo/bar");
351 assertThat(create("/foo/bar/baz").subFragment(1, 3).getPathString()).isEqualTo("bar/baz");
352 assertThat(create("/foo/bar/baz").subFragment(0, 1).getPathString()).isEqualTo("/foo");
353 assertThat(create("/foo/bar/baz").subFragment(1, 2).getPathString()).isEqualTo("bar");
354 assertThat(create("/foo/bar/baz").subFragment(2, 3).getPathString()).isEqualTo("baz");
355 assertThat(create("/foo/bar/baz").subFragment(0, 0).getPathString()).isEqualTo("/");
356 assertThat(create("foo/bar/baz").subFragment(0, 0).getPathString()).isEqualTo("");
357 assertThat(create("foo/bar/baz").subFragment(1, 1).getPathString()).isEqualTo("");
358
359 assertThat(create("/foo/bar/baz").subFragment(0).getPathString()).isEqualTo("/foo/bar/baz");
360 assertThat(create("foo/bar/baz").subFragment(0).getPathString()).isEqualTo("foo/bar/baz");
361 assertThat(create("/foo/bar/baz").subFragment(1).getPathString()).isEqualTo("bar/baz");
362 assertThat(create("foo/bar/baz").subFragment(1).getPathString()).isEqualTo("bar/baz");
363 assertThat(create("foo/bar/baz").subFragment(2).getPathString()).isEqualTo("baz");
364 assertThat(create("foo/bar/baz").subFragment(3).getPathString()).isEqualTo("");
365
jcaterb0c7ee52019-05-02 12:33:13 -0700366 assertThrows(IndexOutOfBoundsException.class, () -> create("foo/bar/baz").subFragment(3, 2));
367 assertThrows(IndexOutOfBoundsException.class, () -> create("foo/bar/baz").subFragment(4, 4));
368 assertThrows(IndexOutOfBoundsException.class, () -> create("foo/bar/baz").subFragment(3, 2));
369 assertThrows(IndexOutOfBoundsException.class, () -> create("foo/bar/baz").subFragment(4));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100370 }
371
372 @Test
373 public void testStartsWith() {
tomlua729b9b2018-02-08 15:32:00 -0800374 PathFragment foobar = create("/foo/bar");
375 PathFragment foobarRelative = create("foo/bar");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100376
377 // (path, prefix) => true
lberkiaea56b32017-05-30 12:35:33 +0200378 assertThat(foobar.startsWith(foobar)).isTrue();
tomlua729b9b2018-02-08 15:32:00 -0800379 assertThat(foobar.startsWith(create("/"))).isTrue();
380 assertThat(foobar.startsWith(create("/foo"))).isTrue();
381 assertThat(foobar.startsWith(create("/foo/"))).isTrue();
382 assertThat(foobar.startsWith(create("/foo/bar/"))).isTrue(); // Includes trailing slash.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100383
384 // (prefix, path) => false
tomlua729b9b2018-02-08 15:32:00 -0800385 assertThat(create("/foo").startsWith(foobar)).isFalse();
386 assertThat(create("/").startsWith(foobar)).isFalse();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100387
388 // (absolute, relative) => false
lberkiaea56b32017-05-30 12:35:33 +0200389 assertThat(foobar.startsWith(foobarRelative)).isFalse();
390 assertThat(foobarRelative.startsWith(foobar)).isFalse();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100391
392 // (relative path, relative prefix) => true
lberkiaea56b32017-05-30 12:35:33 +0200393 assertThat(foobarRelative.startsWith(foobarRelative)).isTrue();
tomlua729b9b2018-02-08 15:32:00 -0800394 assertThat(foobarRelative.startsWith(create("foo"))).isTrue();
395 assertThat(foobarRelative.startsWith(create(""))).isTrue();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100396
397 // (path, sibling) => false
tomlua729b9b2018-02-08 15:32:00 -0800398 assertThat(create("/foo/wiz").startsWith(foobar)).isFalse();
399 assertThat(foobar.startsWith(create("/foo/wiz"))).isFalse();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100400 }
401
402 @Test
Mark Schallerb8154322015-06-22 16:02:24 +0000403 public void testCheckAllPathsStartWithButAreNotEqualTo() {
404 // Check passes:
tomlua729b9b2018-02-08 15:32:00 -0800405 PathFragment.checkAllPathsAreUnder(toPathsSet("a/b", "a/c"), create("a"));
Mark Schallerb8154322015-06-22 16:02:24 +0000406
407 // Check trivially passes:
jhorvitz5fa47192021-04-19 10:25:53 -0700408 PathFragment.checkAllPathsAreUnder(ImmutableList.of(), create("a"));
Mark Schallerb8154322015-06-22 16:02:24 +0000409
410 // Check fails when some path does not start with startingWithPath:
jcaterb0c7ee52019-05-02 12:33:13 -0700411 assertThrows(
tomlua729b9b2018-02-08 15:32:00 -0800412 IllegalArgumentException.class,
413 () -> PathFragment.checkAllPathsAreUnder(toPathsSet("a/b", "b/c"), create("a")));
Mark Schallerb8154322015-06-22 16:02:24 +0000414
415 // Check fails when some path is equal to startingWithPath:
jcaterb0c7ee52019-05-02 12:33:13 -0700416 assertThrows(
tomlua729b9b2018-02-08 15:32:00 -0800417 IllegalArgumentException.class,
418 () -> PathFragment.checkAllPathsAreUnder(toPathsSet("a/b", "a"), create("a")));
Mark Schallerb8154322015-06-22 16:02:24 +0000419 }
420
421 @Test
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100422 public void testEndsWith() {
tomlua729b9b2018-02-08 15:32:00 -0800423 PathFragment foobar = create("/foo/bar");
424 PathFragment foobarRelative = create("foo/bar");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100425
426 // (path, suffix) => true
lberkiaea56b32017-05-30 12:35:33 +0200427 assertThat(foobar.endsWith(foobar)).isTrue();
tomlua729b9b2018-02-08 15:32:00 -0800428 assertThat(foobar.endsWith(create("bar"))).isTrue();
429 assertThat(foobar.endsWith(create("foo/bar"))).isTrue();
430 assertThat(foobar.endsWith(create("/foo/bar"))).isTrue();
431 assertThat(foobar.endsWith(create("/bar"))).isFalse();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100432
433 // (prefix, path) => false
tomlua729b9b2018-02-08 15:32:00 -0800434 assertThat(create("/foo").endsWith(foobar)).isFalse();
435 assertThat(create("/").endsWith(foobar)).isFalse();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100436
437 // (suffix, path) => false
tomlua729b9b2018-02-08 15:32:00 -0800438 assertThat(create("/bar").endsWith(foobar)).isFalse();
439 assertThat(create("bar").endsWith(foobar)).isFalse();
440 assertThat(create("").endsWith(foobar)).isFalse();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100441
442 // (absolute, relative) => true
lberkiaea56b32017-05-30 12:35:33 +0200443 assertThat(foobar.endsWith(foobarRelative)).isTrue();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100444
445 // (relative, absolute) => false
lberkiaea56b32017-05-30 12:35:33 +0200446 assertThat(foobarRelative.endsWith(foobar)).isFalse();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100447
448 // (relative path, relative prefix) => true
lberkiaea56b32017-05-30 12:35:33 +0200449 assertThat(foobarRelative.endsWith(foobarRelative)).isTrue();
tomlua729b9b2018-02-08 15:32:00 -0800450 assertThat(foobarRelative.endsWith(create("bar"))).isTrue();
451 assertThat(foobarRelative.endsWith(create(""))).isTrue();
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100452
453 // (path, sibling) => false
tomlua729b9b2018-02-08 15:32:00 -0800454 assertThat(create("/foo/wiz").endsWith(foobar)).isFalse();
455 assertThat(foobar.endsWith(create("/foo/wiz"))).isFalse();
456 }
457
458 @Test
459 public void testToRelative() {
460 assertThat(create("/foo/bar").toRelative()).isEqualTo(create("foo/bar"));
461 assertThat(create("/").toRelative()).isEqualTo(create(""));
jcaterb0c7ee52019-05-02 12:33:13 -0700462 assertThrows(IllegalArgumentException.class, () -> create("foo").toRelative());
tomlua729b9b2018-02-08 15:32:00 -0800463 }
464
465 @Test
466 public void testGetDriveStr() {
467 assertThat(create("/foo/bar").getDriveStr()).isEqualTo("/");
468 assertThat(create("/").getDriveStr()).isEqualTo("/");
jcaterb0c7ee52019-05-02 12:33:13 -0700469 assertThrows(IllegalArgumentException.class, () -> create("foo").getDriveStr());
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100470 }
471
jhorvitz5fa47192021-04-19 10:25:53 -0700472 private static List<PathFragment> toPaths(List<String> strs) {
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100473 List<PathFragment> paths = Lists.newArrayList();
474 for (String s : strs) {
tomlua729b9b2018-02-08 15:32:00 -0800475 paths.add(create(s));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100476 }
477 return paths;
478 }
479
jhorvitz5fa47192021-04-19 10:25:53 -0700480 private static ImmutableSet<PathFragment> toPathsSet(String... strs) {
Mark Schallerb8154322015-06-22 16:02:24 +0000481 ImmutableSet.Builder<PathFragment> builder = ImmutableSet.builder();
482 for (String str : strs) {
tomlua729b9b2018-02-08 15:32:00 -0800483 builder.add(create(str));
Mark Schallerb8154322015-06-22 16:02:24 +0000484 }
485 return builder.build();
486 }
487
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100488 @Test
jhorvitz5fa47192021-04-19 10:25:53 -0700489 public void testCompareTo() {
tomlua729b9b2018-02-08 15:32:00 -0800490 List<String> pathStrs =
491 ImmutableList.of(
492 "",
493 "/",
494 "foo",
495 "/foo",
496 "foo/bar",
497 "foo.bar",
498 "foo/bar.baz",
499 "foo/bar/baz",
500 "foo/barfile",
501 "foo/Bar",
502 "Foo/bar");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100503 List<PathFragment> paths = toPaths(pathStrs);
504 // First test that compareTo is self-consistent.
505 for (PathFragment x : paths) {
506 for (PathFragment y : paths) {
507 for (PathFragment z : paths) {
508 // Anti-symmetry
lberkiaea56b32017-05-30 12:35:33 +0200509 assertThat(-1 * Integer.signum(y.compareTo(x))).isEqualTo(Integer.signum(x.compareTo(y)));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100510 // Transitivity
511 if (x.compareTo(y) > 0 && y.compareTo(z) > 0) {
Googler2fa3ccf2015-11-10 14:30:39 +0000512 assertThat(x.compareTo(z)).isGreaterThan(0);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100513 }
514 // "Substitutability"
515 if (x.compareTo(y) == 0) {
lberkiaea56b32017-05-30 12:35:33 +0200516 assertThat(Integer.signum(y.compareTo(z))).isEqualTo(Integer.signum(x.compareTo(z)));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100517 }
518 // Consistency with equals
lberkiaea56b32017-05-30 12:35:33 +0200519 assertThat(x.equals(y)).isEqualTo((x.compareTo(y) == 0));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100520 }
521 }
522 }
tomlua729b9b2018-02-08 15:32:00 -0800523 // Now test that compareTo does what we expect. The exact ordering here doesn't matter much.
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100524 Collections.shuffle(paths);
525 Collections.sort(paths);
tomlua729b9b2018-02-08 15:32:00 -0800526 List<PathFragment> expectedOrder =
527 toPaths(
528 ImmutableList.of(
529 "",
530 "/",
531 "/foo",
532 "Foo/bar",
533 "foo",
534 "foo.bar",
535 "foo/Bar",
536 "foo/bar",
537 "foo/bar.baz",
538 "foo/bar/baz",
539 "foo/barfile"));
lberkiaea56b32017-05-30 12:35:33 +0200540 assertThat(paths).isEqualTo(expectedOrder);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100541 }
542
543 @Test
544 public void testGetSafePathString() {
tomlua729b9b2018-02-08 15:32:00 -0800545 assertThat(create("/").getSafePathString()).isEqualTo("/");
546 assertThat(create("/abc").getSafePathString()).isEqualTo("/abc");
547 assertThat(create("").getSafePathString()).isEqualTo(".");
lberkiaea56b32017-05-30 12:35:33 +0200548 assertThat(PathFragment.EMPTY_FRAGMENT.getSafePathString()).isEqualTo(".");
tomlua729b9b2018-02-08 15:32:00 -0800549 assertThat(create("abc/def").getSafePathString()).isEqualTo("abc/def");
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100550 }
Michajlo Matijkiwbaf44c92016-06-23 21:54:05 +0000551
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100552 @Test
553 public void testNormalize() {
tomlua729b9b2018-02-08 15:32:00 -0800554 assertThat(create("/a/b")).isEqualTo(create("/a/b"));
555 assertThat(create("/a/./b")).isEqualTo(create("/a/b"));
556 assertThat(create("/a/../b")).isEqualTo(create("/b"));
557 assertThat(create("a/b")).isEqualTo(create("a/b"));
558 assertThat(create("a/../../b")).isEqualTo(create("../b"));
559 assertThat(create("a/../..")).isEqualTo(create(".."));
560 assertThat(create("a/../b")).isEqualTo(create("b"));
561 assertThat(create("a/b/../b")).isEqualTo(create("a/b"));
562 assertThat(create("/..")).isEqualTo(create("/.."));
563 assertThat(create("..")).isEqualTo(create(".."));
564 }
565
566 @Test
567 public void testSegments() {
568 assertThat(create("").segmentCount()).isEqualTo(0);
569 assertThat(create("a").segmentCount()).isEqualTo(1);
570 assertThat(create("a/b").segmentCount()).isEqualTo(2);
571 assertThat(create("a/b/c").segmentCount()).isEqualTo(3);
572 assertThat(create("/").segmentCount()).isEqualTo(0);
573 assertThat(create("/a").segmentCount()).isEqualTo(1);
574 assertThat(create("/a/b").segmentCount()).isEqualTo(2);
575 assertThat(create("/a/b/c").segmentCount()).isEqualTo(3);
576
jhorvitzc4bdbe02021-02-26 08:11:03 -0800577 assertThat(create("").splitToListOfSegments()).isEmpty();
578 assertThat(create("a").splitToListOfSegments()).containsExactly("a").inOrder();
579 assertThat(create("a/b").splitToListOfSegments()).containsExactly("a", "b").inOrder();
580 assertThat(create("a/b/c").splitToListOfSegments()).containsExactly("a", "b", "c").inOrder();
581 assertThat(create("/").splitToListOfSegments()).isEmpty();
582 assertThat(create("/a").splitToListOfSegments()).containsExactly("a").inOrder();
583 assertThat(create("/a/b").splitToListOfSegments()).containsExactly("a", "b").inOrder();
584 assertThat(create("/a/b/c").splitToListOfSegments()).containsExactly("a", "b", "c").inOrder();
tomlua729b9b2018-02-08 15:32:00 -0800585
586 assertThat(create("a").getSegment(0)).isEqualTo("a");
587 assertThat(create("a/b").getSegment(0)).isEqualTo("a");
588 assertThat(create("a/b").getSegment(1)).isEqualTo("b");
589 assertThat(create("a/b/c").getSegment(2)).isEqualTo("c");
590 assertThat(create("/a").getSegment(0)).isEqualTo("a");
591 assertThat(create("/a/b").getSegment(0)).isEqualTo("a");
592 assertThat(create("/a/b").getSegment(1)).isEqualTo("b");
593 assertThat(create("/a/b/c").getSegment(2)).isEqualTo("c");
594
jcaterb0c7ee52019-05-02 12:33:13 -0700595 assertThrows(IllegalArgumentException.class, () -> create("").getSegment(0));
596 assertThrows(IllegalArgumentException.class, () -> create("a/b").getSegment(2));
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100597 }
598
599 @Test
Googler2258b812017-12-19 12:25:43 -0800600 public void testCodec() throws Exception {
shahan20f35b42018-02-28 15:57:33 -0800601 new SerializationTester(
Googler2258b812017-12-19 12:25:43 -0800602 ImmutableList.of("", "a", "/foo", "foo/bar/baz", "/a/path/fragment/with/lots/of/parts")
603 .stream()
604 .map(PathFragment::create)
605 .collect(toImmutableList()))
shahan20f35b42018-02-28 15:57:33 -0800606 .runTests();
Googler2258b812017-12-19 12:25:43 -0800607 }
608
609 @Test
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100610 public void testSerializationSimple() throws Exception {
janakr5b02f722020-04-29 08:06:46 -0700611 checkSerialization("a", 6);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100612 }
613
614 @Test
615 public void testSerializationAbsolute() throws Exception {
janakr5b02f722020-04-29 08:06:46 -0700616 checkSerialization("/foo", 9);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100617 }
618
619 @Test
620 public void testSerializationNested() throws Exception {
janakr5b02f722020-04-29 08:06:46 -0700621 checkSerialization("foo/bar/baz", 16);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100622 }
623
jhorvitz5fa47192021-04-19 10:25:53 -0700624 private static void checkSerialization(String pathFragmentString, int expectedSize)
625 throws Exception {
tomlua729b9b2018-02-08 15:32:00 -0800626 PathFragment a = create(pathFragmentString);
jhorvitz5fa47192021-04-19 10:25:53 -0700627 ByteString sa =
628 TestUtils.toBytes(new SerializationContext(ImmutableClassToInstanceMap.of()), a);
janakr5b02f722020-04-29 08:06:46 -0700629 assertThat(sa.size()).isEqualTo(expectedSize);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100630
janakr5b02f722020-04-29 08:06:46 -0700631 PathFragment a2 =
jhorvitz5fa47192021-04-19 10:25:53 -0700632 (PathFragment)
633 TestUtils.fromBytes(new DeserializationContext(ImmutableClassToInstanceMap.of()), sa);
lberkiaea56b32017-05-30 12:35:33 +0200634 assertThat(a2).isEqualTo(a);
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100635 }
ajurkowski8d7e8ff2021-01-13 11:10:22 -0800636
637 @Test
638 public void containsUplevelReference_emptyPath_returnsFalse() {
639 assertThat(EMPTY_FRAGMENT.containsUplevelReferences()).isFalse();
640 }
641
642 @Test
643 public void containsUplevelReference_uplevelOnlyPath_returnsTrue() {
644 PathFragment pathFragment = create("..");
645 assertThat(pathFragment.containsUplevelReferences()).isTrue();
646 }
647
648 @Test
649 public void containsUplevelReferences_firstSegmentStartingWithDotDot_returnsFalse() {
650 PathFragment pathFragment = create("..file");
651 assertThat(pathFragment.containsUplevelReferences()).isFalse();
652 }
653
654 @Test
655 public void containsUplevelReferences_startsWithUplevelReference_returnsTrue() {
656 PathFragment pathFragment = create("../file");
657 assertThat(pathFragment.containsUplevelReferences()).isTrue();
658 }
659
660 @Test
661 public void containsUplevelReferences_uplevelReferenceMidPath_normalizesAndReturnsFalse() {
662 PathFragment pathFragment = create("a/../b");
663
664 assertThat(pathFragment.containsUplevelReferences()).isFalse();
665 assertThat(pathFragment.getPathString()).isEqualTo("b");
666 }
667
668 @Test
669 public void containsUplevelReferenes_uplevelReferenceMidGlobalPath_normalizesAndReturnsFalse() {
670 PathFragment pathFragment = create("/dir1/dir2/../file");
671
672 assertThat(pathFragment.containsUplevelReferences()).isFalse();
673 assertThat(pathFragment.getPathString()).isEqualTo("/dir1/file");
674 }
Han-Wen Nienhuysd08b27f2015-02-25 16:45:20 +0100675}